Skip to content

Commit efb884c

Browse files
committed
Fix CDK Stack creation in e2e tests.
1 parent 0358d64 commit efb884c

File tree

2 files changed

+56
-49
lines changed

2 files changed

+56
-49
lines changed

powertools-e2e-tests/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
<properties>
3131
<maven.compiler.source>11</maven.compiler.source>
3232
<maven.compiler.target>11</maven.compiler.target>
33-
<constructs.version>10.3.0</constructs.version>
34-
<cdk.version>2.162.1</cdk.version>
33+
<constructs.version>10.4.2</constructs.version>
34+
<cdk.version>2.186.0</cdk.version>
3535
</properties>
3636

3737
<dependencies>
@@ -231,4 +231,4 @@
231231
</profile>
232232
</profiles>
233233

234-
</project>
234+
</project>

powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import static java.util.Collections.singletonList;
1818

19-
import com.fasterxml.jackson.databind.JsonNode;
2019
import java.io.File;
2120
import java.io.IOException;
2221
import java.nio.file.Paths;
@@ -27,13 +26,18 @@
2726
import java.util.Objects;
2827
import java.util.UUID;
2928
import java.util.stream.Collectors;
29+
3030
import org.slf4j.Logger;
3131
import org.slf4j.LoggerFactory;
3232
import org.yaml.snakeyaml.Yaml;
33+
34+
import com.fasterxml.jackson.databind.JsonNode;
35+
3336
import software.amazon.awscdk.App;
3437
import software.amazon.awscdk.BundlingOptions;
3538
import software.amazon.awscdk.BundlingOutput;
3639
import software.amazon.awscdk.CfnOutput;
40+
import software.amazon.awscdk.DefaultStackSynthesizer;
3741
import software.amazon.awscdk.DockerVolume;
3842
import software.amazon.awscdk.Duration;
3943
import software.amazon.awscdk.RemovalPolicy;
@@ -45,7 +49,11 @@
4549
import software.amazon.awscdk.services.appconfig.CfnDeploymentStrategy;
4650
import software.amazon.awscdk.services.appconfig.CfnEnvironment;
4751
import software.amazon.awscdk.services.appconfig.CfnHostedConfigurationVersion;
48-
import software.amazon.awscdk.services.dynamodb.*;
52+
import software.amazon.awscdk.services.dynamodb.Attribute;
53+
import software.amazon.awscdk.services.dynamodb.AttributeType;
54+
import software.amazon.awscdk.services.dynamodb.BillingMode;
55+
import software.amazon.awscdk.services.dynamodb.StreamViewType;
56+
import software.amazon.awscdk.services.dynamodb.Table;
4957
import software.amazon.awscdk.services.iam.PolicyStatement;
5058
import software.amazon.awscdk.services.kinesis.Stream;
5159
import software.amazon.awscdk.services.kinesis.StreamMode;
@@ -89,7 +97,8 @@
8997
* CloudWatch log groups, ...
9098
* <br/>
9199
* It uses the Cloud Development Kit (CDK) to define required resources. The CDK stack is then synthesized to retrieve
92-
* the CloudFormation templates and the assets (function jars). Assets are uploaded to S3 (with the SDK `PutObjectRequest`)
100+
* the CloudFormation templates and the assets (function jars). Assets are uploaded to S3 (with the SDK
101+
* `PutObjectRequest`)
93102
* and the CloudFormation stack is created (with the SDK `createStack`)
94103
*/
95104
public class Infrastructure {
@@ -174,11 +183,11 @@ public Map<String, String> deploy() {
174183
.onFailure(OnFailure.ROLLBACK)
175184
.capabilities(Capability.CAPABILITY_IAM)
176185
.build());
177-
WaiterResponse<DescribeStacksResponse> waiterResponse =
178-
cfn.waiter().waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build());
186+
WaiterResponse<DescribeStacksResponse> waiterResponse = cfn.waiter()
187+
.waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build());
179188
if (waiterResponse.matched().response().isPresent()) {
180-
software.amazon.awssdk.services.cloudformation.model.Stack deployedStack =
181-
waiterResponse.matched().response().get().stacks().get(0);
189+
software.amazon.awssdk.services.cloudformation.model.Stack deployedStack = waiterResponse.matched()
190+
.response().get().stacks().get(0);
182191
LOG.info("Stack " + deployedStack.stackName() + " successfully deployed");
183192
Map<String, String> outputs = new HashMap<>();
184193
deployedStack.outputs().forEach(output -> outputs.put(output.outputKey(), output.outputValue()));
@@ -203,7 +212,11 @@ public void destroy() {
203212
*/
204213
private Stack createStackWithLambda() {
205214
boolean createTableForAsyncTests = false;
206-
Stack stack = new Stack(app, stackName);
215+
final Stack e2eStack = Stack.Builder.create(app, stackName)
216+
.synthesizer(DefaultStackSynthesizer.Builder.create()
217+
.generateBootstrapVersionRule(false) // Disable bootstrap version check
218+
.build())
219+
.build();
207220

208221
List<String> packagingInstruction = Arrays.asList(
209222
"/bin/sh",
@@ -213,8 +226,7 @@ private Stack createStackWithLambda() {
213226
" -Dmaven.test.skip=true " +
214227
" -Dmaven.compiler.source=" + runtime.getMvnProperty() +
215228
" -Dmaven.compiler.target=" + runtime.getMvnProperty() +
216-
" && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"
217-
);
229+
" && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/");
218230

219231
BundlingOptions.Builder builderOptions = BundlingOptions.builder()
220232
.command(packagingInstruction)
@@ -224,20 +236,19 @@ private Stack createStackWithLambda() {
224236
DockerVolume.builder()
225237
.hostPath(System.getProperty("user.home") + "/.m2/")
226238
.containerPath("/root/.m2/")
227-
.build()
228-
))
239+
.build()))
229240
.user("root")
230241
.outputType(BundlingOutput.ARCHIVED);
231242

232243
functionName = stackName + "-function";
233-
CfnOutput.Builder.create(stack, FUNCTION_NAME_OUTPUT)
244+
CfnOutput.Builder.create(e2eStack, FUNCTION_NAME_OUTPUT)
234245
.value(functionName)
235246
.build();
236247

237248
LOG.debug("Building Lambda function with command " +
238249
packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]")));
239250
Function function = Function.Builder
240-
.create(stack, functionName)
251+
.create(e2eStack, functionName)
241252
.code(Code.fromAsset("handlers/", AssetOptions.builder()
242253
.bundling(builderOptions
243254
.command(packagingInstruction)
@@ -253,15 +264,15 @@ private Stack createStackWithLambda() {
253264
.build();
254265

255266
LogGroup.Builder
256-
.create(stack, functionName + "-logs")
267+
.create(e2eStack, functionName + "-logs")
257268
.logGroupName("/aws/lambda/" + functionName)
258269
.retention(RetentionDays.ONE_DAY)
259270
.removalPolicy(RemovalPolicy.DESTROY)
260271
.build();
261272

262273
if (!StringUtils.isEmpty(idempotencyTable)) {
263274
Table table = Table.Builder
264-
.create(stack, "IdempotencyTable")
275+
.create(e2eStack, "IdempotencyTable")
265276
.billingMode(BillingMode.PAY_PER_REQUEST)
266277
.removalPolicy(RemovalPolicy.DESTROY)
267278
.partitionKey(Attribute.builder().name("id").type(AttributeType.STRING).build())
@@ -275,7 +286,7 @@ private Stack createStackWithLambda() {
275286

276287
if (!StringUtils.isEmpty(queue)) {
277288
Queue sqsQueue = Queue.Builder
278-
.create(stack, "SQSQueue")
289+
.create(e2eStack, "SQSQueue")
279290
.queueName(queue)
280291
.visibilityTimeout(Duration.seconds(timeout * 6))
281292
.retentionPeriod(Duration.seconds(timeout * 6))
@@ -293,14 +304,14 @@ private Stack createStackWithLambda() {
293304
.build();
294305
function.addEventSource(sqsEventSource);
295306
CfnOutput.Builder
296-
.create(stack, "QueueURL")
307+
.create(e2eStack, "QueueURL")
297308
.value(sqsQueue.getQueueUrl())
298309
.build();
299310
createTableForAsyncTests = true;
300311
}
301312
if (!StringUtils.isEmpty(kinesisStream)) {
302313
Stream stream = Stream.Builder
303-
.create(stack, "KinesisStream")
314+
.create(e2eStack, "KinesisStream")
304315
.streamMode(StreamMode.ON_DEMAND)
305316
.streamName(kinesisStream)
306317
.build();
@@ -316,13 +327,13 @@ private Stack createStackWithLambda() {
316327
.build();
317328
function.addEventSource(kinesisEventSource);
318329
CfnOutput.Builder
319-
.create(stack, "KinesisStreamName")
330+
.create(e2eStack, "KinesisStreamName")
320331
.value(stream.getStreamName())
321332
.build();
322333
}
323334

324335
if (!StringUtils.isEmpty(ddbStreamsTableName)) {
325-
Table ddbStreamsTable = Table.Builder.create(stack, "DDBStreamsTable")
336+
Table ddbStreamsTable = Table.Builder.create(e2eStack, "DDBStreamsTable")
326337
.tableName(ddbStreamsTableName)
327338
.stream(StreamViewType.KEYS_ONLY)
328339
.removalPolicy(RemovalPolicy.DESTROY)
@@ -336,12 +347,12 @@ private Stack createStackWithLambda() {
336347
.reportBatchItemFailures(true)
337348
.build();
338349
function.addEventSource(ddbEventSource);
339-
CfnOutput.Builder.create(stack, "DdbStreamsTestTable").value(ddbStreamsTable.getTableName()).build();
350+
CfnOutput.Builder.create(e2eStack, "DdbStreamsTestTable").value(ddbStreamsTable.getTableName()).build();
340351
}
341352

342353
if (!StringUtils.isEmpty(largeMessagesBucket)) {
343354
Bucket offloadBucket = Bucket.Builder
344-
.create(stack, "LargeMessagesOffloadBucket")
355+
.create(e2eStack, "LargeMessagesOffloadBucket")
345356
.removalPolicy(RemovalPolicy.RETAIN) // autodelete does not work without cdk deploy
346357
.bucketName(largeMessagesBucket)
347358
.build();
@@ -352,19 +363,19 @@ private Stack createStackWithLambda() {
352363

353364
if (appConfig != null) {
354365
CfnApplication app = CfnApplication.Builder
355-
.create(stack, "AppConfigApp")
366+
.create(e2eStack, "AppConfigApp")
356367
.name(appConfig.getApplication())
357368
.build();
358369

359370
CfnEnvironment environment = CfnEnvironment.Builder
360-
.create(stack, "AppConfigEnvironment")
371+
.create(e2eStack, "AppConfigEnvironment")
361372
.applicationId(app.getRef())
362373
.name(appConfig.getEnvironment())
363374
.build();
364375

365376
// Create a fast deployment strategy, so we don't have to wait ages
366377
CfnDeploymentStrategy fastDeployment = CfnDeploymentStrategy.Builder
367-
.create(stack, "AppConfigDeployment")
378+
.create(e2eStack, "AppConfigDeployment")
368379
.name("FastDeploymentStrategy")
369380
.deploymentDurationInMinutes(0)
370381
.finalBakeTimeInMinutes(0)
@@ -377,28 +388,27 @@ private Stack createStackWithLambda() {
377388
.create()
378389
.actions(singletonList("appconfig:*"))
379390
.resources(singletonList("*"))
380-
.build()
381-
);
391+
.build());
382392

383393
CfnDeployment previousDeployment = null;
384394
for (Map.Entry<String, String> entry : appConfig.getConfigurationValues().entrySet()) {
385395
CfnConfigurationProfile configProfile = CfnConfigurationProfile.Builder
386-
.create(stack, "AppConfigProfileFor" + entry.getKey())
396+
.create(e2eStack, "AppConfigProfileFor" + entry.getKey())
387397
.applicationId(app.getRef())
388398
.locationUri("hosted")
389399
.name(entry.getKey())
390400
.build();
391401

392402
CfnHostedConfigurationVersion configVersion = CfnHostedConfigurationVersion.Builder
393-
.create(stack, "AppConfigHostedVersionFor" + entry.getKey())
403+
.create(e2eStack, "AppConfigHostedVersionFor" + entry.getKey())
394404
.applicationId(app.getRef())
395405
.contentType("text/plain")
396406
.configurationProfileId(configProfile.getRef())
397407
.content(entry.getValue())
398408
.build();
399409

400410
CfnDeployment deployment = CfnDeployment.Builder
401-
.create(stack, "AppConfigDepoymentFor" + entry.getKey())
411+
.create(e2eStack, "AppConfigDepoymentFor" + entry.getKey())
402412
.applicationId(app.getRef())
403413
.environmentId(environment.getRef())
404414
.deploymentStrategyId(fastDeployment.getRef())
@@ -415,7 +425,7 @@ private Stack createStackWithLambda() {
415425
}
416426
if (createTableForAsyncTests) {
417427
Table table = Table.Builder
418-
.create(stack, "TableForAsyncTests")
428+
.create(e2eStack, "TableForAsyncTests")
419429
.billingMode(BillingMode.PAY_PER_REQUEST)
420430
.removalPolicy(RemovalPolicy.DESTROY)
421431
.partitionKey(Attribute.builder().name("functionName").type(AttributeType.STRING).build())
@@ -424,10 +434,10 @@ private Stack createStackWithLambda() {
424434

425435
table.grantReadWriteData(function);
426436
function.addEnvironment("TABLE_FOR_ASYNC_TESTS", table.getTableName());
427-
CfnOutput.Builder.create(stack, "TableNameForAsyncTests").value(table.getTableName()).build();
437+
CfnOutput.Builder.create(e2eStack, "TableNameForAsyncTests").value(table.getTableName()).build();
428438
}
429439

430-
return stack;
440+
return e2eStack;
431441
}
432442

433443
/**
@@ -444,13 +454,13 @@ private void synthesize() {
444454
*/
445455
private void uploadAssets() {
446456
Map<String, Asset> assets = findAssets();
447-
assets.forEach((objectKey, asset) ->
448-
{
457+
assets.forEach((objectKey, asset) -> {
449458
if (!asset.assetPath.endsWith(".jar")) {
450459
return;
451460
}
452-
ListObjectsV2Response objects =
453-
s3.listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build());
461+
462+
ListObjectsV2Response objects = s3
463+
.listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build());
454464
if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) {
455465
LOG.debug("Asset already exists, skipping");
456466
return;
@@ -472,14 +482,13 @@ private Map<String, Asset> findAssets() {
472482
JsonNode jsonNode = JsonConfig.get().getObjectMapper()
473483
.readTree(new File(cfnAssetDirectory, stackName + ".assets.json"));
474484
JsonNode files = jsonNode.get("files");
475-
files.iterator().forEachRemaining(file ->
476-
{
485+
files.iterator().forEachRemaining(file -> {
477486
String assetPath = file.get("source").get("path").asText();
478487
String assetPackaging = file.get("source").get("packaging").asText();
479-
String bucketName =
480-
file.get("destinations").get("current_account-current_region").get("bucketName").asText();
481-
String objectKey =
482-
file.get("destinations").get("current_account-current_region").get("objectKey").asText();
488+
String bucketName = file.get("destinations").get("current_account-current_region").get("bucketName")
489+
.asText();
490+
String objectKey = file.get("destinations").get("current_account-current_region").get("objectKey")
491+
.asText();
483492
Asset asset = new Asset(assetPath, assetPackaging, bucketName.replace("${AWS::AccountId}", account)
484493
.replace("${AWS::Region}", region.toString()));
485494
assets.put(objectKey, asset);
@@ -509,8 +518,6 @@ private Builder() {
509518
runtime = mapRuntimeVersion("JAVA_VERSION");
510519
}
511520

512-
513-
514521
private JavaRuntime mapRuntimeVersion(String environmentVariableName) {
515522
String javaVersion = System.getenv(environmentVariableName); // must be set in GitHub actions
516523
JavaRuntime ret = null;

0 commit comments

Comments
 (0)