diff --git a/aws-qbusiness-application/aws-qbusiness-application.json b/aws-qbusiness-application/aws-qbusiness-application.json
index e5dc430..96d86eb 100755
--- a/aws-qbusiness-application/aws-qbusiness-application.json
+++ b/aws-qbusiness-application/aws-qbusiness-application.json
@@ -98,6 +98,18 @@
"EncryptionConfiguration": {
"$ref": "#/definitions/EncryptionConfiguration"
},
+ "IdentityCenterApplicationArn": {
+ "type": "string",
+ "maxLength": 1224,
+ "minLength": 10,
+ "pattern": "^arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):sso::\\d{12}:application/(sso)?ins-[a-zA-Z0-9-.]{16}/apl-[a-zA-Z0-9]{16}$"
+ },
+ "IdentityCenterInstanceArn": {
+ "type": "string",
+ "maxLength": 1224,
+ "minLength": 10,
+ "pattern": "^arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}$"
+ },
"RoleArn": {
"type": "string",
"maxLength": 1284,
@@ -128,9 +140,13 @@
"/properties/ApplicationArn",
"/properties/ApplicationId",
"/properties/CreatedAt",
+ "/properties/IdentityCenterApplicationArn",
"/properties/Status",
"/properties/UpdatedAt"
],
+ "writeOnlyProperties": [
+ "/properties/IdentityCenterInstanceArn"
+ ],
"createOnlyProperties": [
"/properties/EncryptionConfiguration"
],
@@ -146,7 +162,12 @@
"qbusiness:CreateApplication",
"qbusiness:GetApplication",
"qbusiness:ListTagsForResource",
- "qbusiness:TagResource"
+ "qbusiness:TagResource",
+ "sso:CreateApplication",
+ "sso:DeleteApplication",
+ "sso:PutApplicationAccessScope",
+ "sso:PutApplicationAuthenticationMethod",
+ "sso:PutApplicationGrant"
]
},
"read": {
@@ -162,14 +183,20 @@
"qbusiness:ListTagsForResource",
"qbusiness:TagResource",
"qbusiness:UntagResource",
- "qbusiness:UpdateApplication"
+ "qbusiness:UpdateApplication",
+ "sso:CreateApplication",
+ "sso:DeleteApplication",
+ "sso:PutApplicationAccessScope",
+ "sso:PutApplicationAuthenticationMethod",
+ "sso:PutApplicationGrant"
]
},
"delete": {
"permissions": [
"kms:RetireGrant",
"qbusiness:DeleteApplication",
- "qbusiness:GetApplication"
+ "qbusiness:GetApplication",
+ "sso:DeleteApplication"
]
},
"list": {
diff --git a/aws-qbusiness-application/pom.xml b/aws-qbusiness-application/pom.xml
index 2e4e189..b6ca5f6 100644
--- a/aws-qbusiness-application/pom.xml
+++ b/aws-qbusiness-application/pom.xml
@@ -55,19 +55,19 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
software.amazon.awssdk
aws-core
- 2.23.12
+ 2.25.42
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java
index 9a36350..92bbda0 100644
--- a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java
+++ b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java
@@ -18,6 +18,7 @@
import software.amazon.awssdk.services.qbusiness.model.TagResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.UntagResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdateApplicationRequest;
+import software.amazon.cloudformation.exceptions.CfnInvalidRequestException;
import software.amazon.cloudformation.proxy.ResourceHandlerRequest;
/**
@@ -36,10 +37,15 @@ public class Translator {
* @return awsRequest the aws service request to create a resource
*/
static CreateApplicationRequest translateToCreateRequest(final String idempotentToken, final ResourceModel model) {
+ // https://w.amazon.com/bin/view/AWS21/Design/Uluru/Onboarding_Guide/ModelingGuidelines#HRequiredWriteOnlyProperties
+ if (model.getIdentityCenterInstanceArn() == null) {
+ throw new CfnInvalidRequestException("IdentityCenterInstanceArn is required.");
+ }
return CreateApplicationRequest.builder()
.clientToken(idempotentToken)
.displayName(model.getDisplayName())
.roleArn(model.getRoleArn())
+ .identityCenterInstanceArn(model.getIdentityCenterInstanceArn())
.description(model.getDescription())
.encryptionConfiguration(toServiceEncryptionConfig(model.getEncryptionConfiguration()))
.attachmentsConfiguration(toServiceAttachmentConfiguration(model.getAttachmentsConfiguration()))
@@ -79,6 +85,7 @@ static ResourceModel translateFromReadResponse(final GetApplicationResponse awsR
.applicationId(awsResponse.applicationId())
.applicationArn(awsResponse.applicationArn())
.roleArn(awsResponse.roleArn())
+ .identityCenterApplicationArn(awsResponse.identityCenterApplicationArn())
.status(awsResponse.statusAsString())
.description(awsResponse.description())
.createdAt(instantToString(awsResponse.createdAt()))
@@ -176,6 +183,7 @@ static UpdateApplicationRequest translateToUpdateRequest(final ResourceModel mod
.displayName(model.getDisplayName())
.description(model.getDescription())
.roleArn(model.getRoleArn())
+ .identityCenterInstanceArn(model.getIdentityCenterInstanceArn())
.attachmentsConfiguration(toServiceAttachmentConfiguration(model.getAttachmentsConfiguration()))
.build();
}
@@ -203,6 +211,10 @@ static List translateFromListResponse(final ListApplicationsRespo
.stream()
.map(application -> ResourceModel.builder()
.applicationId(application.applicationId())
+ .displayName(application.displayName())
+ .createdAt(instantToString(application.createdAt()))
+ .updatedAt(instantToString(application.updatedAt()))
+ .status(application.statusAsString())
.build()
)
.toList();
diff --git a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Utils.java b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Utils.java
index 3e1a503..a7249c4 100644
--- a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Utils.java
+++ b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Utils.java
@@ -22,7 +22,6 @@ public static String buildApplicationArn(final ResourceHandlerRequestbuilder()
diff --git a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java
index 4c2c01e..bdf09bc 100644
--- a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java
+++ b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java
@@ -106,6 +106,7 @@ public void handleRequest_SimpleSuccess() {
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.description("this is a description, there are many like it but this one is mine.")
.displayName("Foobar")
+ .identityCenterApplicationArn("arn:aws:sso::123456789012:application/ssoins/apl")
.status(ApplicationStatus.ACTIVE)
.encryptionConfiguration(EncryptionConfiguration.builder()
.kmsKeyId("keyblade")
@@ -141,6 +142,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultModel.getApplicationId()).isEqualTo(APP_ID);
assertThat(resultModel.getApplicationArn()).isEqualTo("this-is-an-arn-there-are-many-like-it-but-this-one-is-mine");
assertThat(resultModel.getRoleArn()).isEqualTo("role1");
+ assertThat(resultModel.getIdentityCenterApplicationArn()).isEqualTo("arn:aws:sso::123456789012:application/ssoins/apl");
assertThat(resultModel.getCreatedAt()).isEqualTo("2023-10-20T18:02:15Z");
assertThat(resultModel.getUpdatedAt()).isEqualTo("2023-10-20T22:02:15Z");
assertThat(resultModel.getDescription()).isEqualTo("this is a description, there are many like it but this one is mine.");
diff --git a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/UpdateHandlerTest.java b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/UpdateHandlerTest.java
index e24dfe0..a47a958 100644
--- a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/UpdateHandlerTest.java
+++ b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/UpdateHandlerTest.java
@@ -92,6 +92,7 @@ public void setup() {
.attachmentsControlMode(AttachmentsControlMode.DISABLED.toString())
.build()
)
+ .identityCenterInstanceArn("arn:aws:sso:::instance/before")
.tags(List.of(
Tag.builder().key("remain").value("thesame").build(),
Tag.builder().key("toremove").value("nolongerthere").build(),
@@ -108,6 +109,7 @@ public void setup() {
.attachmentsControlMode(AttachmentsControlMode.ENABLED.toString())
.build()
)
+ .identityCenterInstanceArn("arn:aws:sso:::instance/after")
.tags(List.of(
Tag.builder().key("remain").value("thesame").build(),
Tag.builder().key("iwillchange").value("nowanewvalue").build(),
@@ -179,6 +181,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(updateAppRequest.displayName()).isEqualTo("New Phone Who dis");
assertThat(updateAppRequest.description()).isEqualTo("It's a new description");
assertThat(updateAppRequest.roleArn()).isEqualTo("now-better-role");
+ assertThat(updateAppRequest.identityCenterInstanceArn()).isEqualTo("arn:aws:sso:::instance/after");
assertThat(updateAppRequest.attachmentsConfiguration()).isEqualTo(software.amazon.awssdk.services.qbusiness.model.AttachmentsConfiguration.builder()
.attachmentsControlMode(AttachmentsControlMode.ENABLED)
.build());
diff --git a/aws-qbusiness-datasource/aws-qbusiness-datasource.json b/aws-qbusiness-datasource/aws-qbusiness-datasource.json
index 05a95b3..81069a4 100755
--- a/aws-qbusiness-datasource/aws-qbusiness-datasource.json
+++ b/aws-qbusiness-datasource/aws-qbusiness-datasource.json
@@ -346,6 +346,8 @@
}
},
"required": [
+ "ApplicationId",
+ "IndexId",
"Configuration",
"DisplayName"
],
diff --git a/aws-qbusiness-datasource/pom.xml b/aws-qbusiness-datasource/pom.xml
index f476d2c..3379fcf 100644
--- a/aws-qbusiness-datasource/pom.xml
+++ b/aws-qbusiness-datasource/pom.xml
@@ -30,13 +30,13 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-index/aws-qbusiness-index.json b/aws-qbusiness-index/aws-qbusiness-index.json
index 4a9d4c9..aba7ec1 100755
--- a/aws-qbusiness-index/aws-qbusiness-index.json
+++ b/aws-qbusiness-index/aws-qbusiness-index.json
@@ -1,7 +1,6 @@
{
"typeName": "AWS::QBusiness::Index",
"description": "Definition of AWS::QBusiness::Index Resource Type",
- "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-qbusiness",
"definitions": {
"AttributeType": {
"type": "string",
@@ -17,8 +16,9 @@
"properties": {
"Name": {
"type": "string",
- "maxLength": 2048,
- "minLength": 1
+ "maxLength": 30,
+ "minLength": 1,
+ "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_-]*$"
},
"Type": {
"$ref": "#/definitions/AttributeType"
@@ -58,6 +58,13 @@
"UPDATING"
]
},
+ "IndexType": {
+ "type": "string",
+ "enum": [
+ "ENTERPRISE",
+ "STARTER"
+ ]
+ },
"Status": {
"type": "string",
"enum": [
@@ -98,10 +105,6 @@
}
},
"additionalProperties": false
- },
- "Unit": {
- "type": "object",
- "additionalProperties": false
}
},
"properties": {
@@ -154,6 +157,9 @@
"IndexStatistics": {
"$ref": "#/definitions/IndexStatistics"
},
+ "Type": {
+ "$ref": "#/definitions/IndexType"
+ },
"Status": {
"$ref": "#/definitions/IndexStatus"
},
@@ -172,6 +178,7 @@
}
},
"required": [
+ "ApplicationId",
"DisplayName"
],
"readOnlyProperties": [
@@ -183,7 +190,8 @@
"/properties/UpdatedAt"
],
"createOnlyProperties": [
- "/properties/ApplicationId"
+ "/properties/ApplicationId",
+ "/properties/Type"
],
"primaryIdentifier": [
"/properties/ApplicationId",
@@ -235,5 +243,9 @@
}
}
},
+ "tagging": {
+ "taggable": true
+ },
+ "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-qbusiness",
"additionalProperties": false
}
diff --git a/aws-qbusiness-index/pom.xml b/aws-qbusiness-index/pom.xml
index 1dd34b4..5d14d8b 100644
--- a/aws-qbusiness-index/pom.xml
+++ b/aws-qbusiness-index/pom.xml
@@ -37,13 +37,13 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-index/src/main/java/software/amazon/qbusiness/index/Translator.java b/aws-qbusiness-index/src/main/java/software/amazon/qbusiness/index/Translator.java
index 2261ba3..0c530fe 100644
--- a/aws-qbusiness-index/src/main/java/software/amazon/qbusiness/index/Translator.java
+++ b/aws-qbusiness-index/src/main/java/software/amazon/qbusiness/index/Translator.java
@@ -43,6 +43,7 @@ static CreateIndexRequest translateToCreateRequest(final String idempotentToken,
.displayName(model.getDisplayName())
.applicationId(model.getApplicationId())
.description(model.getDescription())
+ .type(model.getType())
.capacityConfiguration(toServiceCapacityConfiguration(model.getCapacityConfiguration()))
.tags(TagHelper.serviceTagsFromCfnTags(model.getTags()))
.build();
@@ -90,6 +91,7 @@ static ResourceModel translateFromReadResponse(final GetIndexResponse awsRespons
.indexStatistics(fromServiceIndexStatistics(awsResponse.indexStatistics()))
.status(awsResponse.statusAsString())
.description(awsResponse.description())
+ .type(awsResponse.typeAsString())
.documentAttributeConfigurations(fromServiceDocumentAttributeConfigurations(awsResponse.documentAttributeConfigurations()))
.createdAt(instantToString(awsResponse.createdAt()))
.updatedAt(instantToString(awsResponse.updatedAt()))
diff --git a/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/CreateHandlerTest.java b/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/CreateHandlerTest.java
index 4acfdf0..d47fa4a 100644
--- a/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/CreateHandlerTest.java
+++ b/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/CreateHandlerTest.java
@@ -30,10 +30,12 @@
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
import software.amazon.awssdk.services.qbusiness.model.AccessDeniedException;
+import software.amazon.awssdk.services.qbusiness.model.AttributeType;
import software.amazon.awssdk.services.qbusiness.model.ConflictException;
import software.amazon.awssdk.services.qbusiness.model.CreateIndexRequest;
import software.amazon.awssdk.services.qbusiness.model.CreateIndexResponse;
import software.amazon.awssdk.services.qbusiness.model.ErrorDetail;
+import software.amazon.awssdk.services.qbusiness.model.IndexType;
import software.amazon.awssdk.services.qbusiness.model.QBusinessException;
import software.amazon.awssdk.services.qbusiness.model.GetIndexRequest;
import software.amazon.awssdk.services.qbusiness.model.GetIndexResponse;
@@ -43,7 +45,10 @@
import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceResponse;
import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException;
import software.amazon.awssdk.services.qbusiness.model.ServiceQuotaExceededException;
+import software.amazon.awssdk.services.qbusiness.model.Status;
import software.amazon.awssdk.services.qbusiness.model.ThrottlingException;
+import software.amazon.awssdk.services.qbusiness.model.UpdateIndexRequest;
+import software.amazon.awssdk.services.qbusiness.model.UpdateIndexResponse;
import software.amazon.awssdk.services.qbusiness.model.ValidationException;
import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
@@ -96,6 +101,7 @@ public void setup() {
.description("A Description")
.applicationId(APP_ID)
.capacityConfiguration(new IndexCapacityConfiguration(10D))
+ .type(IndexType.ENTERPRISE.toString())
.build();
testRequest = ResourceHandlerRequest.builder()
@@ -132,6 +138,7 @@ public void handleRequest_SimpleSuccess() {
.createdAt(Instant.ofEpochMilli(1697824935000L))
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.status(IndexStatus.ACTIVE)
+ .type(IndexType.ENTERPRISE)
.description(createModel.getDescription())
.displayName(createModel.getDisplayName())
.capacityConfiguration(software.amazon.awssdk.services.qbusiness.model.IndexCapacityConfiguration.builder()
@@ -152,6 +159,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(model.getApplicationId()).isEqualTo(createModel.getApplicationId());
assertThat(model.getIndexId()).isEqualTo(createModel.getIndexId());
assertThat(model.getDescription()).isEqualTo(createModel.getDescription());
+ assertThat(model.getType()).isEqualTo(createModel.getType());
assertThat(model.getStatus()).isEqualTo(IndexStatus.ACTIVE.toString());
assertThat(model.getCapacityConfiguration().getUnits()).isEqualTo(createModel.getCapacityConfiguration().getUnits());
@@ -162,12 +170,65 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
verify(QBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
}
+ @Test
+ public void handleCreateRequestWithDocumentAttributeConfiguration() {
+ // set up scenario
+ when(QBusinessClient.createIndex(any(CreateIndexRequest.class)))
+ .thenReturn(CreateIndexResponse.builder()
+ .indexId(INDEX_ID)
+ .build()
+ );
+ when(QBusinessClient.listTagsForResource(any(ListTagsForResourceRequest.class))).thenReturn(ListTagsForResourceResponse.builder()
+ .tags(List.of())
+ .build());
+
+ var statusResponseBuilder = GetIndexResponse.builder()
+ .applicationId(APP_ID)
+ .indexId(INDEX_ID)
+ .type(IndexType.ENTERPRISE)
+ .createdAt(Instant.ofEpochMilli(1697824935000L))
+ .updatedAt(Instant.ofEpochMilli(1697839335000L))
+ .status(IndexStatus.ACTIVE);
+
+ when(QBusinessClient.getIndex(any(GetIndexRequest.class)))
+ .thenReturn(statusResponseBuilder.status(IndexStatus.ACTIVE).build())
+ .thenReturn(statusResponseBuilder.status(IndexStatus.UPDATING).build())
+ .thenReturn(statusResponseBuilder.status(IndexStatus.ACTIVE).build())
+ .thenReturn(statusResponseBuilder
+ .status(IndexStatus.ACTIVE)
+ .type(IndexType.ENTERPRISE)
+ .description(createModel.getDescription())
+ .displayName(createModel.getDisplayName())
+ .capacityConfiguration(software.amazon.awssdk.services.qbusiness.model.IndexCapacityConfiguration.builder()
+ .units(10)
+ .build())
+ .build());
+ createModel.setDocumentAttributeConfigurations(List.of(
+ DocumentAttributeConfiguration.builder()
+ .name("that-attrib")
+ .type(AttributeType.STRING.toString())
+ .search(Status.DISABLED.toString())
+ .build()
+ ));
+
+ // call method under test
+ final ProgressEvent resultProgress = underTest.handleRequest(
+ proxy, testRequest, new CallbackContext(), proxyClient, logger
+ );
+ assertThat(resultProgress).isNotNull();
+ assertThat(resultProgress.isSuccess()).isTrue();
+ verify(QBusinessClient).createIndex(any(CreateIndexRequest.class));
+ verify(QBusinessClient, times(2)).getIndex(any(GetIndexRequest.class));
+ verify(QBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
+ }
+
@Test
public void handleRequestFromProcessingStateToActive() {
// set up scenario
var getResponse = GetIndexResponse.builder()
.applicationId(APP_ID)
.indexId(INDEX_ID)
+ .type(IndexType.ENTERPRISE)
.createdAt(Instant.ofEpochMilli(1697824935000L))
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.description(createModel.getDescription())
@@ -219,6 +280,7 @@ public void testItFailsWithErrorMessageWhenGetReturnsFailStatus() {
.thenReturn(GetIndexResponse.builder()
.applicationId(APP_ID)
.indexId(INDEX_ID)
+ .type(IndexType.ENTERPRISE)
.createdAt(Instant.ofEpochMilli(1697824935000L))
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.status(IndexStatus.FAILED)
diff --git a/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/ReadHandlerTest.java b/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/ReadHandlerTest.java
index 61038c8..5168e62 100644
--- a/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/ReadHandlerTest.java
+++ b/aws-qbusiness-index/src/test/java/software/amazon/qbusiness/index/ReadHandlerTest.java
@@ -27,6 +27,7 @@
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
import software.amazon.awssdk.services.qbusiness.model.AccessDeniedException;
import software.amazon.awssdk.services.qbusiness.model.AttributeType;
+import software.amazon.awssdk.services.qbusiness.model.IndexType;
import software.amazon.awssdk.services.qbusiness.model.QBusinessException;
import software.amazon.awssdk.services.qbusiness.model.GetIndexRequest;
import software.amazon.awssdk.services.qbusiness.model.GetIndexResponse;
@@ -98,6 +99,7 @@ public void handleRequest_SimpleSuccess() {
.thenReturn(GetIndexResponse.builder()
.applicationId(APP_ID)
.indexId(INDEX_ID)
+ .type(IndexType.ENTERPRISE)
.createdAt(Instant.ofEpochMilli(1697824935000L))
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.description("This is a description of the index.")
@@ -144,6 +146,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultModel.getDisplayName()).isEqualTo("IndexName");
assertThat(resultModel.getApplicationId()).isEqualTo(APP_ID);
assertThat(resultModel.getIndexId()).isEqualTo(INDEX_ID);
+ assertThat(resultModel.getType()).isEqualTo(IndexType.ENTERPRISE.toString());
assertThat(resultModel.getCreatedAt()).isEqualTo("2023-10-20T18:02:15Z");
assertThat(resultModel.getUpdatedAt()).isEqualTo("2023-10-20T22:02:15Z");
assertThat(resultModel.getDescription()).isEqualTo("This is a description of the index.");
diff --git a/aws-qbusiness-plugin/aws-qbusiness-plugin.json b/aws-qbusiness-plugin/aws-qbusiness-plugin.json
index c1efd19..3ace575 100755
--- a/aws-qbusiness-plugin/aws-qbusiness-plugin.json
+++ b/aws-qbusiness-plugin/aws-qbusiness-plugin.json
@@ -2,6 +2,42 @@
"typeName": "AWS::QBusiness::Plugin",
"description": "Definition of AWS::QBusiness::Plugin Resource Type",
"definitions": {
+ "APISchema": {
+ "oneOf": [
+ {
+ "type": "object",
+ "title": "Payload",
+ "properties": {
+ "Payload": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "Payload"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "title": "S3",
+ "properties": {
+ "S3": {
+ "$ref": "#/definitions/S3"
+ }
+ },
+ "required": [
+ "S3"
+ ],
+ "additionalProperties": false
+ }
+ ]
+ },
+ "APISchemaType": {
+ "type": "string",
+ "enum": [
+ "OPEN_API_V3"
+ ]
+ },
"BasicAuthConfiguration": {
"type": "object",
"properties": {
@@ -24,6 +60,32 @@
],
"additionalProperties": false
},
+ "CustomPluginConfiguration": {
+ "type": "object",
+ "properties": {
+ "Description": {
+ "type": "string",
+ "maxLength": 200,
+ "minLength": 1
+ },
+ "ApiSchemaType": {
+ "$ref": "#/definitions/APISchemaType"
+ },
+ "ApiSchema": {
+ "$ref": "#/definitions/APISchema"
+ }
+ },
+ "required": [
+ "ApiSchema",
+ "ApiSchemaType",
+ "Description"
+ ],
+ "additionalProperties": false
+ },
+ "NoAuthConfiguration": {
+ "type": "object",
+ "additionalProperties": false
+ },
"OAuth2ClientCredentialConfiguration": {
"type": "object",
"properties": {
@@ -73,9 +135,34 @@
"OAuth2ClientCredentialConfiguration"
],
"additionalProperties": false
+ },
+ {
+ "type": "object",
+ "title": "NoAuthConfiguration",
+ "properties": {
+ "NoAuthConfiguration": {
+ "$ref": "#/definitions/NoAuthConfiguration"
+ }
+ },
+ "required": [
+ "NoAuthConfiguration"
+ ],
+ "additionalProperties": false
}
]
},
+ "PluginBuildStatus": {
+ "type": "string",
+ "enum": [
+ "READY",
+ "CREATE_IN_PROGRESS",
+ "CREATE_FAILED",
+ "UPDATE_IN_PROGRESS",
+ "UPDATE_FAILED",
+ "DELETE_IN_PROGRESS",
+ "DELETE_FAILED"
+ ]
+ },
"PluginState": {
"type": "string",
"enum": [
@@ -89,9 +176,31 @@
"SERVICE_NOW",
"SALESFORCE",
"JIRA",
- "ZENDESK"
+ "ZENDESK",
+ "CUSTOM"
]
},
+ "S3": {
+ "type": "object",
+ "properties": {
+ "Bucket": {
+ "type": "string",
+ "maxLength": 63,
+ "minLength": 1,
+ "pattern": "^[a-z0-9][\\.\\-a-z0-9]{1,61}[a-z0-9]$"
+ },
+ "Key": {
+ "type": "string",
+ "maxLength": 1024,
+ "minLength": 1
+ }
+ },
+ "required": [
+ "Bucket",
+ "Key"
+ ],
+ "additionalProperties": false
+ },
"Tag": {
"type": "object",
"properties": {
@@ -123,10 +232,16 @@
"AuthConfiguration": {
"$ref": "#/definitions/PluginAuthConfiguration"
},
+ "BuildStatus": {
+ "$ref": "#/definitions/PluginBuildStatus"
+ },
"CreatedAt": {
"type": "string",
"format": "date-time"
},
+ "CustomPluginConfiguration": {
+ "$ref": "#/definitions/CustomPluginConfiguration"
+ },
"DisplayName": {
"type": "string",
"maxLength": 100,
@@ -172,12 +287,13 @@
}
},
"required": [
+ "ApplicationId",
"AuthConfiguration",
"DisplayName",
- "ServerUrl",
"Type"
],
"readOnlyProperties": [
+ "/properties/BuildStatus",
"/properties/CreatedAt",
"/properties/PluginArn",
"/properties/PluginId",
diff --git a/aws-qbusiness-plugin/pom.xml b/aws-qbusiness-plugin/pom.xml
index ee3a77b..fecbac4 100644
--- a/aws-qbusiness-plugin/pom.xml
+++ b/aws-qbusiness-plugin/pom.xml
@@ -43,7 +43,7 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
@@ -90,7 +90,7 @@
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java
index 6cada98..d909f9b 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java
@@ -2,22 +2,32 @@
import software.amazon.cloudformation.exceptions.CfnGeneralServiceException;
+import java.util.Collections;
+import java.util.Map;
+
public class AuthConfigHelper {
public static PluginAuthConfiguration convertFromServiceAuthConfig(
software.amazon.awssdk.services.qbusiness.model.PluginAuthConfiguration serviceAuthConfig
) {
+
+ final PluginAuthConfiguration.PluginAuthConfigurationBuilder builder = PluginAuthConfiguration.builder();
+
if (serviceAuthConfig.oAuth2ClientCredentialConfiguration() != null) {
- return software.amazon.qbusiness.plugin.PluginAuthConfiguration.builder()
- .oAuth2ClientCredentialConfiguration(
- convertFromServiceOAuth(serviceAuthConfig.oAuth2ClientCredentialConfiguration()))
- .build();
+ builder.oAuth2ClientCredentialConfiguration(
+ convertFromServiceOAuth(serviceAuthConfig.oAuth2ClientCredentialConfiguration()));
}
- return software.amazon.qbusiness.plugin.PluginAuthConfiguration.builder()
- .basicAuthConfiguration(
- convertFromServiceBasicAuth(serviceAuthConfig.basicAuthConfiguration()))
- .build();
+ if (serviceAuthConfig.basicAuthConfiguration() != null) {
+ builder.basicAuthConfiguration(
+ convertFromServiceBasicAuth(serviceAuthConfig.basicAuthConfiguration()));
+ }
+
+ if (serviceAuthConfig.noAuthConfiguration() != null) {
+ builder.noAuthConfiguration(convertFromServiceNoAuth(serviceAuthConfig.noAuthConfiguration()));
+ }
+
+ return builder.build();
}
public static software.amazon.awssdk.services.qbusiness.model.PluginAuthConfiguration convertToServiceAuthConfig(
@@ -38,6 +48,12 @@ public static software.amazon.awssdk.services.qbusiness.model.PluginAuthConfigur
.basicAuthConfiguration(convertToServiceBasicAuth(cfnAuthConfig.getBasicAuthConfiguration()))
.build();
}
+
+ if (cfnAuthConfig.getNoAuthConfiguration() != null) {
+ return software.amazon.awssdk.services.qbusiness.model.PluginAuthConfiguration.builder()
+ .noAuthConfiguration(convertToServiceNoAuth(cfnAuthConfig.getNoAuthConfiguration()))
+ .build();
+ }
throw new CfnGeneralServiceException("Unknown auth configuration");
}
@@ -59,6 +75,12 @@ private static OAuth2ClientCredentialConfiguration convertFromServiceOAuth(
.build();
}
+ private static Map convertFromServiceNoAuth(
+ software.amazon.awssdk.services.qbusiness.model.NoAuthConfiguration serviceNoAuth
+ ) {
+ return Collections.emptyMap();
+ }
+
private static software.amazon.awssdk.services.qbusiness.model.BasicAuthConfiguration convertToServiceBasicAuth(
BasicAuthConfiguration cfnBasicAuth
) {
@@ -77,4 +99,11 @@ private static software.amazon.awssdk.services.qbusiness.model.OAuth2ClientCrede
.build();
}
+ private static software.amazon.awssdk.services.qbusiness.model.NoAuthConfiguration convertToServiceNoAuth(
+ Map cfnNoAuth
+ ) {
+ return software.amazon.awssdk.services.qbusiness.model.NoAuthConfiguration.builder()
+ .build();
+ }
+
}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/BaseHandlerStd.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/BaseHandlerStd.java
index 63688f7..1276ae5 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/BaseHandlerStd.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/BaseHandlerStd.java
@@ -4,6 +4,10 @@
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
import software.amazon.awssdk.services.qbusiness.model.AccessDeniedException;
import software.amazon.awssdk.services.qbusiness.model.ConflictException;
+import software.amazon.awssdk.services.qbusiness.model.GetDataSourceRequest;
+import software.amazon.awssdk.services.qbusiness.model.GetDataSourceResponse;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginRequest;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginResponse;
import software.amazon.awssdk.services.qbusiness.model.QBusinessRequest;
import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceResponse;
@@ -89,5 +93,17 @@ protected ProgressEvent handleError(
return ProgressEvent.failed(resourceModel, context, cfnException.getErrorCode(), cfnException.getMessage());
}
+ protected GetPluginResponse getPlugin(ResourceModel model, ProxyClient proxyClient) {
+ var request = GetPluginRequest.builder()
+ .applicationId(model.getApplicationId())
+ .pluginId(model.getPluginId())
+ .build();
+ return callGetPlugin(request, proxyClient);
+ }
+
+ protected GetPluginResponse callGetPlugin(GetPluginRequest request, ProxyClient proxyClient) {
+ var client = proxyClient.client();
+ return proxyClient.injectCredentialsAndInvokeV2(request, client::getPlugin);
+ }
}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CreateHandler.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CreateHandler.java
index 81abdeb..1cdb9df 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CreateHandler.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CreateHandler.java
@@ -1,10 +1,19 @@
package software.amazon.qbusiness.plugin;
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
+import software.amazon.awssdk.services.qbusiness.model.ApplicationStatus;
import software.amazon.awssdk.services.qbusiness.model.CreatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.CreatePluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.DataSourceStatus;
+import software.amazon.awssdk.services.qbusiness.model.GetApplicationRequest;
+import software.amazon.awssdk.services.qbusiness.model.GetApplicationResponse;
+import software.amazon.awssdk.services.qbusiness.model.GetDataSourceResponse;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.InternalServerException;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginResponse;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.Logger;
import software.amazon.cloudformation.proxy.ProgressEvent;
@@ -13,6 +22,7 @@
import software.amazon.cloudformation.proxy.delay.Constant;
import java.time.Duration;
+import java.util.Objects;
import static software.amazon.qbusiness.plugin.Constants.API_CREATE_PLUGIN;
import static software.amazon.qbusiness.plugin.Constants.API_UPDATE_PLUGIN;
@@ -54,6 +64,7 @@ protected ProgressEvent handleRequest(
.translateToServiceRequest(model -> Translator.translateToCreateRequest(model, request.getClientRequestToken()))
.backoffDelay(backOffStrategy)
.makeServiceCall((awsRequest, clientProxyClient) -> callCreatePlugin(awsRequest, clientProxyClient, progress.getResourceModel()))
+ .stabilize((createReq, createResponse, client, model, context) -> isStabilized(request, client, model, logger))
.handleError((createPluginRequest, error, client, model, context) ->
handleError(createPluginRequest, model, error, context, logger, API_CREATE_PLUGIN))
.progress()
@@ -91,4 +102,39 @@ private UpdatePluginResponse callUpdatePlugin(
) {
return client.injectCredentialsAndInvokeV2(request, client.client()::updatePlugin);
}
+
+ private boolean isStabilized(
+ final ResourceHandlerRequest request,
+ ProxyClient proxyClient,
+ ResourceModel model,
+ Logger logger
+ ) {
+ logger.log("[INFO] Checking for Create Complete for Plugin process in stack: %s with ID: %s, For Account: %s, Application: %s"
+ .formatted(request.getStackId(), model.getPluginId(), request.getAwsAccountId(), model.getApplicationId())
+ );
+
+ GetPluginResponse getPluginRes = getPlugin(model, proxyClient);
+ var status = getPluginRes.buildStatus();
+
+ if (PluginBuildStatus.READY.equals(status)) {
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s has stabilized".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+
+ return true;
+ }
+
+ if (PluginBuildStatus.CREATE_IN_PROGRESS.equals(status)) {
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s is still stabilizing".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+ return false;
+ }
+
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s has failed to stabilize".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+
+ throw new CfnNotStabilizedException(ResourceModel.TYPE_NAME, model.getPluginId(), null);
+ }
}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CustomPluginConfigHelper.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CustomPluginConfigHelper.java
new file mode 100644
index 0000000..5a7f266
--- /dev/null
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/CustomPluginConfigHelper.java
@@ -0,0 +1,83 @@
+package software.amazon.qbusiness.plugin;
+
+import org.apache.commons.lang3.StringUtils;
+import software.amazon.cloudformation.exceptions.CfnGeneralServiceException;
+
+public class CustomPluginConfigHelper {
+
+ public static CustomPluginConfiguration convertFromServiceCustomPluginConfig(
+ software.amazon.awssdk.services.qbusiness.model.CustomPluginConfiguration customPluginConfig
+ ) {
+ if (customPluginConfig == null) {
+ return null;
+ }
+
+ return CustomPluginConfiguration.builder()
+ .apiSchemaType(customPluginConfig.apiSchemaTypeAsString())
+ .apiSchema(convertFromServiceApiSchema(customPluginConfig.apiSchema()))
+ .description(customPluginConfig.description())
+ .build();
+ }
+
+ public static software.amazon.awssdk.services.qbusiness.model.CustomPluginConfiguration convertToServiceCustomPluginConfig(
+ CustomPluginConfiguration customPluginConfig
+ ) {
+ if (customPluginConfig == null) {
+ return null;
+ }
+
+ return software.amazon.awssdk.services.qbusiness.model.CustomPluginConfiguration.builder()
+ .apiSchemaType(customPluginConfig.getApiSchemaType())
+ .apiSchema(convertToServiceApiSchema(customPluginConfig.getApiSchema()))
+ .description(customPluginConfig.getDescription())
+ .build();
+ }
+
+ public static APISchema convertFromServiceApiSchema(
+ software.amazon.awssdk.services.qbusiness.model.APISchema apiSchema
+ ) {
+ if (apiSchema == null) {
+ return null;
+ }
+
+ final APISchema.APISchemaBuilder builder = APISchema.builder();
+ if (StringUtils.isNotBlank(apiSchema.payload())) {
+ builder.payload(apiSchema.payload());
+ }
+
+ if (apiSchema.s3() != null) {
+ builder.s3(S3.builder()
+ .bucket(apiSchema.s3().bucket())
+ .key(apiSchema.s3().key())
+ .build());
+ }
+
+ return builder.build();
+ }
+
+ public static software.amazon.awssdk.services.qbusiness.model.APISchema convertToServiceApiSchema(
+ APISchema apiSchema
+ ) {
+ if (apiSchema == null) {
+ return null;
+ }
+
+ if (apiSchema.getPayload() != null) {
+ return software.amazon.awssdk.services.qbusiness.model.APISchema.builder()
+ .payload(apiSchema.getPayload())
+ .build();
+ }
+
+ if (apiSchema.getS3() != null) {
+ return software.amazon.awssdk.services.qbusiness.model.APISchema.builder()
+ .s3(software.amazon.awssdk.services.qbusiness.model.S3.builder()
+ .bucket(apiSchema.getS3().getBucket())
+ .key(apiSchema.getS3().getKey())
+ .build())
+ .build();
+ }
+
+ throw new CfnGeneralServiceException("Unknown Api Schema");
+ }
+
+}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/DeleteHandler.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/DeleteHandler.java
index 437e277..9070c1d 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/DeleteHandler.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/DeleteHandler.java
@@ -3,6 +3,10 @@
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
import software.amazon.awssdk.services.qbusiness.model.DeletePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.DeletePluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
+import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.Logger;
import software.amazon.cloudformation.proxy.ProgressEvent;
@@ -31,6 +35,7 @@ protected ProgressEvent handleRequest(
proxy.initiate("AWS-QBusiness-Retriever::Delete", proxyClient, progress.getResourceModel(), progress.getCallbackContext())
.translateToServiceRequest(Translator::translateToDeleteRequest)
.makeServiceCall(this::callDeleteRetriever)
+ .stabilize((deleteReq, deleteRes, client, model, context) -> isDoneDeleting(client, model))
.handleError((deleteRetrieverRequest, error, client, model, context) ->
handleError(deleteRetrieverRequest, model, error, context, logger, API_DELETE_PLUGIN))
.progress()
@@ -42,4 +47,28 @@ protected DeletePluginResponse callDeleteRetriever(DeletePluginRequest request,
return client.injectCredentialsAndInvokeV2(request, client.client()::deletePlugin);
}
+ private boolean isDoneDeleting(
+ ProxyClient proxyClient,
+ ResourceModel model
+ ) {
+ try {
+ GetPluginResponse getPluginRes = getPlugin(model, proxyClient);
+ var status = getPluginRes.buildStatus();
+ if (!PluginBuildStatus.DELETE_FAILED.equals(status)) {
+ logger.log("[INFO] Delete of %s still stabilizing for Resource id: %s, application: %s"
+ .formatted(ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId()));
+ return false;
+ } else {
+ logger.log("[INFO] %s with ID: %s, for App: %s, has failed to stabilize".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId()
+ ));
+ throw new CfnNotStabilizedException(ResourceModel.TYPE_NAME, model.getPluginId(), null);
+ }
+ } catch (ResourceNotFoundException e) {
+ logger.log("[INFO] Delete process of %s has stabilized for Resource id: %s, application: %s"
+ .formatted(ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId()));
+ return true;
+ }
+ }
+
}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/ReadHandler.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/ReadHandler.java
index fedac25..78fef99 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/ReadHandler.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/ReadHandler.java
@@ -49,9 +49,4 @@ protected ProgressEvent handleRequest(
)
);
}
-
- protected GetPluginResponse callGetPlugin(GetPluginRequest request, ProxyClient client) {
- return client.injectCredentialsAndInvokeV2(request, client.client()::getPlugin);
- }
-
}
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java
index 2daed6a..b9db0e3 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java
@@ -41,6 +41,7 @@ static CreatePluginRequest translateToCreateRequest(final ResourceModel model, f
.type(model.getType())
.serverUrl(model.getServerUrl())
.authConfiguration(AuthConfigHelper.convertToServiceAuthConfig(model.getAuthConfiguration()))
+ .customPluginConfiguration(CustomPluginConfigHelper.convertToServiceCustomPluginConfig(model.getCustomPluginConfiguration()))
.clientToken(idempotenceToken)
.tags(TagHelper.serviceTagsFromCfnTags(model.getTags()))
.build();
@@ -83,6 +84,8 @@ static ResourceModel translateFromReadResponse(final GetPluginResponse awsRespon
.serverUrl(awsResponse.serverUrl())
.authConfiguration(AuthConfigHelper.convertFromServiceAuthConfig(awsResponse.authConfiguration()))
.state(awsResponse.stateAsString())
+ .buildStatus(awsResponse.buildStatusAsString())
+ .customPluginConfiguration(CustomPluginConfigHelper.convertFromServiceCustomPluginConfig(awsResponse.customPluginConfiguration()))
.createdAt(instantToString(awsResponse.createdAt()))
.updatedAt(instantToString(awsResponse.updatedAt()))
.build();
@@ -114,6 +117,7 @@ static UpdatePluginRequest translateToUpdateRequest(final ResourceModel model) {
.displayName(model.getDisplayName())
.serverUrl(model.getServerUrl())
.authConfiguration(AuthConfigHelper.convertToServiceAuthConfig(model.getAuthConfiguration()))
+ .customPluginConfiguration(CustomPluginConfigHelper.convertToServiceCustomPluginConfig(model.getCustomPluginConfiguration()))
.state(model.getState())
.build();
}
@@ -147,6 +151,7 @@ static List translateFromListResponse(final String applicationId,
.type(plugin.type().toString())
.serverUrl(plugin.serverUrl())
.state(plugin.stateAsString())
+ .buildStatus(plugin.buildStatusAsString())
.createdAt(instantToString(plugin.createdAt()))
.updatedAt(instantToString(plugin.updatedAt()))
.build())
diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java
index 88c4efe..51a8290 100644
--- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java
+++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java
@@ -2,12 +2,15 @@
import org.apache.commons.collections.CollectionUtils;
import software.amazon.awssdk.services.qbusiness.QBusinessClient;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
import software.amazon.awssdk.services.qbusiness.model.TagResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.TagResourceResponse;
import software.amazon.awssdk.services.qbusiness.model.UntagResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.UntagResourceResponse;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginResponse;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.Logger;
import software.amazon.cloudformation.proxy.ProgressEvent;
@@ -61,6 +64,7 @@ protected ProgressEvent handleRequest(
.translateToServiceRequest(Translator::translateToUpdateRequest)
.backoffDelay(backOffStrategy)
.makeServiceCall(this::callUpdatePlugin)
+ .stabilize((updateReq, updateResponse, client, model, context) -> isStabilized(request, client, model, logger))
.handleError((describeApplicationRequest, error, client, model, context) ->
handleError(describeApplicationRequest, model, error, context, logger, API_UPDATE_PLUGIN))
.progress())
@@ -127,4 +131,39 @@ private UntagResourceResponse callUntagResource(UntagResourceRequest request, Pr
return proxyClient.injectCredentialsAndInvokeV2(request, client::untagResource);
}
+ private boolean isStabilized(
+ final ResourceHandlerRequest request,
+ ProxyClient proxyClient,
+ ResourceModel model,
+ Logger logger
+ ) {
+ logger.log("[INFO] Checking for Update Complete for Plugin process in stack: %s with ID: %s, For Account: %s, Application: %s"
+ .formatted(request.getStackId(), model.getPluginId(), request.getAwsAccountId(), model.getApplicationId())
+ );
+
+ GetPluginResponse getPluginRes = getPlugin(model, proxyClient);
+ var status = getPluginRes.buildStatus();
+
+ if (PluginBuildStatus.READY.equals(status)) {
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s has stabilized".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+
+ return true;
+ }
+
+ if (PluginBuildStatus.UPDATE_IN_PROGRESS.equals(status)) {
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s is still stabilizing".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+ return false;
+ }
+
+ logger.log("[INFO] %s with ID: %s, for App: %s, stack ID: %s has failed to stabilize".formatted(
+ ResourceModel.TYPE_NAME, model.getPluginId(), model.getApplicationId(), request.getStackId()
+ ));
+
+ throw new CfnNotStabilizedException(ResourceModel.TYPE_NAME, model.getPluginId(), null);
+ }
+
}
diff --git a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/CreateHandlerTest.java b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/CreateHandlerTest.java
index 1bc9b4c..c4f8693 100644
--- a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/CreateHandlerTest.java
+++ b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/CreateHandlerTest.java
@@ -1,9 +1,11 @@
package software.amazon.qbusiness.plugin;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -28,6 +30,7 @@
import software.amazon.awssdk.services.qbusiness.model.ConflictException;
import software.amazon.awssdk.services.qbusiness.model.CreatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.CreatePluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
import software.amazon.awssdk.services.qbusiness.model.QBusinessException;
import software.amazon.awssdk.services.qbusiness.model.GetApplicationRequest;
import software.amazon.awssdk.services.qbusiness.model.GetDataSourceRequest;
@@ -42,6 +45,7 @@
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginResponse;
import software.amazon.awssdk.services.qbusiness.model.ValidationException;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.OperationStatus;
@@ -107,6 +111,7 @@ public void setup() {
.displayName(PLUGIN_NAME)
.type(PLUGIN_TYPE)
.state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY.toString())
.serverUrl(SERVER_URL)
.authConfiguration(serviceAuthConfiguration)
.createdAt(Instant.ofEpochMilli(CREATED_TIME).toString())
@@ -147,6 +152,7 @@ public void handleRequest_SimpleSuccess() {
.displayName(PLUGIN_NAME)
.type(PLUGIN_TYPE)
.state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
.serverUrl(SERVER_URL)
.authConfiguration(cfnAuthConfiguration)
.createdAt(Instant.ofEpochMilli(CREATED_TIME))
@@ -164,7 +170,7 @@ public void handleRequest_SimpleSuccess() {
final ProgressEvent response = underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
verify(qBusinessClient).createPlugin(any(CreatePluginRequest.class));
- verify(qBusinessClient).getPlugin(any(GetPluginRequest.class));
+ verify(qBusinessClient, times(2)).getPlugin(any(GetPluginRequest.class));
verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
verify(qBusinessClient).updatePlugin(
argThat(
@@ -188,12 +194,116 @@ public void handleRequest_SimpleSuccess() {
assertThat(resultModel.getPluginId()).isEqualTo(PLUGIN_ID);
assertThat(resultModel.getType()).isEqualTo(PLUGIN_TYPE);
assertThat(resultModel.getState()).isEqualTo(PLUGIN_STATE);
+ assertThat(resultModel.getBuildStatus()).isEqualTo(PluginBuildStatus.READY.toString());
assertThat(resultModel.getDisplayName()).isEqualTo(PLUGIN_NAME);
assertThat(resultModel.getAuthConfiguration()).isEqualTo(serviceAuthConfiguration);
assertThat(resultModel.getCreatedAt()).isEqualTo(Instant.ofEpochMilli(CREATED_TIME).toString());
assertThat(resultModel.getUpdatedAt()).isEqualTo(Instant.ofEpochMilli(UPDATED_TIME).toString());
}
+ @Test
+ public void handleRequest_StabilizeFromCreateInProgressToReady() {
+
+ when(proxyClient.client().createPlugin(any(CreatePluginRequest.class)))
+ .thenReturn(CreatePluginResponse.builder()
+ .pluginId(PLUGIN_ID)
+ .build());
+ when(proxyClient.client().getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.CREATE_IN_PROGRESS)
+ .serverUrl(SERVER_URL)
+ .authConfiguration(cfnAuthConfiguration)
+ .createdAt(Instant.ofEpochMilli(CREATED_TIME))
+ .updatedAt(Instant.ofEpochMilli(UPDATED_TIME))
+ .build())
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(SERVER_URL)
+ .authConfiguration(cfnAuthConfiguration)
+ .createdAt(Instant.ofEpochMilli(CREATED_TIME))
+ .updatedAt(Instant.ofEpochMilli(UPDATED_TIME))
+ .build());
+ when(qBusinessClient.updatePlugin(any(UpdatePluginRequest.class))).thenReturn(UpdatePluginResponse.builder().build());
+ when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class)))
+ .thenReturn(ListTagsForResourceResponse.builder()
+ .tags(List.of(software.amazon.awssdk.services.qbusiness.model.Tag.builder()
+ .key("Tag 1")
+ .value("Tag 2")
+ .build()))
+ .build());
+
+ final ProgressEvent response = underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ verify(qBusinessClient).createPlugin(any(CreatePluginRequest.class));
+ verify(qBusinessClient, times(3)).getPlugin(any(GetPluginRequest.class));
+ verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
+ verify(qBusinessClient).updatePlugin(
+ argThat(
+ (ArgumentMatcher) t -> t.stateAsString().equals(PLUGIN_STATE) &&
+ t.applicationId().equals(APPLICATION_ID) &&
+ t.pluginId().equals(PLUGIN_ID)
+ )
+ );
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
+ assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
+ assertThat(response.getResourceModel()).isEqualTo(request.getDesiredResourceState());
+ assertThat(response.getResourceModels()).isNull();
+ assertThat(response.getMessage()).isNull();
+ assertThat(response.getErrorCode()).isNull();
+
+ ResourceModel resultModel = response.getResourceModel();
+
+ assertThat(resultModel.getApplicationId()).isEqualTo(APPLICATION_ID);
+ assertThat(resultModel.getPluginId()).isEqualTo(PLUGIN_ID);
+ assertThat(resultModel.getType()).isEqualTo(PLUGIN_TYPE);
+ assertThat(resultModel.getState()).isEqualTo(PLUGIN_STATE);
+ assertThat(resultModel.getBuildStatus()).isEqualTo(PluginBuildStatus.READY.toString());
+ assertThat(resultModel.getDisplayName()).isEqualTo(PLUGIN_NAME);
+ assertThat(resultModel.getAuthConfiguration()).isEqualTo(serviceAuthConfiguration);
+ assertThat(resultModel.getCreatedAt()).isEqualTo(Instant.ofEpochMilli(CREATED_TIME).toString());
+ assertThat(resultModel.getUpdatedAt()).isEqualTo(Instant.ofEpochMilli(UPDATED_TIME).toString());
+ }
+
+ @Test
+ public void handleRequest_ThrowsExpectedErrorWhenStabilizationFails() {
+
+ when(proxyClient.client().createPlugin(any(CreatePluginRequest.class)))
+ .thenReturn(CreatePluginResponse.builder()
+ .pluginId(PLUGIN_ID)
+ .build());
+ when(proxyClient.client().getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.CREATE_FAILED)
+ .serverUrl(SERVER_URL)
+ .authConfiguration(cfnAuthConfiguration)
+ .createdAt(Instant.ofEpochMilli(CREATED_TIME))
+ .updatedAt(Instant.ofEpochMilli(UPDATED_TIME))
+ .build());
+
+ assertThatThrownBy(() -> underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger))
+ .isInstanceOf(CfnNotStabilizedException.class);
+
+ verify(qBusinessClient).createPlugin(any(CreatePluginRequest.class));
+ verify(qBusinessClient).getPlugin(any(GetPluginRequest.class));
+ }
+
@Test
public void testThatItDoesNotCallUpdatePluginIfStateIsNotSet() {
// set up
@@ -210,6 +320,7 @@ public void testThatItDoesNotCallUpdatePluginIfStateIsNotSet() {
.displayName(PLUGIN_NAME)
.type(PLUGIN_TYPE)
.state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
.serverUrl(SERVER_URL)
.authConfiguration(cfnAuthConfiguration)
.createdAt(Instant.ofEpochMilli(CREATED_TIME))
@@ -225,7 +336,7 @@ public void testThatItDoesNotCallUpdatePluginIfStateIsNotSet() {
// verify results
verify(qBusinessClient).createPlugin(any(CreatePluginRequest.class));
- verify(qBusinessClient).getPlugin(any(GetPluginRequest.class));
+ verify(qBusinessClient, times(2)).getPlugin(any(GetPluginRequest.class));
verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
assertThat(response).isNotNull();
diff --git a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/DeleteHandlerTest.java b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/DeleteHandlerTest.java
index 799ed2b..eb4b1ef 100644
--- a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/DeleteHandlerTest.java
+++ b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/DeleteHandlerTest.java
@@ -1,9 +1,11 @@
package software.amazon.qbusiness.plugin;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -26,11 +28,16 @@
import software.amazon.awssdk.services.qbusiness.model.ConflictException;
import software.amazon.awssdk.services.qbusiness.model.DeletePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.DeletePluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.GetDataSourceRequest;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginRequest;
+import software.amazon.awssdk.services.qbusiness.model.GetPluginResponse;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
import software.amazon.awssdk.services.qbusiness.model.QBusinessException;
import software.amazon.awssdk.services.qbusiness.model.InternalServerException;
import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException;
import software.amazon.awssdk.services.qbusiness.model.ThrottlingException;
import software.amazon.awssdk.services.qbusiness.model.ValidationException;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.OperationStatus;
@@ -93,10 +100,12 @@ public void handleRequest_SimpleSuccess() {
when(proxyClient.client().deletePlugin(any(DeletePluginRequest.class)))
.thenReturn(DeletePluginResponse.builder().build());
+ when(proxyClient.client().getPlugin(any(GetPluginRequest.class))).thenThrow(ResourceNotFoundException.builder().build());
final ProgressEvent response = underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
verify(qBusinessClient).deletePlugin(any(DeletePluginRequest.class));
+ verify(qBusinessClient).getPlugin(any(GetPluginRequest.class));
assertThat(response).isNotNull();
assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
@@ -114,6 +123,44 @@ public void handleRequest_SimpleSuccess() {
}
+ @Test
+ public void handleRequest_StabilizeFromDeleteInProgressToDeleted() {
+
+ when(proxyClient.client().deletePlugin(any(DeletePluginRequest.class)))
+ .thenReturn(DeletePluginResponse.builder().build());
+ when(proxyClient.client().getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .buildStatus(PluginBuildStatus.DELETE_IN_PROGRESS)
+ .build())
+ .thenThrow(ResourceNotFoundException.builder().build());
+
+ final ProgressEvent response = underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ verify(qBusinessClient).deletePlugin(any(DeletePluginRequest.class));
+ verify(qBusinessClient, times(2)).getPlugin(any(GetPluginRequest.class));
+ }
+
+ @Test
+ public void handleRequest_ThrowsExpectedErrorWhenStabilizationFails() {
+
+ when(proxyClient.client().deletePlugin(any(DeletePluginRequest.class)))
+ .thenReturn(DeletePluginResponse.builder().build());
+ when(proxyClient.client().getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .buildStatus(PluginBuildStatus.DELETE_FAILED)
+ .build());
+
+ assertThatThrownBy(() -> underTest.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger))
+ .isInstanceOf(CfnNotStabilizedException.class);;
+
+ verify(qBusinessClient).deletePlugin(any(DeletePluginRequest.class));
+ verify(qBusinessClient, times(1)).getPlugin(any(GetPluginRequest.class));
+ }
+
private static Stream serviceErrorAndHandlerCodes() {
return Stream.of(
Arguments.of(ValidationException.builder().build(), HandlerErrorCode.InvalidRequest),
diff --git a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/UpdateHandlerTest.java b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/UpdateHandlerTest.java
index 54179fa..22ff2e7 100644
--- a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/UpdateHandlerTest.java
+++ b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/UpdateHandlerTest.java
@@ -1,6 +1,7 @@
package software.amazon.qbusiness.plugin;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
@@ -36,6 +37,7 @@
import software.amazon.awssdk.services.qbusiness.model.InternalServerException;
import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceRequest;
import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceResponse;
+import software.amazon.awssdk.services.qbusiness.model.PluginBuildStatus;
import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException;
import software.amazon.awssdk.services.qbusiness.model.ServiceQuotaExceededException;
import software.amazon.awssdk.services.qbusiness.model.TagResourceRequest;
@@ -46,6 +48,7 @@
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdatePluginResponse;
import software.amazon.awssdk.services.qbusiness.model.ValidationException;
+import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.ProgressEvent;
@@ -136,6 +139,7 @@ public void setup() {
.displayName(PLUGIN_NAME)
.type(PLUGIN_TYPE)
.state(PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY.toString())
.serverUrl(SERVER_URL)
.authConfiguration(serviceAuthConfiguration)
.tags(List.of(
@@ -151,6 +155,7 @@ public void setup() {
.displayName(UPDATED_PLUGIN_NAME)
.type(PLUGIN_TYPE)
.state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY.toString())
.serverUrl(UPDATED_SERVER_URL)
.authConfiguration(updatedServiceAuthConfiguration)
.tags(List.of(
@@ -188,16 +193,6 @@ public void setup() {
when(proxyClient.client().updatePlugin(any(UpdatePluginRequest.class)))
.thenReturn(UpdatePluginResponse.builder()
.build());
- when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
- .thenReturn(GetPluginResponse.builder()
- .applicationId(APPLICATION_ID)
- .pluginId(PLUGIN_ID)
- .displayName(UPDATED_PLUGIN_NAME)
- .type(PLUGIN_TYPE)
- .state(UPDATED_PLUGIN_STATE)
- .serverUrl(UPDATED_SERVER_URL)
- .authConfiguration(updatedCfnAuthConfiguration)
- .build());
when(qBusinessClient.listTagsForResource(any(ListTagsForResourceRequest.class)))
.thenReturn(ListTagsForResourceResponse.builder().tags(List.of()).build());
@@ -212,7 +207,17 @@ public void tear_down() throws Exception {
@Test
public void handleRequest_SimpleSuccess() {
-
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
when(qBusinessClient.tagResource(any(TagResourceRequest.class)))
.thenReturn(TagResourceResponse.builder().build());
when(qBusinessClient.untagResource(any(UntagResourceRequest.class)))
@@ -237,7 +242,7 @@ proxy, request, new CallbackContext(), proxyClient, logger
assertThat(resultProgress.getResourceModel().getState()).isEqualTo(UPDATED_PLUGIN_STATE);
assertThat(resultProgress.getResourceModel().getServerUrl()).isEqualTo(UPDATED_SERVER_URL);
- verify(qBusinessClient).getPlugin(
+ verify(qBusinessClient, times(2)).getPlugin(
argThat((ArgumentMatcher) t ->
t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
)
@@ -266,6 +271,109 @@ proxy, request, new CallbackContext(), proxyClient, logger
));
}
+ @Test
+ public void handleRequest_StabilizeFromUpdateInProgressToReady() {
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.UPDATE_IN_PROGRESS)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build())
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
+
+ when(qBusinessClient.tagResource(any(TagResourceRequest.class)))
+ .thenReturn(TagResourceResponse.builder().build());
+ when(qBusinessClient.untagResource(any(UntagResourceRequest.class)))
+ .thenReturn(UntagResourceResponse.builder().build());
+ final ProgressEvent resultProgress = underTest.handleRequest(
+ proxy, request, new CallbackContext(), proxyClient, logger
+ );
+
+ assertThat(resultProgress).isNotNull();
+ assertThat(resultProgress.isSuccess()).isTrue();
+ ArgumentCaptor updatePluginReqCaptor = ArgumentCaptor.forClass(UpdatePluginRequest.class);
+ verify(qBusinessClient).updatePlugin(updatePluginReqCaptor.capture());
+ assertThat(resultProgress.getResourceModel().getApplicationId()).isEqualTo(APPLICATION_ID);
+ assertThat(resultProgress.getResourceModel().getPluginId()).isEqualTo(PLUGIN_ID);
+ assertThat(resultProgress.getResourceModel().getAuthConfiguration().getBasicAuthConfiguration().getRoleArn())
+ .isEqualTo(AuthConfigHelper.convertToServiceAuthConfig(updatedModel.getAuthConfiguration())
+ .basicAuthConfiguration().roleArn());
+ assertThat(resultProgress.getResourceModel().getAuthConfiguration().getBasicAuthConfiguration().getSecretArn())
+ .isEqualTo(AuthConfigHelper.convertToServiceAuthConfig(updatedModel.getAuthConfiguration())
+ .basicAuthConfiguration().secretArn());
+ assertThat(resultProgress.getResourceModel().getDisplayName()).isEqualTo(UPDATED_PLUGIN_NAME);
+ assertThat(resultProgress.getResourceModel().getState()).isEqualTo(UPDATED_PLUGIN_STATE);
+ assertThat(resultProgress.getResourceModel().getServerUrl()).isEqualTo(UPDATED_SERVER_URL);
+
+ verify(qBusinessClient, times(3)).getPlugin(
+ argThat((ArgumentMatcher) t ->
+ t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
+ )
+ );
+ verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
+
+ var tagReqCaptor = ArgumentCaptor.forClass(TagResourceRequest.class);
+ var untagReqCaptor = ArgumentCaptor.forClass(UntagResourceRequest.class);
+ verify(qBusinessClient).tagResource(tagReqCaptor.capture());
+ verify(qBusinessClient).untagResource(untagReqCaptor.capture());
+
+ var tagResourceRequest = tagReqCaptor.getValue();
+ Map tagsInTagResourceReq = tagResourceRequest.tags().stream()
+ .collect(Collectors.toMap(tag -> tag.key(), tag -> tag.value()));
+ assertThat(tagsInTagResourceReq).containsOnly(
+ Map.entry("iwillchange", "nowanewvalue"),
+ Map.entry("iamnew", "overhere"),
+ Map.entry("stackchange", "whatwhenwhere"),
+ Map.entry("stacknewaddition", "newvalue")
+ );
+
+ var untagResourceReq = untagReqCaptor.getValue();
+ assertThat(untagResourceReq.tagKeys()).containsOnlyOnceElementsOf(List.of(
+ "toremove",
+ "stack-i-remove"
+ ));
+ }
+
+ @Test
+ public void handleRequest_ThrowsExpectedErrorWhenStabilizationFails() {
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.UPDATE_FAILED)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
+
+ assertThatThrownBy(() -> underTest.handleRequest(
+ proxy, request, new CallbackContext(), proxyClient, logger
+ )).isInstanceOf(CfnNotStabilizedException.class);
+
+ verify(qBusinessClient).updatePlugin(any(UpdatePluginRequest.class));
+ verify(qBusinessClient, times(1)).getPlugin(
+ argThat((ArgumentMatcher) t ->
+ t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
+ )
+ );
+ }
+
private static Stream serviceErrorAndHandlerCodes() {
return Stream.of(
Arguments.of(ValidationException.builder().build(), HandlerErrorCode.InvalidRequest),
@@ -280,6 +388,17 @@ private static Stream serviceErrorAndHandlerCodes() {
@Test
public void testThatItDoesntTagAndUnTag() {
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
when(qBusinessClient.tagResource(any(TagResourceRequest.class)))
.thenReturn(TagResourceResponse.builder().build());
request.setPreviousResourceTags(Map.of(
@@ -303,7 +422,7 @@ proxy, request, new CallbackContext(), proxyClient, logger
assertThat(resultProgress.isSuccess()).isTrue();
verify(qBusinessClient).updatePlugin(any(UpdatePluginRequest.class));
- verify(qBusinessClient).getPlugin(
+ verify(qBusinessClient, times(2)).getPlugin(
argThat((ArgumentMatcher) t ->
t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
)
@@ -325,6 +444,17 @@ proxy, request, new CallbackContext(), proxyClient, logger
@Test
public void testThatItCallsUnTagButSkipsCallingTag() {
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
when(qBusinessClient.untagResource(any(UntagResourceRequest.class)))
.thenReturn(UntagResourceResponse.builder().build());
model.setTags(List.of(
@@ -350,7 +480,7 @@ proxy, request, new CallbackContext(), proxyClient, logger
assertThat(resultProgress).isNotNull();
assertThat(resultProgress.isSuccess()).isTrue();
verify(qBusinessClient).updatePlugin(any(UpdatePluginRequest.class));
- verify(qBusinessClient).getPlugin(
+ verify(qBusinessClient, times(2)).getPlugin(
argThat((ArgumentMatcher) t ->
t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
)
@@ -398,6 +528,17 @@ public void testThatItDoesntTagAndUnTagWhenTagFieldsAreNull(
Map reqTags,
Map sysTags
) {
+ when(qBusinessClient.getPlugin(any(GetPluginRequest.class)))
+ .thenReturn(GetPluginResponse.builder()
+ .applicationId(APPLICATION_ID)
+ .pluginId(PLUGIN_ID)
+ .displayName(UPDATED_PLUGIN_NAME)
+ .type(PLUGIN_TYPE)
+ .state(UPDATED_PLUGIN_STATE)
+ .buildStatus(PluginBuildStatus.READY)
+ .serverUrl(UPDATED_SERVER_URL)
+ .authConfiguration(updatedCfnAuthConfiguration)
+ .build());
// set up test scenario
model.setTags(modelTags);
updatedModel.setTags(modelTags);
@@ -415,7 +556,7 @@ proxy, request, new CallbackContext(), proxyClient, logger
assertThat(resultProgress).isNotNull();
assertThat(resultProgress.isSuccess()).isTrue();
verify(qBusinessClient).updatePlugin(any(UpdatePluginRequest.class));
- verify(qBusinessClient).getPlugin(
+ verify(qBusinessClient, times(2)).getPlugin(
argThat((ArgumentMatcher) t ->
t.applicationId().equals(APPLICATION_ID) && t.pluginId().equals(PLUGIN_ID)
)
diff --git a/aws-qbusiness-retriever/aws-qbusiness-retriever.json b/aws-qbusiness-retriever/aws-qbusiness-retriever.json
index d62ffe8..faeafb4 100755
--- a/aws-qbusiness-retriever/aws-qbusiness-retriever.json
+++ b/aws-qbusiness-retriever/aws-qbusiness-retriever.json
@@ -157,6 +157,7 @@
}
},
"required": [
+ "ApplicationId",
"Configuration",
"DisplayName",
"Type"
diff --git a/aws-qbusiness-retriever/pom.xml b/aws-qbusiness-retriever/pom.xml
index 57c78f7..0ed2e56 100644
--- a/aws-qbusiness-retriever/pom.xml
+++ b/aws-qbusiness-retriever/pom.xml
@@ -37,13 +37,13 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json b/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json
index 31a675b..7a5d244 100755
--- a/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json
+++ b/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json
@@ -1,41 +1,7 @@
{
"typeName": "AWS::QBusiness::WebExperience",
"description": "Definition of AWS::QBusiness::WebExperience Resource Type",
- "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-qbusiness",
"definitions": {
- "SamlConfiguration": {
- "type": "object",
- "properties": {
- "MetadataXML": {
- "type": "string",
- "maxLength": 10000000,
- "minLength": 1000,
- "pattern": "^.*$"
- },
- "RoleArn": {
- "type": "string",
- "maxLength": 1284,
- "minLength": 0,
- "pattern": "^arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}$"
- },
- "UserIdAttribute": {
- "type": "string",
- "maxLength": 256,
- "minLength": 1
- },
- "UserGroupAttribute": {
- "type": "string",
- "maxLength": 256,
- "minLength": 1
- }
- },
- "required": [
- "MetadataXML",
- "RoleArn",
- "UserIdAttribute"
- ],
- "additionalProperties": false
- },
"Tag": {
"type": "object",
"properties": {
@@ -56,23 +22,6 @@
],
"additionalProperties": false
},
- "WebExperienceAuthConfiguration": {
- "oneOf": [
- {
- "type": "object",
- "title": "SamlConfiguration",
- "properties": {
- "SamlConfiguration": {
- "$ref": "#/definitions/SamlConfiguration"
- }
- },
- "required": [
- "SamlConfiguration"
- ],
- "additionalProperties": false
- }
- ]
- },
"WebExperienceSamplePromptsControlMode": {
"type": "string",
"enum": [
@@ -98,9 +47,6 @@
"minLength": 36,
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9-]{35}$"
},
- "AuthenticationConfiguration": {
- "$ref": "#/definitions/WebExperienceAuthConfiguration"
- },
"CreatedAt": {
"type": "string",
"format": "date-time"
@@ -111,6 +57,12 @@
"minLength": 1,
"pattern": "^(https?|ftp|file)://([^\\s]*)$"
},
+ "RoleArn": {
+ "type": "string",
+ "maxLength": 1284,
+ "minLength": 0,
+ "pattern": "^arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}$"
+ },
"SamplePromptsControlMode": {
"$ref": "#/definitions/WebExperienceSamplePromptsControlMode"
},
@@ -160,6 +112,9 @@
"minLength": 0
}
},
+ "required": [
+ "ApplicationId"
+ ],
"readOnlyProperties": [
"/properties/CreatedAt",
"/properties/DefaultEndpoint",
@@ -180,10 +135,11 @@
"permissions": [
"iam:PassRole",
"qbusiness:CreateWebExperience",
- "qbusiness:UpdateWebExperience",
"qbusiness:GetWebExperience",
"qbusiness:ListTagsForResource",
- "qbusiness:TagResource"
+ "qbusiness:TagResource",
+ "sso:PutApplicationGrant",
+ "sso:UpdateApplication"
]
},
"read": {
@@ -199,7 +155,9 @@
"qbusiness:ListTagsForResource",
"qbusiness:TagResource",
"qbusiness:UntagResource",
- "qbusiness:UpdateWebExperience"
+ "qbusiness:UpdateWebExperience",
+ "sso:PutApplicationGrant",
+ "sso:UpdateApplication"
]
},
"delete": {
@@ -227,5 +185,6 @@
"tagging": {
"taggable": true
},
+ "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-qbusiness",
"additionalProperties": false
}
diff --git a/aws-qbusiness-webexperience/pom.xml b/aws-qbusiness-webexperience/pom.xml
index 5f1dcb1..719fbbf 100644
--- a/aws-qbusiness-webexperience/pom.xml
+++ b/aws-qbusiness-webexperience/pom.xml
@@ -37,13 +37,13 @@
software.amazon.awssdk
qbusiness
- 2.23.12
+ 2.25.42
software.amazon.awssdk
sdk-core
- 2.23.12
+ 2.25.42
diff --git a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/CreateHandler.java b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/CreateHandler.java
index c663126..f666597 100644
--- a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/CreateHandler.java
+++ b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/CreateHandler.java
@@ -5,8 +5,6 @@
import software.amazon.awssdk.services.qbusiness.model.CreateWebExperienceResponse;
import software.amazon.awssdk.services.qbusiness.model.ErrorDetail;
import software.amazon.awssdk.services.qbusiness.model.GetWebExperienceResponse;
-import software.amazon.awssdk.services.qbusiness.model.UpdateWebExperienceRequest;
-import software.amazon.awssdk.services.qbusiness.model.UpdateWebExperienceResponse;
import software.amazon.awssdk.services.qbusiness.model.WebExperienceStatus;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
@@ -21,7 +19,6 @@
import java.util.Objects;
import static software.amazon.qbusiness.webexperience.Constants.API_CREATE_WEB_EXPERIENCE;
-import static software.amazon.qbusiness.webexperience.Constants.API_UPDATE_WEB_EXPERIENCE;
public class CreateHandler extends BaseHandlerStd {
@@ -60,29 +57,11 @@ protected ProgressEvent handleRequest(
.backoffDelay(backOffStrategy)
.makeServiceCall((awsRequest, clientProxyClient) ->
callCreateWebExperience(awsRequest, clientProxyClient, progress.getResourceModel()))
- .stabilize((awsReq, response, clientProxyClient, model, context) -> isCreateStabilized(clientProxyClient, model, logger))
+ .stabilize((awsReq, response, clientProxyClient, model, context) -> isStabilized(clientProxyClient, model, logger))
.handleError((createReq, error, client, model, context) ->
handleError(createReq, model, error, context, logger, API_CREATE_WEB_EXPERIENCE))
.progress()
)
- .then(progress -> {
- // if authentication configuration was not set, let's short circuit
- if (request.getDesiredResourceState().getAuthenticationConfiguration() == null) {
- return readHandler(proxy, request, callbackContext, proxyClient);
- }
-
- // customer has set an authentication configuration, let's set up a call to Update.
- return proxy.initiate("AWS-QBusiness-WebExperience::PostCreateUpdate",
- proxyClient, progress.getResourceModel(), progress.getCallbackContext()
- )
- .translateToServiceRequest(Translator::translateToPostCreateUpdateRequest)
- .backoffDelay(backOffStrategy)
- .makeServiceCall(this::callUpdateWebExperience)
- .stabilize((awsReq, response, clientProxyClient, model, context) -> isUpdateStabilized(clientProxyClient, model, logger))
- .handleError((createReq, error, client, model, context) ->
- handleError(createReq, model, error, context, logger, API_UPDATE_WEB_EXPERIENCE))
- .progress();
- })
.then(progress -> readHandler(proxy, request, callbackContext, proxyClient));
}
@@ -94,56 +73,32 @@ private ProgressEvent readHandler(
return new ReadHandler().handleRequest(proxy, request, callbackContext, proxyClient, logger);
}
- private boolean isCreateStabilized(
+ private boolean isStabilized(
final ProxyClient proxyClient,
final ResourceModel model,
final Logger logger) {
final GetWebExperienceResponse getWebExperienceResponse = getWebExperience(model, proxyClient, logger);
final String status = getWebExperienceResponse.statusAsString();
+ final String roleArn = getWebExperienceResponse.roleArn();
- // CreateWebExperience does not take AuthenticationConfiguration. In this case, the status becomes
- // PENDING_AUTH_CONFIG. See https://tiny.amazon.com/1geblgev
- if (WebExperienceStatus.PENDING_AUTH_CONFIG.toString().equals(status)) {
+ if (WebExperienceStatus.ACTIVE.toString().equals(status)) {
logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s has stabilized for create operation"
- .formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
+ .formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
return true;
}
- if (!WebExperienceStatus.FAILED.toString().equals(status)) {
- logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s is still stabilizing for create operation."
+ // If RoleArn is not passed, the status becomes
+ // PENDING_AUTH_CONFIG. See https://tiny.amazon.com/4i460dfb
+ if (roleArn == null && WebExperienceStatus.PENDING_AUTH_CONFIG.toString().equals(status)) {
+ logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s has stabilized for create operation"
.formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
- return false;
- }
-
- // handle failed state
-
- RuntimeException causeMessage = null;
- ErrorDetail error = getWebExperienceResponse.error();
- if (Objects.nonNull(error) && StringUtils.isNotBlank(error.errorMessage())) {
- causeMessage = new RuntimeException(error.errorMessage());
- }
-
- throw new CfnNotStabilizedException(ResourceModel.TYPE_NAME, model.getPrimaryIdentifier().toString(), causeMessage);
- }
-
- private boolean isUpdateStabilized(
- final ProxyClient proxyClient,
- final ResourceModel model,
- final Logger logger) {
- final GetWebExperienceResponse getWebExperienceResponse = getWebExperience(model, proxyClient, logger);
-
- final String status = getWebExperienceResponse.statusAsString();
-
- if (WebExperienceStatus.ACTIVE.toString().equals(status)) {
- logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s has stabilized for update operation"
- .formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
return true;
}
if (!WebExperienceStatus.FAILED.toString().equals(status)) {
- logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s is still stabilizing for update operation."
- .formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
+ logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s is still stabilizing for create operation."
+ .formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
return false;
}
@@ -158,7 +113,6 @@ private boolean isUpdateStabilized(
throw new CfnNotStabilizedException(ResourceModel.TYPE_NAME, model.getPrimaryIdentifier().toString(), causeMessage);
}
-
private CreateWebExperienceResponse callCreateWebExperience(
final CreateWebExperienceRequest request,
final ProxyClient proxyClient,
@@ -167,11 +121,4 @@ private CreateWebExperienceResponse callCreateWebExperience(
model.setWebExperienceId(response.webExperienceId());
return response;
}
-
- private UpdateWebExperienceResponse callUpdateWebExperience(
- UpdateWebExperienceRequest updateReq,
- final ProxyClient proxyClient
- ) {
- return proxyClient.injectCredentialsAndInvokeV2(updateReq, proxyClient.client()::updateWebExperience);
- }
}
diff --git a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java
index cad5d32..200d8b1 100644
--- a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java
+++ b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java
@@ -43,6 +43,7 @@ static CreateWebExperienceRequest translateToCreateRequest(final String idempote
return CreateWebExperienceRequest.builder()
.clientToken(idempotentToken)
.applicationId(model.getApplicationId())
+ .roleArn(model.getRoleArn())
.title(model.getTitle())
.subtitle(model.getSubtitle())
.welcomeMessage(model.getWelcomeMessage())
@@ -50,14 +51,6 @@ static CreateWebExperienceRequest translateToCreateRequest(final String idempote
.build();
}
- static UpdateWebExperienceRequest translateToPostCreateUpdateRequest(final ResourceModel model) {
- return UpdateWebExperienceRequest.builder()
- .applicationId(model.getApplicationId())
- .webExperienceId(model.getWebExperienceId())
- .authenticationConfiguration(toServiceAuthenticationConfiguration(model.getAuthenticationConfiguration()))
- .build();
- }
-
/**
* Request to read a resource
*
@@ -102,7 +95,7 @@ static ResourceModel translateFromReadResponse(final GetWebExperienceResponse aw
.subtitle(awsResponse.subtitle())
.welcomeMessage(awsResponse.welcomeMessage())
.samplePromptsControlMode(awsResponse.samplePromptsControlModeAsString())
- .authenticationConfiguration(fromServiceAuthenticationConfiguration(awsResponse.authenticationConfiguration()))
+ .roleArn(awsResponse.roleArn())
.defaultEndpoint(awsResponse.defaultEndpoint())
.createdAt(instantToString(awsResponse.createdAt()))
.updatedAt(instantToString(awsResponse.updatedAt()))
@@ -151,7 +144,7 @@ static UpdateWebExperienceRequest translateToUpdateRequest(final ResourceModel m
.webExperienceId(model.getWebExperienceId())
.title(model.getTitle())
.subtitle(model.getSubtitle())
- .authenticationConfiguration(toServiceAuthenticationConfiguration(model.getAuthenticationConfiguration()))
+ .roleArn(model.getRoleArn())
.build();
}
@@ -274,53 +267,6 @@ static UntagResourceRequest untagResourceRequest(
.build();
}
-
- private static WebExperienceAuthConfiguration fromServiceAuthenticationConfiguration(
- final software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration webExperienceAuthConfiguration) {
- if (Objects.isNull(webExperienceAuthConfiguration)) {
- return null;
- }
-
- return WebExperienceAuthConfiguration.builder()
- .samlConfiguration(fromServiceWebExperienceAuthConfiguration(webExperienceAuthConfiguration.samlConfiguration()))
- .build();
- }
-
- private static SamlConfiguration fromServiceWebExperienceAuthConfiguration(
- final software.amazon.awssdk.services.qbusiness.model.SamlConfiguration samlConfigurationOptions) {
- return SamlConfiguration.builder()
- .metadataXML(samlConfigurationOptions.metadataXML())
- .roleArn(samlConfigurationOptions.roleArn())
- .userIdAttribute(samlConfigurationOptions.userIdAttribute())
- .userGroupAttribute(samlConfigurationOptions.userGroupAttribute())
- .build();
- }
-
- private static software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration
- toServiceAuthenticationConfiguration(final WebExperienceAuthConfiguration authenticationConfiguration) {
- if (authenticationConfiguration == null || authenticationConfiguration.getSamlConfiguration() == null) {
- return null;
- }
-
- return software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(toServiceSamlConfigurationOptions(authenticationConfiguration.getSamlConfiguration()))
- .build();
- }
-
- private static software.amazon.awssdk.services.qbusiness.model.SamlConfiguration
- toServiceSamlConfigurationOptions(final SamlConfiguration samlConfigurationOptions) {
- if (samlConfigurationOptions == null) {
- return null;
- }
-
- return software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML(samlConfigurationOptions.getMetadataXML())
- .roleArn(samlConfigurationOptions.getRoleArn())
- .userIdAttribute(samlConfigurationOptions.getUserIdAttribute())
- .userGroupAttribute(samlConfigurationOptions.getUserGroupAttribute())
- .build();
- }
-
private static String instantToString(Instant instant) {
return Optional.ofNullable(instant)
.map(Instant::toString)
diff --git a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/UpdateHandler.java b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/UpdateHandler.java
index 89fae60..b29eb49 100644
--- a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/UpdateHandler.java
+++ b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/UpdateHandler.java
@@ -10,7 +10,6 @@
import software.amazon.awssdk.services.qbusiness.model.UntagResourceResponse;
import software.amazon.awssdk.services.qbusiness.model.UpdateWebExperienceRequest;
import software.amazon.awssdk.services.qbusiness.model.UpdateWebExperienceResponse;
-import software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration;
import software.amazon.awssdk.services.qbusiness.model.WebExperienceStatus;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
@@ -136,7 +135,7 @@ private boolean isStabilized(
final ResourceModel model) {
final GetWebExperienceResponse getWebExperienceResponse = getWebExperience(model, proxyClient, logger);
final WebExperienceStatus status = getWebExperienceResponse.status();
- final WebExperienceAuthConfiguration authConfiguration = getWebExperienceResponse.authenticationConfiguration();
+ final String roleArn = getWebExperienceResponse.roleArn();
if (WebExperienceStatus.ACTIVE.equals(status)) {
logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s has stabilized."
@@ -144,7 +143,7 @@ private boolean isStabilized(
return true;
}
- if (authConfiguration == null && WebExperienceStatus.PENDING_AUTH_CONFIG.equals(status)) {
+ if (roleArn == null && WebExperienceStatus.PENDING_AUTH_CONFIG.equals(status)) {
logger.log("[INFO] %s with ApplicationId: %s and WebExperienceId: %s has stabilized."
.formatted(ResourceModel.TYPE_NAME, model.getApplicationId(), model.getWebExperienceId()));
return true;
diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java
index ade004a..f0df558 100644
--- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java
+++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java
@@ -41,7 +41,6 @@
import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException;
import software.amazon.awssdk.services.qbusiness.model.ServiceQuotaExceededException;
import software.amazon.awssdk.services.qbusiness.model.ThrottlingException;
-import software.amazon.awssdk.services.qbusiness.model.UpdateWebExperienceRequest;
import software.amazon.awssdk.services.qbusiness.model.ValidationException;
import software.amazon.awssdk.services.qbusiness.model.WebExperienceStatus;
import software.amazon.cloudformation.exceptions.CfnNotStabilizedException;
@@ -89,14 +88,7 @@ public void setup() {
.applicationId(APP_ID)
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
- .authenticationConfiguration(WebExperienceAuthConfiguration.builder()
- .samlConfiguration(SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.build();
testRequest = ResourceHandlerRequest.builder()
@@ -128,32 +120,20 @@ public void handleRequest_SimpleSuccess() {
.tags(List.of())
.build());
- GetWebExperienceResponse baseResponse = GetWebExperienceResponse.builder()
+ GetWebExperienceResponse response = GetWebExperienceResponse.builder()
.applicationId(APP_ID)
.webExperienceId(WEB_EXPERIENCE_ID)
.createdAt(Instant.ofEpochMilli(1697824935000L))
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
- .status(WebExperienceStatus.PENDING_AUTH_CONFIG)
- .defaultEndpoint("Endpoint")
- .build();
-
- GetWebExperienceResponse responseWithAuth = baseResponse.toBuilder()
.status(WebExperienceStatus.ACTIVE)
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
+ .defaultEndpoint("Endpoint")
.build();
when(qBusinessClient.getWebExperience(any(GetWebExperienceRequest.class)))
- .thenReturn(baseResponse)
- .thenReturn(responseWithAuth);
+ .thenReturn(response);
// call method under test
final ProgressEvent resultProgress = underTest.handleRequest(
@@ -171,29 +151,19 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultModel.getTitle()).isEqualTo("This is a title of the web experience.");
assertThat(resultModel.getSubtitle()).isEqualTo("This is a subtitle of the web experience.");
assertThat(resultModel.getStatus()).isEqualTo(WebExperienceStatus.ACTIVE.toString());
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getMetadataXML()).isEqualTo("XML");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getRoleArn()).isEqualTo("RoleARN");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserIdAttribute()).isEqualTo("UserAttribute");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserGroupAttribute())
- .isEqualTo("UserGroupAttribute");
+ assertThat(resultModel.getRoleArn()).isEqualTo("RoleArn");
assertThat(resultModel.getDefaultEndpoint()).isEqualTo("Endpoint");
verify(qBusinessClient).createWebExperience(any(CreateWebExperienceRequest.class));
- var updateReqCaptor = ArgumentCaptor.forClass(UpdateWebExperienceRequest.class);
- verify(qBusinessClient).updateWebExperience(updateReqCaptor.capture());
- verify(qBusinessClient, times(3)).getWebExperience(
+ verify(qBusinessClient, times(2)).getWebExperience(
argThat((ArgumentMatcher) t -> t.applicationId().equals(APP_ID) && t.webExperienceId().equals(WEB_EXPERIENCE_ID))
);
verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
-
- UpdateWebExperienceRequest updateRequest = updateReqCaptor.getValue();
- assertThat(updateRequest.applicationId()).isEqualTo(APP_ID);
- assertThat(updateRequest.webExperienceId()).isEqualTo(WEB_EXPERIENCE_ID);
}
@Test
- public void testItSkipsCallingUpdate() {
+ public void handleRequest_WithoutRoleArn() {
// set up
when(qBusinessClient.createWebExperience(any(CreateWebExperienceRequest.class)))
.thenReturn(CreateWebExperienceResponse.builder()
@@ -206,7 +176,7 @@ public void testItSkipsCallingUpdate() {
.build());
createModel = createModel.toBuilder()
- .authenticationConfiguration(null)
+ .roleArn(null)
.build();
testRequest.setDesiredResourceState(createModel);
GetWebExperienceResponse response = GetWebExperienceResponse.builder()
@@ -261,21 +231,13 @@ public void handleRequestFromProcessingStateToActive() {
.updatedAt(Instant.ofEpochMilli(1697839335000L))
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.defaultEndpoint("Endpoint")
.build();
when(qBusinessClient.getWebExperience(any(GetWebExperienceRequest.class)))
.thenReturn(
getResponse.toBuilder().status(WebExperienceStatus.CREATING).build(),
- getResponse.toBuilder().status(WebExperienceStatus.PENDING_AUTH_CONFIG).build(),
getResponse.toBuilder().status(WebExperienceStatus.ACTIVE).build()
);
@@ -288,10 +250,9 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultProgress).isNotNull();
assertThat(resultProgress.isSuccess()).isTrue();
verify(qBusinessClient).createWebExperience(any(CreateWebExperienceRequest.class));
- verify(qBusinessClient, times(4)).getWebExperience(
+ verify(qBusinessClient, times(3)).getWebExperience(
argThat((ArgumentMatcher) t -> t.applicationId().equals(APP_ID) && t.webExperienceId().equals(WEB_EXPERIENCE_ID))
);
- verify(qBusinessClient).updateWebExperience(any(UpdateWebExperienceRequest.class));
verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class));
}
@@ -314,14 +275,7 @@ public void testItFailsWithErrorMessageWhenGetReturnsFailStatus() {
.subtitle("This is a subtitle of the web experience.")
.error(ErrorDetail.builder().errorMessage("There was a problem in get web experience.").build())
.status(WebExperienceStatus.FAILED)
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("roleArn")
.defaultEndpoint("Endpoint")
.build());
diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java
index eba8e49..733314e 100644
--- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java
+++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java
@@ -101,14 +101,7 @@ public void handleRequest_SimpleSuccess() {
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
.status(WebExperienceStatus.ACTIVE)
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.defaultEndpoint("Endpoint")
.build());
when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class)))
@@ -141,11 +134,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultModel.getTitle()).isEqualTo("This is a title of the web experience.");
assertThat(resultModel.getSubtitle()).isEqualTo("This is a subtitle of the web experience.");
assertThat(resultModel.getStatus()).isEqualTo(WebExperienceStatus.ACTIVE.toString());
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getMetadataXML()).isEqualTo("XML");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getRoleArn()).isEqualTo("RoleARN");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserIdAttribute()).isEqualTo("UserAttribute");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserGroupAttribute())
- .isEqualTo("UserGroupAttribute");
+ assertThat(resultModel.getRoleArn()).isEqualTo("RoleArn");
assertThat(resultModel.getDefaultEndpoint()).isEqualTo("Endpoint");
var tags = resultModel.getTags().stream().map(tag -> Map.entry(tag.getKey(), tag.getValue())).toList();
@@ -163,14 +152,7 @@ public void handleRequest_SimpleSuccess_withMissingProperties() {
.webExperienceId(WEB_EXPERIENCE_ID)
.title("This is a title of the web experience.")
.status(WebExperienceStatus.ACTIVE)
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.build());
// call method under test
@@ -195,11 +177,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(resultModel.getTitle()).isEqualTo("This is a title of the web experience.");
assertThat(resultModel.getApplicationId()).isEqualTo(APP_ID);
assertThat(resultModel.getWebExperienceId()).isEqualTo(WEB_EXPERIENCE_ID);
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getMetadataXML()).isEqualTo("XML");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getRoleArn()).isEqualTo("RoleARN");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserIdAttribute()).isEqualTo("UserAttribute");
- assertThat(resultModel.getAuthenticationConfiguration().getSamlConfiguration().getUserGroupAttribute())
- .isEqualTo("UserGroupAttribute");
+ assertThat(resultModel.getRoleArn()).isEqualTo("RoleArn");
}
private static Stream serviceErrorAndExpectedCfnCode() {
@@ -245,14 +223,7 @@ public void testThatItReturnsExpectedErrorCodeWhenListTagsForResourceFails(
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
.status(WebExperienceStatus.ACTIVE)
- .authenticationConfiguration(software.amazon.awssdk.services.qbusiness.model.WebExperienceAuthConfiguration.builder()
- .samlConfiguration(software.amazon.awssdk.services.qbusiness.model.SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.defaultEndpoint("Endpoint")
.build());
diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java
index dbdc3c7..97e05f3 100644
--- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java
+++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java
@@ -88,14 +88,7 @@ public void setup() {
.title("This is a title of the web experience.")
.subtitle("This is a subtitle of the web experience.")
.status(WebExperienceStatus.ACTIVE.toString())
- .authenticationConfiguration(WebExperienceAuthConfiguration.builder()
- .samlConfiguration(SamlConfiguration.builder()
- .metadataXML("XML")
- .roleArn("RoleARN")
- .userIdAttribute("UserAttribute")
- .userGroupAttribute("UserGroupAttribute")
- .build())
- .build())
+ .roleArn("RoleArn")
.defaultEndpoint("Endpoint")
.tags(List.of(
Tag.builder().key("remain").value("thesame").build(),
@@ -109,14 +102,7 @@ public void setup() {
.webExperienceId(WEB_EXPERIENCE_ID)
.title("This is a new title of the web experience.")
.subtitle("This is a new subtitle of the web experience.")
- .authenticationConfiguration(WebExperienceAuthConfiguration.builder()
- .samlConfiguration(SamlConfiguration.builder()
- .metadataXML("XML2")
- .roleArn("RoleARN2")
- .userIdAttribute("UserAttribute2")
- .userGroupAttribute("UserGroupAttribute2")
- .build())
- .build())
+ .roleArn("RoleArn")
.tags(List.of(
Tag.builder().key("remain").value("thesame").build(),
Tag.builder().key("iwillchange").value("nowanewvalue").build(),
@@ -191,11 +177,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
assertThat(updateAppRequest.webExperienceId()).isEqualTo(WEB_EXPERIENCE_ID);
assertThat(updateAppRequest.title()).isEqualTo("This is a new title of the web experience.");
assertThat(updateAppRequest.subtitle()).isEqualTo("This is a new subtitle of the web experience.");
- assertThat(updateAppRequest.authenticationConfiguration().samlConfiguration().metadataXML()).isEqualTo("XML2");
- assertThat(updateAppRequest.authenticationConfiguration().samlConfiguration().roleArn()).isEqualTo("RoleARN2");
- assertThat(updateAppRequest.authenticationConfiguration().samlConfiguration().userIdAttribute()).isEqualTo("UserAttribute2");
- assertThat(updateAppRequest.authenticationConfiguration().samlConfiguration().userGroupAttribute())
- .isEqualTo("UserGroupAttribute2");
+ assertThat(updateAppRequest.roleArn()).isEqualTo("RoleArn");
verify(sdkClient, times(2)).getWebExperience(
argThat((ArgumentMatcher) t -> t.applicationId().equals(APP_ID) && t.webExperienceId().equals(WEB_EXPERIENCE_ID))
@@ -225,7 +207,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger
}
@Test
- public void handleRequest_WithoutAuthContextSuccess() {
+ public void handleRequest_WithoutRoleArnSuccess() {
// call method under test
previousModel = ResourceModel.builder()
.applicationId(APP_ID)