diff --git a/aws-redshiftserverless-workgroup/.rpdk-config b/aws-redshiftserverless-workgroup/.rpdk-config
index e1c475e..ff023bb 100644
--- a/aws-redshiftserverless-workgroup/.rpdk-config
+++ b/aws-redshiftserverless-workgroup/.rpdk-config
@@ -23,5 +23,6 @@
],
"codegen_template_path": "guided_aws",
"protocolVersion": "2.0.0"
- }
+ },
+ "executableEntrypoint": "software.amazon.redshiftserverless.workgroup.HandlerWrapperExecutable"
}
diff --git a/aws-redshiftserverless-workgroup/pom.xml b/aws-redshiftserverless-workgroup/pom.xml
index 88c6806..4aeeef3 100644
--- a/aws-redshiftserverless-workgroup/pom.xml
+++ b/aws-redshiftserverless-workgroup/pom.xml
@@ -72,6 +72,12 @@
5.5.0-M1
test
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.5.0-M1
+ test
+
org.mockito
diff --git a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/BaseHandlerStd.java b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/BaseHandlerStd.java
index b9acb4f..d81cb19 100644
--- a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/BaseHandlerStd.java
+++ b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/BaseHandlerStd.java
@@ -1,6 +1,7 @@
package software.amazon.redshiftserverless.workgroup;
import software.amazon.awssdk.services.redshiftserverless.RedshiftServerlessClient;
+import software.amazon.awssdk.services.redshiftserverless.model.ConflictException;
import software.amazon.awssdk.services.redshiftserverless.model.DeleteWorkgroupRequest;
import software.amazon.awssdk.services.redshiftserverless.model.GetWorkgroupRequest;
import software.amazon.awssdk.services.redshiftserverless.model.RedshiftServerlessResponse;
@@ -19,6 +20,13 @@
public abstract class BaseHandlerStd extends BaseHandler {
+ public static final String BUSY_WORKGROUP_RETRY_EXCEPTION_MESSAGE =
+ "There is an operation running on the existing workgroup";
+
+ protected static boolean isRetriableWorkgroupException(ConflictException exception) {
+ return exception.getMessage().contains(BUSY_WORKGROUP_RETRY_EXCEPTION_MESSAGE);
+ }
+
protected static final Constant BACKOFF_STRATEGY = Constant.of()
.timeout(Duration.ofMinutes(30L))
.delay(Duration.ofSeconds(5L))
diff --git a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CallbackContext.java b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CallbackContext.java
index f4ae984..7e906bd 100644
--- a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CallbackContext.java
+++ b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CallbackContext.java
@@ -7,4 +7,5 @@
@lombok.ToString
@lombok.EqualsAndHashCode(callSuper = true)
public class CallbackContext extends StdCallbackContext {
+ int retryOnResourceNotFound = 5;
}
diff --git a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CreateHandler.java b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CreateHandler.java
index 0e78f92..2c9e497 100644
--- a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CreateHandler.java
+++ b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/CreateHandler.java
@@ -39,17 +39,40 @@ protected ProgressEvent handleRequest(
.handleError(this::createWorkgroupErrorHandler)
.progress()
)
-
.then(progress -> new ReadHandler().handleRequest(proxy, request, callbackContext, proxyClient, logger));
}
private CreateWorkgroupResponse createWorkgroup(final CreateWorkgroupRequest awsRequest,
final ProxyClient proxyClient) {
- CreateWorkgroupResponse awsResponse;
- awsResponse = proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::createWorkgroup);
+ final int MAX_RETRIES = 4;
+ int retryCount = 0;
+
+ while (true) {
+ try {
+ CreateWorkgroupResponse awsResponse =
+ proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::createWorkgroup);
+
+ logger.log(String.format("%s has successfully been created.", ResourceModel.TYPE_NAME));
+
+ return awsResponse;
- logger.log(String.format("%s successfully created.", ResourceModel.TYPE_NAME));
- return awsResponse;
+ } catch (ConflictException ex) {
+ if (retryCount >= MAX_RETRIES || !isRetriableWorkgroupException(ex)) {
+ throw ex;
+ }
+
+ logger.log(String.format("Retrying CreateWorkgroup due to expected ConflictException: " +
+ "%s. Attempt %d/%d", ex.getMessage(), retryCount + 1, MAX_RETRIES));
+ retryCount++;
+ }
+
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt(); // Restore the interrupted status
+ throw new RuntimeException("Interrupted during retry wait", ie);
+ }
+ }
}
private ProgressEvent createWorkgroupErrorHandler(final CreateWorkgroupRequest awsRequest,
diff --git a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/ReadHandler.java b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/ReadHandler.java
index 0ac2f9f..ed05694 100644
--- a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/ReadHandler.java
+++ b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/ReadHandler.java
@@ -6,13 +6,20 @@
import software.amazon.awssdk.services.redshiftserverless.model.InternalServerException;
import software.amazon.awssdk.services.redshiftserverless.model.ResourceNotFoundException;
import software.amazon.awssdk.services.redshiftserverless.model.ValidationException;
+import software.amazon.awssdk.services.redshiftserverless.model.WorkgroupStatus;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.Logger;
+import software.amazon.cloudformation.proxy.OperationStatus;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.cloudformation.proxy.ProxyClient;
import software.amazon.cloudformation.proxy.ResourceHandlerRequest;
+import java.util.Arrays;
+import java.util.List;
+
+import static software.amazon.cloudformation.proxy.ProgressEvent.progress;
+
public class ReadHandler extends BaseHandlerStd {
private Logger logger;
@@ -29,16 +36,45 @@ protected ProgressEvent handleRequest(
.translateToServiceRequest(Translator::translateToReadRequest)
.makeServiceCall(this::readWorkgroup)
.handleError(this::readWorkgroupErrorHandler)
- .done(awsResponse -> ProgressEvent.defaultSuccessHandler(Translator.translateFromReadResponse(awsResponse)));
+ .done(awsResponse -> getProgressEventFromReadWorkgroupResponse(awsResponse, callbackContext));
}
private GetWorkgroupResponse readWorkgroup(final GetWorkgroupRequest awsRequest,
final ProxyClient proxyClient) {
GetWorkgroupResponse awsResponse;
- awsResponse = proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::getWorkgroup);
+ awsResponse = proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::getWorkgroup);
+
+ logger.log(String.format("%s has yo successfully been read.", ResourceModel.TYPE_NAME));
+ return awsResponse;
+ }
- logger.log(String.format("%s has successfully been read.", ResourceModel.TYPE_NAME));
- return awsResponse;
+ /**
+ * We used to return operationStatus.SUCCESS for all workgroup statuses,
+ * including creating, deleting, modifying.
+ *
+ * When CFN contract test checks if the resource has been deleted by calling ReadHandler,
+ * and when the workgroup == DELETING, we should have returned in_progress to indicate the
+ * deletion is not finished, and contract test can't start creating the same resource again.
+ *
+ * Same scenario would cause customer issues too.
+ *
+ * @param getWorkgroupResponse
+ * @param ctx
+ * @return
+ */
+ private static ProgressEvent getProgressEventFromReadWorkgroupResponse(GetWorkgroupResponse getWorkgroupResponse,
+ CallbackContext ctx) {
+ ResourceModel workgroupModel = Translator.translateFromReadResponse(getWorkgroupResponse);
+ List inProgressWorkgroupStatuses = Arrays.asList(
+ WorkgroupStatus.CREATING,
+ WorkgroupStatus.DELETING,
+ WorkgroupStatus.MODIFYING
+ );
+ boolean isInProgress = inProgressWorkgroupStatuses.contains(getWorkgroupResponse.workgroup().status());
+
+ ProgressEvent progressEvent = progress(workgroupModel, ctx);
+ progressEvent.setStatus(isInProgress ? OperationStatus.IN_PROGRESS : OperationStatus.SUCCESS);
+ return progressEvent;
}
private ProgressEvent readWorkgroupErrorHandler(final GetWorkgroupRequest awsRequest,
@@ -48,13 +84,10 @@ private ProgressEvent readWorkgroupErrorHandler(
final CallbackContext context) {
if (exception instanceof ResourceNotFoundException) {
return ProgressEvent.defaultFailureHandler(exception, HandlerErrorCode.NotFound);
-
} else if (exception instanceof ValidationException) {
return ProgressEvent.defaultFailureHandler(exception, HandlerErrorCode.InvalidRequest);
-
} else if (exception instanceof InternalServerException) {
return ProgressEvent.defaultFailureHandler(exception, HandlerErrorCode.InternalFailure);
-
} else {
return ProgressEvent.defaultFailureHandler(exception, HandlerErrorCode.GeneralServiceException);
}
diff --git a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/UpdateHandler.java b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/UpdateHandler.java
index fc902a0..21cc5ae 100644
--- a/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/UpdateHandler.java
+++ b/aws-redshiftserverless-workgroup/src/main/java/software/amazon/redshiftserverless/workgroup/UpdateHandler.java
@@ -179,11 +179,35 @@ private ProgressEvent operateTagsErrorHandler(fi
private UpdateWorkgroupResponse updateWorkgroup(final UpdateWorkgroupRequest awsRequest,
final ProxyClient proxyClient) {
- UpdateWorkgroupResponse awsResponse;
- awsResponse = proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::updateWorkgroup);
+ final int MAX_RETRIES = 4;
+ int retryCount = 0;
+
+ while (true) {
+ try {
+ UpdateWorkgroupResponse awsResponse =
+ proxyClient.injectCredentialsAndInvokeV2(awsRequest, proxyClient.client()::updateWorkgroup);
+
+ logger.log(String.format("%s has successfully been updated.", ResourceModel.TYPE_NAME));
+
+ return awsResponse;
+ } catch (ConflictException ex) {
+ if (retryCount >= MAX_RETRIES || !isRetriableWorkgroupException(ex)) {
+ throw ex;
+ }
+
+ logger.log(String.format("Retrying UpdateWorkgroup due to expected ConflictException: " +
+ "%s. Attempt %d/%d", ex.getMessage(), retryCount + 1, MAX_RETRIES));
+ retryCount++;
+ }
+
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt(); // Restore the interrupted status
+ throw new RuntimeException("Interrupted during retry wait", ie);
+ }
+ }
- logger.log(String.format("%s has successfully been updated.", ResourceModel.TYPE_NAME));
- return awsResponse;
}
private ProgressEvent updateWorkgroupErrorHandler(final UpdateWorkgroupRequest awsRequest,
diff --git a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/CreateHandlerTest.java b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/CreateHandlerTest.java
index c236088..650cf40 100644
--- a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/CreateHandlerTest.java
+++ b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/CreateHandlerTest.java
@@ -7,9 +7,12 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.services.redshiftserverless.RedshiftServerlessClient;
+import software.amazon.awssdk.services.redshiftserverless.model.ConflictException;
import software.amazon.awssdk.services.redshiftserverless.model.CreateWorkgroupRequest;
import software.amazon.awssdk.services.redshiftserverless.model.GetWorkgroupRequest;
+import software.amazon.awssdk.services.redshiftserverless.model.InternalServerException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
+import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.OperationStatus;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.cloudformation.proxy.ProxyClient;
@@ -72,4 +75,69 @@ public void handleRequest_SimpleSuccess() {
assertThat(response.getMessage()).isNull();
assertThat(response.getErrorCode()).isNull();
}
+
+ @Test
+ public void handleRequest_retryOnConflictException() {
+ final CreateHandler handler = new CreateHandler();
+
+ final ResourceModel requestResourceModel = createRequestResourceModel();
+ final ResourceModel responseResourceModel = getReadResponseResourceModel();
+
+ final ResourceHandlerRequest request = ResourceHandlerRequest.builder()
+ .desiredResourceState(requestResourceModel)
+ .build();
+
+ ConflictException exception = ConflictException.builder()
+ .message("There is an operation running on the existing workgroup. Try again later.")
+ .build();
+
+ /**
+ * The Thread.sleep() is actually called here, making unit longer.
+ * MockStatic easily will need a Java version upgrade, then the Mockito upgrade,
+ * I'll leave the upgrade in another commit.
+ */
+ when(proxyClient.client().createWorkgroup(any(CreateWorkgroupRequest.class)))
+ .thenThrow(exception)
+ .thenReturn(createResponseSdk());
+ when(proxyClient.client().getWorkgroup(any(GetWorkgroupRequest.class))).thenReturn(getReadResponseSdk());
+
+ final ProgressEvent response = handler.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
+ assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
+ assertThat(response.getResourceModel()).isEqualTo(responseResourceModel);
+ assertThat(response.getResourceModels()).isNull();
+ assertThat(response.getMessage()).isNull();
+ assertThat(response.getErrorCode()).isNull();
+ }
+
+ @Test
+ public void handleRequest_noRetryOnOtherException() throws InterruptedException {
+ final CreateHandler handler = new CreateHandler();
+ final ResourceModel requestResourceModel = createRequestResourceModel();
+ final ResourceHandlerRequest request = ResourceHandlerRequest.builder()
+ .desiredResourceState(requestResourceModel)
+ .build();
+
+ /**
+ * The Thread.sleep() is actually called here, making unit longer.
+ * MockStatic easily will need a Java version upgrade, then the Mockito upgrade,
+ * I'll leave the upgrade in another commit.
+ */
+ when(proxyClient.client().createWorkgroup(any(CreateWorkgroupRequest.class)))
+ .thenThrow(InternalServerException.builder()
+ .message("test")
+ .build());
+
+ final ProgressEvent response =
+ handler.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo(OperationStatus.FAILED);
+ assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
+ assertThat(response.getResourceModels()).isNull();
+ assertThat(response.getMessage()).isEqualTo("test");
+ assertThat(response.getErrorCode()).isEqualTo(HandlerErrorCode.InternalFailure);
+ }
}
diff --git a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/ReadHandlerTest.java b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/ReadHandlerTest.java
index af2d094..6fa3d3d 100644
--- a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/ReadHandlerTest.java
+++ b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/ReadHandlerTest.java
@@ -4,19 +4,30 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.services.redshiftserverless.RedshiftServerlessClient;
+import software.amazon.awssdk.services.redshiftserverless.model.GetNamespaceRequest;
import software.amazon.awssdk.services.redshiftserverless.model.GetWorkgroupRequest;
+import software.amazon.awssdk.services.redshiftserverless.model.GetWorkgroupResponse;
+import software.amazon.awssdk.services.redshiftserverless.model.WorkgroupStatus;
+import software.amazon.cloudformation.exceptions.CfnGeneralServiceException;
+import software.amazon.cloudformation.exceptions.CfnInvalidRequestException;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
import software.amazon.cloudformation.proxy.OperationStatus;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.cloudformation.proxy.ProxyClient;
import software.amazon.cloudformation.proxy.ResourceHandlerRequest;
+import java.lang.reflect.Method;
import java.time.Duration;
+import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
@@ -47,23 +58,41 @@ public void tear_down() {
verifyNoMoreInteractions(sdkClient);
}
- @Test
- public void handleRequest_SimpleSuccess() {
+ static Stream provideReadHandlerParams() {
+ return Stream.of(
+ Arguments.of(WorkgroupStatus.AVAILABLE, OperationStatus.SUCCESS),
+ Arguments.of(WorkgroupStatus.CREATING, OperationStatus.IN_PROGRESS),
+ Arguments.of(WorkgroupStatus.DELETING, OperationStatus.IN_PROGRESS),
+ Arguments.of(WorkgroupStatus.MODIFYING, OperationStatus.IN_PROGRESS),
+ Arguments.of(WorkgroupStatus.UNKNOWN_TO_SDK_VERSION, OperationStatus.SUCCESS)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideReadHandlerParams")
+ public void handleRequest_callReturns(
+ WorkgroupStatus returnedWgStatus,
+ OperationStatus expectedOperationStatus
+ ) {
final ReadHandler handler = new ReadHandler();
- final ResourceModel requestResourceModel = getReadRequestResourceModel();
- final ResourceModel responseResourceModel = getReadResponseResourceModel();
+ GetWorkgroupResponse defaultResponse = getReadResponseSdk();
+ GetWorkgroupResponse testResponse = defaultResponse.toBuilder()
+ .workgroup(defaultResponse.workgroup().toBuilder().status(returnedWgStatus).build())
+ .build();
+ when(proxyClient.client().getWorkgroup(any(GetWorkgroupRequest.class))).thenReturn(testResponse);
+
+ final ResourceModel requestResourceModel = getReadRequestResourceModel();
+ final ResourceModel responseResourceModel = Translator.translateFromReadResponse(testResponse);
final ResourceHandlerRequest request = ResourceHandlerRequest.builder()
.desiredResourceState(requestResourceModel)
.build();
- when(proxyClient.client().getWorkgroup(any(GetWorkgroupRequest.class))).thenReturn(getReadResponseSdk());
-
final ProgressEvent response = handler.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
assertThat(response).isNotNull();
- assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
+ assertThat(response.getStatus()).isEqualTo(expectedOperationStatus);
assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
assertThat(response.getResourceModel()).isEqualTo(responseResourceModel);
assertThat(response.getResourceModels()).isNull();
diff --git a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/UpdateHandlerTest.java b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/UpdateHandlerTest.java
index c48edec..3ea471e 100644
--- a/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/UpdateHandlerTest.java
+++ b/aws-redshiftserverless-workgroup/src/test/java/software/amazon/redshiftserverless/workgroup/UpdateHandlerTest.java
@@ -7,11 +7,14 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.services.redshiftserverless.RedshiftServerlessClient;
+import software.amazon.awssdk.services.redshiftserverless.model.ConflictException;
import software.amazon.awssdk.services.redshiftserverless.model.GetWorkgroupRequest;
+import software.amazon.awssdk.services.redshiftserverless.model.InternalServerException;
import software.amazon.awssdk.services.redshiftserverless.model.ListTagsForResourceRequest;
import software.amazon.awssdk.services.redshiftserverless.model.ListTagsForResourceResponse;
import software.amazon.awssdk.services.redshiftserverless.model.UpdateWorkgroupRequest;
import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy;
+import software.amazon.cloudformation.proxy.HandlerErrorCode;
import software.amazon.cloudformation.proxy.OperationStatus;
import software.amazon.cloudformation.proxy.ProgressEvent;
import software.amazon.cloudformation.proxy.ProxyClient;
@@ -75,4 +78,73 @@ public void handleRequest_SimpleSuccess() {
assertThat(response.getMessage()).isNull();
assertThat(response.getErrorCode()).isNull();
}
+
+ @Test
+ public void handleRequest_retryOnConflictException() {
+ final UpdateHandler handler = new UpdateHandler();
+
+ final ResourceModel requestResourceModel = updateRequestResourceModel();
+ final ResourceModel responseResourceModel = getReadResponseResourceModel();
+
+ final ResourceHandlerRequest request = ResourceHandlerRequest.builder()
+ .desiredResourceState(requestResourceModel)
+ .build();
+
+ ConflictException exception = ConflictException.builder()
+ .message("There is an operation running on the existing workgroup. Try again later.")
+ .build();
+
+ /**
+ * The Thread.sleep() is actually called here, making unit longer.
+ * MockStatic easily will need a Java version upgrade, then the Mockito upgrade,
+ * I'll leave the upgrade in another commit.
+ */
+ when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class))).thenReturn(ListTagsForResourceResponse.builder().build());
+ when(proxyClient.client().updateWorkgroup(any(UpdateWorkgroupRequest.class)))
+ .thenThrow(exception)
+ .thenReturn(updateResponseSdk());
+ when(proxyClient.client().getWorkgroup(any(GetWorkgroupRequest.class))).thenReturn(getReadResponseSdk());
+
+ final ProgressEvent response = handler.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
+ assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
+ assertThat(response.getResourceModel()).isEqualTo(responseResourceModel);
+ assertThat(response.getResourceModels()).isNull();
+ assertThat(response.getMessage()).isNull();
+ assertThat(response.getErrorCode()).isNull();
+ }
+
+ @Test
+ public void handleRequest_noRetryOnOtherException() {
+ final UpdateHandler handler = new UpdateHandler();
+ final ResourceModel requestResourceModel = updateResponseResourceModel();
+ final ResourceHandlerRequest request = ResourceHandlerRequest.builder()
+ .desiredResourceState(requestResourceModel)
+ .build();
+
+ /**
+ * The Thread.sleep() is actually called here, making unit longer.
+ * MockStatic easily will need a Java version upgrade, then the Mockito upgrade,
+ * I'll leave the upgrade in another commit.
+ */
+ when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class)))
+ .thenReturn(ListTagsForResourceResponse.builder().build());
+ when(proxyClient.client().updateWorkgroup(any(UpdateWorkgroupRequest.class)))
+ .thenThrow(InternalServerException.builder()
+ .message("test")
+ .build());
+ when(proxyClient.client().getWorkgroup(any(GetWorkgroupRequest.class))).thenReturn(getReadResponseSdk());
+
+ final ProgressEvent response =
+ handler.handleRequest(proxy, request, new CallbackContext(), proxyClient, logger);
+
+ assertThat(response).isNotNull();
+ assertThat(response.getStatus()).isEqualTo(OperationStatus.FAILED);
+ assertThat(response.getCallbackDelaySeconds()).isEqualTo(0);
+ assertThat(response.getResourceModels()).isNull();
+ assertThat(response.getMessage()).isEqualTo("test");
+ assertThat(response.getErrorCode()).isEqualTo(HandlerErrorCode.InternalFailure);
+ }
}