Skip to content

Commit 8da24cb

Browse files
authored
build(examples): Add example for the powertools-cloudformation module (#1089)
1 parent 5b1c2c4 commit 8da24cb

File tree

14 files changed

+739
-0
lines changed

14 files changed

+739
-0
lines changed

examples/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<module>powertools-examples-serialization</module>
2222
<module>powertools-examples-sqs</module>
2323
<module>powertools-examples-validation</module>
24+
<module>powertools-examples-cloudformation</module>
2425
</modules>
2526

2627
<!-- Don't deploy the examples -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Cloudformation Custom Resource Example
2+
3+
This project contains an example of Lambda function using the CloudFormation module of Powertools for AWS Lambda in Java. For more information on this module, please refer to the [documentation](https://awslabs.github.io/aws-lambda-powertools-java/utilities/custom_resources/).
4+
5+
## Deploy the sample application
6+
7+
This sample can be used either with the Serverless Application Model (SAM) or with CDK.
8+
9+
### Deploy with SAM CLI
10+
To use the SAM CLI, you need the following tools.
11+
12+
* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
13+
* Java 8 - [Install Java 8](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)
14+
* Maven - [Install Maven](https://maven.apache.org/install.html)
15+
* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
16+
17+
To build and deploy this application for the first time, run the following in your shell:
18+
19+
```bash
20+
cd infra/sam
21+
sam build
22+
sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-20230717
23+
```
24+
25+
### Deploy with CDK
26+
To use CDK you need the following tools.
27+
28+
* CDK - [Install CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html)
29+
* Java 8 - [Install Java 8](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)
30+
* Maven - [Install Maven](https://maven.apache.org/install.html)
31+
* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
32+
33+
To build and deploy this application for the first time, run the following in your shell:
34+
35+
```bash
36+
cd infra/cdk
37+
mvn package
38+
cdk synth
39+
cdk deploy -c BucketNameParam=my-unique-bucket-20230718
40+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.classpath.txt
2+
target
3+
.classpath
4+
.project
5+
.idea
6+
.settings
7+
.vscode
8+
*.iml
9+
10+
# CDK asset staging directory
11+
.cdk.staging
12+
cdk.out
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"app": "mvn -e -q compile exec:java",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"target",
11+
"pom.xml",
12+
"src/test"
13+
]
14+
},
15+
"context": {
16+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
17+
"@aws-cdk/core:checkSecretUsage": true,
18+
"@aws-cdk/core:target-partitions": [
19+
"aws",
20+
"aws-cn"
21+
],
22+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
23+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
24+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
25+
"@aws-cdk/aws-iam:minimizePolicies": true,
26+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
27+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
28+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
29+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
30+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
31+
"@aws-cdk/core:enablePartitionLiterals": true,
32+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
33+
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
34+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
35+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.myorg</groupId>
7+
<artifactId>powertools-examples-cloudformation-cdk</artifactId>
8+
<version>0.1</version>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<cdk.version>2.59.0</cdk.version>
13+
<constructs.version>[10.0.0,11.0.0)</constructs.version>
14+
</properties>
15+
16+
<build>
17+
<plugins>
18+
<plugin>
19+
<groupId>org.apache.maven.plugins</groupId>
20+
<artifactId>maven-compiler-plugin</artifactId>
21+
<version>3.8.1</version>
22+
<configuration>
23+
<source>8</source>
24+
<target>8</target>
25+
</configuration>
26+
</plugin>
27+
28+
<plugin>
29+
<groupId>org.codehaus.mojo</groupId>
30+
<artifactId>exec-maven-plugin</artifactId>
31+
<version>3.0.0</version>
32+
<configuration>
33+
<mainClass>com.myorg.PowertoolsExamplesCloudformationCdkApp</mainClass>
34+
</configuration>
35+
</plugin>
36+
</plugins>
37+
</build>
38+
39+
<dependencies>
40+
<!-- AWS Cloud Development Kit -->
41+
<dependency>
42+
<groupId>software.amazon.awscdk</groupId>
43+
<artifactId>aws-cdk-lib</artifactId>
44+
<version>${cdk.version}</version>
45+
</dependency>
46+
47+
<dependency>
48+
<groupId>software.constructs</groupId>
49+
<artifactId>constructs</artifactId>
50+
<version>${constructs.version}</version>
51+
</dependency>
52+
</dependencies>
53+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.myorg;
2+
3+
import software.amazon.awscdk.App;
4+
import software.amazon.awscdk.StackProps;
5+
6+
public class PowertoolsExamplesCloudformationCdkApp {
7+
public static void main(final String[] args) {
8+
App app = new App();
9+
10+
new PowertoolsExamplesCloudformationCdkStack(app, "PowertoolsExamplesCloudformationCdkStack", StackProps.builder()
11+
.build());
12+
13+
app.synth();
14+
}
15+
}
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.myorg;
2+
3+
import software.amazon.awscdk.Stack;
4+
import software.amazon.awscdk.*;
5+
import software.amazon.awscdk.services.iam.Effect;
6+
import software.amazon.awscdk.services.iam.PolicyStatement;
7+
import software.amazon.awscdk.services.iam.PolicyStatementProps;
8+
import software.amazon.awscdk.services.lambda.Code;
9+
import software.amazon.awscdk.services.lambda.Function;
10+
import software.amazon.awscdk.services.lambda.FunctionProps;
11+
import software.amazon.awscdk.services.lambda.Runtime;
12+
import software.amazon.awscdk.services.s3.assets.AssetOptions;
13+
import software.constructs.Construct;
14+
15+
import java.io.Serializable;
16+
import java.util.Arrays;
17+
import java.util.Collections;
18+
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
23+
import static java.util.Collections.singletonList;
24+
import static software.amazon.awscdk.BundlingOutput.NOT_ARCHIVED;
25+
26+
public class PowertoolsExamplesCloudformationCdkStack extends Stack {
27+
28+
public static final String SAMPLE_BUCKET_NAME = "sample-bucket-name-20230315-abc123";
29+
30+
public PowertoolsExamplesCloudformationCdkStack(final Construct scope, final String id) {
31+
this(scope, id, null);
32+
}
33+
34+
public PowertoolsExamplesCloudformationCdkStack(final Construct scope, final String id, final StackProps props) {
35+
super(scope, id, props);
36+
37+
38+
List<String> functionPackagingInstructions = Arrays.asList(
39+
"/bin/sh",
40+
"-c",
41+
"mvn clean install" +
42+
"&& mkdir /asset-output/lib" +
43+
"&& cp target/powertools-examples-cloudformation-*.jar /asset-output/lib"
44+
);
45+
BundlingOptions bundlingOptions = BundlingOptions.builder()
46+
.command(functionPackagingInstructions)
47+
.image(Runtime.JAVA_11.getBundlingImage())
48+
.volumes(singletonList(
49+
// Mount local .m2 repo to avoid download all the dependencies again inside the container
50+
DockerVolume.builder()
51+
.hostPath(System.getProperty("user.home") + "/.m2/")
52+
.containerPath("/root/.m2/")
53+
.build()
54+
))
55+
.user("root")
56+
.outputType(NOT_ARCHIVED)
57+
.build();
58+
59+
Function helloWorldFunction = new Function(this, "HelloWorldFunction", FunctionProps.builder()
60+
.runtime(Runtime.JAVA_11)
61+
.code(Code.fromAsset("../../", AssetOptions.builder().bundling(bundlingOptions)
62+
.build()))
63+
.handler("helloworld.App::handleRequest")
64+
.memorySize(512)
65+
.timeout(Duration.seconds(20))
66+
.environment(Collections
67+
.singletonMap("JAVA_TOOL_OPTIONS", "-XX:+TieredCompilation -XX:TieredStopAtLevel=1"))
68+
.build());
69+
helloWorldFunction.addToRolePolicy(new PolicyStatement(PolicyStatementProps.builder()
70+
.effect(Effect.ALLOW)
71+
.actions(Arrays.asList("s3:GetLifecycleConfiguration",
72+
"s3:PutLifecycleConfiguration",
73+
"s3:CreateBucket",
74+
"s3:ListBucket",
75+
"s3:DeleteBucket"))
76+
.resources(singletonList("*")).build()));
77+
78+
String bucketName = (String) this.getNode().tryGetContext("BucketNameParam");
79+
80+
Map<String, Serializable> crProperties = new HashMap<>();
81+
crProperties.put("BucketName", bucketName);
82+
CustomResource.Builder
83+
.create(this, "HelloWorldCustomResource")
84+
.serviceToken(helloWorldFunction.getFunctionArn())
85+
.properties(crProperties)
86+
.build();
87+
88+
}
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"RequestType": "Create",
3+
"ResponseURL": "http://pre-signed-S3-url-for-response",
4+
"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/MyStack/guid",
5+
"RequestId": "unique id for this create request",
6+
"ResourceType": "Custom::TestResource",
7+
"ResourceProperties": {
8+
"BucketName": "test-bucket-20230307-1",
9+
"RetentionDays" : 10,
10+
"StackName": "MyStack"
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"RequestType": "Delete",
3+
"ResponseURL": "http://pre-signed-S3-url-for-response",
4+
"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/MyStack/guid",
5+
"RequestId": "unique id for this create request",
6+
"ResourceType": "Custom::TestResource",
7+
"LogicalResourceId": "MyTestResource",
8+
"PhysicalResourceId": "test-bucket-20230307-1",
9+
"ResourceProperties": {
10+
"BucketName": "test-bucket-20230307-1",
11+
"RetentionDays" : 10,
12+
"StackName": "MyStack"
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"RequestType": "Update",
3+
"ResponseURL": "http://pre-signed-S3-url-for-response",
4+
"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/MyStack/guid",
5+
"RequestId": "unique id for this create request",
6+
"ResourceType": "Custom::TestResource",
7+
"LogicalResourceId": "MyTestResource",
8+
"PhysicalResourceId": "test-bucket-20230307-1",
9+
"ResourceProperties": {
10+
"BucketName": "test-bucket-20230307-1",
11+
"RetentionDays" : 100,
12+
"StackName": "MyStack"
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: >
4+
powertools-examples-cloudformation
5+
6+
Sample SAM Template for powertools-examples-cloudformation
7+
8+
Globals:
9+
Function:
10+
Timeout: 20
11+
12+
Parameters:
13+
BucketNameParam:
14+
Type: String
15+
16+
Resources:
17+
HelloWorldCustomResource:
18+
Type: AWS::CloudFormation::CustomResource
19+
Properties:
20+
ServiceToken: !GetAtt HelloWorldFunction.Arn
21+
BucketName: !Ref BucketNameParam
22+
23+
HelloWorldFunction:
24+
Type: AWS::Serverless::Function
25+
Properties:
26+
CodeUri: ../../
27+
Handler: helloworld.App::handleRequest
28+
Runtime: java11
29+
Architectures:
30+
- x86_64
31+
MemorySize: 512
32+
Policies:
33+
- Statement:
34+
- Sid: bucketaccess1
35+
Effect: Allow
36+
Action:
37+
- s3:GetLifecycleConfiguration
38+
- s3:PutLifecycleConfiguration
39+
- s3:CreateBucket
40+
- s3:ListBucket
41+
- s3:DeleteBucket
42+
Resource: '*'
43+
Environment:
44+
Variables:
45+
JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1
46+
47+
Outputs:
48+
HelloWorldFunction:
49+
Description: "Hello World Lambda Function ARN"
50+
Value: !GetAtt HelloWorldFunction.Arn

0 commit comments

Comments
 (0)