diff --git a/python/rpdk/java/templates/generate/HandlerWrapper.java b/python/rpdk/java/templates/generate/HandlerWrapper.java index 3873d9ba..04ff6de2 100644 --- a/python/rpdk/java/templates/generate/HandlerWrapper.java +++ b/python/rpdk/java/templates/generate/HandlerWrapper.java @@ -2,6 +2,7 @@ package {{ package_name }}; import com.amazonaws.AmazonServiceException; +import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.regions.PartitionMetadata; import software.amazon.awssdk.regions.Region; import software.amazon.cloudformation.Action; @@ -100,7 +101,7 @@ public void testEntrypoint( response = invokeHandler(proxy, payload.getRequest(), payload.getAction(), payload.getCallbackContext()); } catch (final BaseHandlerException e) { response = ProgressEvent.defaultFailureHandler(e, e.getErrorCode()); - } catch (final AmazonServiceException e) { + } catch (final AmazonServiceException | AwsServiceException e) { response = ProgressEvent.defaultFailureHandler(e, HandlerErrorCode.GeneralServiceException); } catch (final Throwable e) { e.printStackTrace(); diff --git a/src/main/java/software/amazon/cloudformation/LambdaWrapper.java b/src/main/java/software/amazon/cloudformation/LambdaWrapper.java index bfe18df7..5d1f7f9b 100644 --- a/src/main/java/software/amazon/cloudformation/LambdaWrapper.java +++ b/src/main/java/software/amazon/cloudformation/LambdaWrapper.java @@ -39,6 +39,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONObject; import org.json.JSONTokener; +import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.utils.StringUtils; @@ -361,7 +362,7 @@ public void handleRequest(final InputStream inputStream, final OutputStream outp publishExceptionMetric(request.getAction(), e, e.getErrorCode()); logUnhandledError(e.getMessage(), request, e); return ProgressEvent.defaultFailureHandler(e, e.getErrorCode()); - } catch (final AmazonServiceException e) { + } catch (final AmazonServiceException | AwsServiceException e) { publishExceptionMetric(request.getAction(), e, HandlerErrorCode.GeneralServiceException); logUnhandledError("A downstream service error occurred", request, e); return ProgressEvent.defaultFailureHandler(e, HandlerErrorCode.GeneralServiceException); diff --git a/src/test/java/software/amazon/cloudformation/LambdaWrapperTest.java b/src/test/java/software/amazon/cloudformation/LambdaWrapperTest.java index b1eb20e1..c40c9a82 100755 --- a/src/test/java/software/amazon/cloudformation/LambdaWrapperTest.java +++ b/src/test/java/software/amazon/cloudformation/LambdaWrapperTest.java @@ -43,6 +43,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.services.cloudwatchlogs.model.CloudWatchLogsException; import software.amazon.cloudformation.exceptions.ResourceAlreadyExistsException; import software.amazon.cloudformation.exceptions.ResourceNotFoundException; import software.amazon.cloudformation.exceptions.TerminalException; @@ -720,6 +721,40 @@ public void invokeHandler_throwsAmazonServiceException_returnsServiceException() } } + @Test + public void invokeHandler_throwsSDK2ServiceException_returnsServiceException() throws IOException { + wrapper.setInvokeHandlerException(CloudWatchLogsException.builder().build()); + + wrapper.setTransformResponse(resourceHandlerRequest); + + try (final InputStream in = loadRequestStream("create.request.json"); + final OutputStream out = new ByteArrayOutputStream()) { + final Context context = getLambdaContext(); + + wrapper.handleRequest(in, out, context); + + // verify initialiseRuntime was called and initialised dependencies + verifyInitialiseRuntime(); + + // all metrics should be published, once for a single invocation + verify(providerMetricsPublisher, times(1)).publishInvocationMetric(any(Instant.class), eq(Action.CREATE)); + verify(providerMetricsPublisher, times(1)).publishDurationMetric(any(Instant.class), eq(Action.CREATE), anyLong()); + + // failure metric should be published + verify(providerMetricsPublisher, times(1)).publishExceptionMetric(any(Instant.class), any(), + any(CloudWatchLogsException.class), any(HandlerErrorCode.class)); + + // verify that model validation occurred for CREATE/UPDATE/DELETE + verify(validator, times(1)).validateObject(any(JSONObject.class), any(JSONObject.class)); + + // verify output response + verifyHandlerResponse(out, + ProgressEvent.builder().errorCode(HandlerErrorCode.GeneralServiceException) + .status(OperationStatus.FAILED) + .message("some error (Service: null; Status Code: 0; Error Code: null; Request ID: null)").build()); + } + } + @Test public void invokeHandler_throwsResourceAlreadyExistsException_returnsAlreadyExists() throws IOException { // exceptions are caught consistently by LambdaWrapper