Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cloudwatchlogs</artifactId>
<version>2.5.69</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
Expand Down
33 changes: 19 additions & 14 deletions src/main/java/software/amazon/cloudformation/LambdaWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
Expand All @@ -44,6 +44,8 @@
import org.json.JSONObject;
import org.json.JSONTokener;

import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.cloudformation.exceptions.BaseHandlerException;
import software.amazon.cloudformation.exceptions.FileScrubberException;
Expand Down Expand Up @@ -80,6 +82,8 @@

public abstract class LambdaWrapper<ResourceT, CallbackT> implements RequestStreamHandler {

public static final SdkHttpClient HTTP_CLIENT = ApacheHttpClient.builder().build();

private static final List<Action> MUTATING_ACTIONS = Arrays.asList(Action.CREATE, Action.DELETE, Action.UPDATE);
private static final int INVOCATION_TIMEOUT_MS = 60000;

Expand Down Expand Up @@ -115,11 +119,11 @@ public abstract class LambdaWrapper<ResourceT, CallbackT> implements RequestStre
protected LambdaWrapper() {
this.platformCredentialsProvider = new SessionCredentialsProvider();
this.providerCredentialsProvider = new SessionCredentialsProvider();
this.cloudFormationProvider = new CloudFormationProvider(this.platformCredentialsProvider);
this.platformCloudWatchProvider = new CloudWatchProvider(this.platformCredentialsProvider);
this.providerCloudWatchProvider = new CloudWatchProvider(this.providerCredentialsProvider);
this.platformCloudWatchEventsProvider = new CloudWatchEventsProvider(this.platformCredentialsProvider);
this.cloudWatchLogsProvider = new CloudWatchLogsProvider(this.providerCredentialsProvider);
this.cloudFormationProvider = new CloudFormationProvider(this.platformCredentialsProvider, HTTP_CLIENT);
this.platformCloudWatchProvider = new CloudWatchProvider(this.platformCredentialsProvider, HTTP_CLIENT);
this.providerCloudWatchProvider = new CloudWatchProvider(this.providerCredentialsProvider, HTTP_CLIENT);
this.platformCloudWatchEventsProvider = new CloudWatchEventsProvider(this.platformCredentialsProvider, HTTP_CLIENT);
this.cloudWatchLogsProvider = new CloudWatchLogsProvider(this.providerCredentialsProvider, HTTP_CLIENT);
this.serializer = new Serializer();
this.validator = new Validator();
this.typeReference = getTypeReference();
Expand All @@ -137,16 +141,17 @@ public LambdaWrapper(final CallbackAdapter<ResourceT> callbackAdapter,
final MetricsPublisher providerMetricsPublisher,
final CloudWatchScheduler scheduler,
final SchemaValidator validator,
final Serializer serializer) {
final Serializer serializer,
final SdkHttpClient httpClient) {

this.callbackAdapter = callbackAdapter;
this.platformCredentialsProvider = platformCredentialsProvider;
this.providerCredentialsProvider = providerCredentialsProvider;
this.cloudFormationProvider = new CloudFormationProvider(this.platformCredentialsProvider);
this.platformCloudWatchProvider = new CloudWatchProvider(this.platformCredentialsProvider);
this.providerCloudWatchProvider = new CloudWatchProvider(this.providerCredentialsProvider);
this.platformCloudWatchEventsProvider = new CloudWatchEventsProvider(this.platformCredentialsProvider);
this.cloudWatchLogsProvider = new CloudWatchLogsProvider(this.providerCredentialsProvider);
this.cloudFormationProvider = new CloudFormationProvider(this.platformCredentialsProvider, httpClient);
this.platformCloudWatchProvider = new CloudWatchProvider(this.platformCredentialsProvider, httpClient);
this.providerCloudWatchProvider = new CloudWatchProvider(this.providerCredentialsProvider, httpClient);
this.platformCloudWatchEventsProvider = new CloudWatchEventsProvider(this.platformCredentialsProvider, httpClient);
this.cloudWatchLogsProvider = new CloudWatchLogsProvider(this.providerCredentialsProvider, httpClient);
this.providerEventsLogger = providerEventsLogger;
this.platformLambdaLogger = platformEventsLogger;
this.platformMetricsPublisher = platformMetricsPublisher;
Expand Down Expand Up @@ -245,7 +250,7 @@ public void handleRequest(final InputStream inputStream, final OutputStream outp
throw new TerminalException("No request object received");
}

String input = IOUtils.toString(inputStream, "UTF-8");
String input = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
JSONObject rawInput = new JSONObject(new JSONTokener(input));

// deserialize incoming payload to modelled request
Expand Down Expand Up @@ -483,7 +488,7 @@ private Response<ResourceT> createProgressResponse(final ProgressEvent<ResourceT
private void writeResponse(final OutputStream outputStream, final Response<ResourceT> response) throws IOException {

String output = this.serializer.serialize(response);
outputStream.write(output.getBytes(Charset.forName("UTF-8")));
outputStream.write(output.getBytes(StandardCharsets.UTF_8));
outputStream.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,35 @@

import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder;
import software.amazon.awssdk.awscore.client.builder.AwsSyncClientBuilder;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.http.SdkHttpClient;

public abstract class AmazonWebServicesProvider {

protected static final ClientOverrideConfiguration CONFIGURATION = ClientOverrideConfiguration.builder()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the available runtime, is 16 retries too many?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just ported it as is, but happy to tweak this if we have better values (the defaults?).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, default is 3 times I think (except 10 for DDB client). 16 seems too much.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since all aws clients are sharing the same HTTP client, do we want to increase the Maximum Connections?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 50 is fine, right? Given that the Lambda in each VM only really serves one request at a time (even if we create a few more connections for every request).

// Default Retry Condition of Retry Policy retries on Throttling and ClockSkew
// Exceptions
.retryPolicy(RetryPolicy.builder().numRetries(16).build()).build();

protected final CredentialsProvider credentialsProvider;
protected final SdkHttpClient httpClient;

protected AmazonWebServicesProvider(final CredentialsProvider credentialsProvider) {
protected AmazonWebServicesProvider(final CredentialsProvider credentialsProvider,
final SdkHttpClient httpClient) {
this.credentialsProvider = credentialsProvider;
this.httpClient = httpClient;
}

protected AwsCredentialsProvider getCredentialsProvider() {
return StaticCredentialsProvider.create(this.credentialsProvider.get());
}

protected <BuilderT extends AwsClientBuilder<BuilderT, ClientT> & AwsSyncClientBuilder<BuilderT, ClientT>,
ClientT> BuilderT defaultClient(final BuilderT builder) {
return builder.credentialsProvider(this.getCredentialsProvider()).overrideConfiguration(CONFIGURATION)
.httpClient(httpClient);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@

import java.net.URI;

import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.services.cloudformation.CloudFormationClient;

public class CloudFormationProvider extends AmazonWebServicesProvider {

private URI callbackEndpoint;

public CloudFormationProvider(final CredentialsProvider credentialsProvider) {
super(credentialsProvider);
public CloudFormationProvider(final CredentialsProvider credentialsProvider,
final SdkHttpClient httpClient) {
super(credentialsProvider, httpClient);
}

public void setCallbackEndpoint(final URI callbackEndpoint) {
this.callbackEndpoint = callbackEndpoint;
}

public CloudFormationClient get() {
return CloudFormationClient.builder().credentialsProvider(this.getCredentialsProvider())
return CloudFormationClient.builder().credentialsProvider(this.getCredentialsProvider()).httpClient(httpClient)
.endpointOverride(this.callbackEndpoint).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,17 @@
*/
package software.amazon.cloudformation.injection;

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient;

public class CloudWatchEventsProvider extends AmazonWebServicesProvider {

public CloudWatchEventsProvider(final CredentialsProvider credentialsProvider) {
super(credentialsProvider);
public CloudWatchEventsProvider(final CredentialsProvider credentialsProvider,
final SdkHttpClient httpClient) {
super(credentialsProvider, httpClient);
}

public CloudWatchEventsClient get() {
return CloudWatchEventsClient.builder().overrideConfiguration(ClientOverrideConfiguration.builder()
// Default Retry Condition of Retry Policy retries on Throttling and ClockSkew
// Exceptions
.retryPolicy(RetryPolicy.builder().numRetries(16).build()).build()).credentialsProvider(this.getCredentialsProvider())
.build();
return defaultClient(CloudWatchEventsClient.builder()).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,17 @@
*/
package software.amazon.cloudformation.injection;

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;

public class CloudWatchLogsProvider extends AmazonWebServicesProvider {

public CloudWatchLogsProvider(final CredentialsProvider credentialsProvider) {
super(credentialsProvider);
public CloudWatchLogsProvider(final CredentialsProvider credentialsProvider,
final SdkHttpClient httpClient) {
super(credentialsProvider, httpClient);
}

public CloudWatchLogsClient get() {
return CloudWatchLogsClient.builder().credentialsProvider(this.getCredentialsProvider())
.overrideConfiguration(ClientOverrideConfiguration.builder()
// Default Retry Condition of Retry Policy retries on Throttling and ClockSkew
// Exceptions
.retryPolicy(RetryPolicy.builder().numRetries(16).build()).build())
.build();
return defaultClient(CloudWatchLogsClient.builder()).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,17 @@
*/
package software.amazon.cloudformation.injection;

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;

public class CloudWatchProvider extends AmazonWebServicesProvider {

public CloudWatchProvider(final CredentialsProvider credentialsProvider) {
super(credentialsProvider);
public CloudWatchProvider(final CredentialsProvider credentialsProvider,
final SdkHttpClient httpClient) {
super(credentialsProvider, httpClient);
}

public CloudWatchClient get() {
return CloudWatchClient.builder().credentialsProvider(this.getCredentialsProvider())
.overrideConfiguration(ClientOverrideConfiguration.builder()
// Default Retry Condition of Retry Policy retries on Throttling and ClockSkew
// Exceptions
.retryPolicy(RetryPolicy.builder().numRetries(16).build()).build())
.build();
return defaultClient(CloudWatchClient.builder()).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import software.amazon.awssdk.core.SdkPojo;
import software.amazon.awssdk.utils.builder.SdkBuilder;

@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
public class AWSServiceSerdeModule extends Module {

public static class AWSSerializers extends Serializers.Base {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@
value="${checkstyle.suppressions.file}"
default="checkstyle-suppressions.xml"/>
</module>

<!-- Enable @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
<!-- Enable @SuppressWarnings annotation -->
<module name="SuppressWarningsHolder" />

<!-- Allow suppressing rules via comments. -->
<module name="SuppressionCommentFilter"/>
Expand Down
Loading