Skip to content

Commit 962dd84

Browse files
committed
Initial Commit
0 parents  commit 962dd84

File tree

12 files changed

+3768
-0
lines changed

12 files changed

+3768
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea
2+
**/node_modules
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env node
2+
import * as cdk from 'aws-cdk-lib';
3+
import {InfraPipelineStack} from '../lib/infra-pipeline-stack';
4+
import {ApplicationPipelineStack} from "../lib/application-pipeline-stack";
5+
6+
const app = new cdk.App();
7+
new ApplicationPipelineStack(app, 'ApplicationPipelineStack');
8+
new InfraPipelineStack(app, 'InfraPipelineStack');

infrastructure-cdk/cdk.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/infra-app.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
21+
"@aws-cdk/core:stackRelativeExports": true,
22+
"@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
23+
"@aws-cdk/aws-lambda:recognizeVersionProps": true,
24+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
25+
"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true,
26+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28+
"@aws-cdk/core:checkSecretUsage": true,
29+
"@aws-cdk/aws-iam:minimizePolicies": true,
30+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
31+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
32+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
33+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
34+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
35+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
36+
"@aws-cdk/core:enablePartitionLiterals": true,
37+
"@aws-cdk/core:target-partitions": [
38+
"aws",
39+
"aws-cn"
40+
]
41+
}
42+
}

infrastructure-cdk/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
roots: ['<rootDir>/test'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.tsx?$': 'ts-jest'
7+
}
8+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {Aws, CfnOutput, Stack, StackProps} from 'aws-cdk-lib';
2+
import {Construct} from 'constructs';
3+
import {JavaBuildPipeline} from "./constructs/java-build-pipeline";
4+
import {BlockPublicAccess, Bucket, BucketEncryption} from "aws-cdk-lib/aws-s3";
5+
import {ASSET_BUCKET_EXPORT_NAME, REPOSITORY_FILE_PATH} from "./shared-vars";
6+
7+
export class ApplicationPipelineStack extends Stack {
8+
constructor(scope: Construct, id: string, props?: StackProps) {
9+
super(scope, id, props);
10+
11+
const artefactBucket = new Bucket(this, 'ArtefactBucket', {
12+
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
13+
enforceSSL: true,
14+
encryption: BucketEncryption.S3_MANAGED
15+
});
16+
17+
new JavaBuildPipeline(this, 'java-app', {
18+
deployBucket: artefactBucket, repositoryName: REPOSITORY_FILE_PATH
19+
});
20+
21+
new CfnOutput(this, 'AssetBucketName', {
22+
value: artefactBucket.bucketName,
23+
description: "Artefact Bucket name storing application binaries",
24+
exportName: ASSET_BUCKET_EXPORT_NAME
25+
});
26+
27+
new CfnOutput(this, 'AssetBucketLink', {
28+
value: "https://s3.console.aws.amazon.com/s3/buckets/" + artefactBucket.bucketName + "?region=" + Aws.REGION + "&tab=objects",
29+
description: "Artefact Bucket Link"
30+
});
31+
32+
}
33+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import {Construct} from "constructs";
2+
import {BuildSpec, LinuxBuildImage, PipelineProject} from "aws-cdk-lib/aws-codebuild";
3+
import {IBucket} from "aws-cdk-lib/aws-s3";
4+
import {Artifact, Pipeline} from "aws-cdk-lib/aws-codepipeline";
5+
import {
6+
CodeBuildAction,
7+
LambdaInvokeAction,
8+
ManualApprovalAction,
9+
S3DeployAction
10+
} from "aws-cdk-lib/aws-codepipeline-actions";
11+
import {IFunction} from "aws-cdk-lib/aws-lambda/lib/function-base";
12+
13+
14+
interface JavaBuildPipelineProps {
15+
repositoryName: string
16+
deployBucket: IBucket
17+
projectRoot?: string
18+
deployBucketBasePath?: string
19+
postActionLambda?: IFunction
20+
}
21+
22+
export class JavaBuildPipeline extends Construct {
23+
constructor(scope: Construct, id: string, props: JavaBuildPipelineProps) {
24+
super(scope, id);
25+
26+
let directory = ".";
27+
let s3BasePath = "jars";
28+
if (props.projectRoot) {
29+
directory = props.projectRoot;
30+
}
31+
if (props.deployBucketBasePath) {
32+
s3BasePath = props.deployBucketBasePath
33+
}
34+
35+
const sourceAsset = new Artifact();
36+
const defaultBuildSpec = BuildSpec.fromObject({
37+
version: '0.2',
38+
phases: {
39+
install: {
40+
"runtime-versions": {
41+
"java": "corretto11"
42+
}
43+
},
44+
build: {
45+
commands: [
46+
`curl ${props.repositoryName} --output app.zip`, // Download zip directly from Github
47+
'unzip app.zip',
48+
`cd ${directory}`,
49+
'mvn clean package -B',
50+
`mkdir -p ${s3BasePath}`,
51+
`cp target/*.jar ${s3BasePath}/`
52+
]
53+
}
54+
},
55+
artifacts: {
56+
files: [
57+
`${s3BasePath}/*.jar`
58+
],
59+
'discard-paths': false,
60+
'base-directory': directory
61+
}
62+
});
63+
64+
const project = new PipelineProject(this, 'Pipeline', {
65+
environment: {
66+
buildImage: LinuxBuildImage.STANDARD_5_0
67+
},
68+
buildSpec: defaultBuildSpec
69+
});
70+
71+
const buildOutput = new Artifact();
72+
73+
const pipeline = new Pipeline(this, 'CodePipeline', {
74+
stages: [
75+
// In real world use code snippet like below to work with repository
76+
//
77+
// {
78+
// stageName: "source", actions: [new GitHubSourceAction({
79+
// actionName: "CodeCheckout",
80+
// oauthToken: SecretValue.secretsManager("github-secret"),
81+
// output: sourceAsset,
82+
// owner: "some-owner",
83+
// repo: props.repositoryName
84+
// })]
85+
// },
86+
{
87+
stageName: "build", actions: [new CodeBuildAction({
88+
actionName: "CodeBuild", input: sourceAsset, project: project, outputs: [buildOutput]
89+
})]
90+
}, {
91+
stageName: "saveArtefact", actions: [new S3DeployAction({
92+
bucket: props.deployBucket,
93+
actionName: "SaveArtefact",
94+
input: buildOutput,
95+
extract: true
96+
})]
97+
}, {
98+
stageName: "approval",
99+
actions: [new ManualApprovalAction({
100+
actionName: "Manual"
101+
})]
102+
}]
103+
});
104+
105+
if (props.postActionLambda) {
106+
pipeline.addStage({
107+
stageName: "deploy", actions: [new LambdaInvokeAction({
108+
actionName: "Deploy",
109+
lambda: props.postActionLambda
110+
})]
111+
});
112+
}
113+
}
114+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {Stack, StackProps} from 'aws-cdk-lib';
2+
import {Construct} from 'constructs';
3+
import {CodePipeline, ShellStep} from "aws-cdk-lib/pipelines";
4+
import {RealtimeApplication} from "./real-time-application";
5+
import {REPOSITORY_FILE_PATH} from "./shared-vars";
6+
7+
export class InfraPipelineStack extends Stack {
8+
constructor(scope: Construct, id: string, props?: StackProps) {
9+
super(scope, id, props);
10+
11+
12+
const pipeline = new CodePipeline(this, 'Pipeline', {
13+
selfMutation: false,
14+
synth: new ShellStep('Synth', {
15+
commands: [
16+
"curl " + REPOSITORY_FILE_PATH + " --output app.zip",
17+
"unzip app.zip",
18+
"cd infrastructure-cdk",
19+
"npm ci",
20+
"npm run build",
21+
"npm cdk synth"
22+
],
23+
primaryOutputDirectory: 'infrastructure-cdk/cdk.out'
24+
})
25+
});
26+
27+
pipeline.addStage(new RealtimeApplication(this, 'app'));
28+
}
29+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {Aws, Fn, Stage, StageProps} from "aws-cdk-lib";
2+
import {Construct} from "constructs";
3+
import {Code, Function, Runtime} from "aws-cdk-lib/aws-lambda";
4+
import {Stream, StreamEncryption, StreamMode} from "aws-cdk-lib/aws-kinesis";
5+
import * as kda from "@aws-cdk/aws-kinesisanalytics-flink-alpha";
6+
import {APPLICATION_NAME, ASSET_BUCKET_EXPORT_NAME} from "./shared-vars";
7+
import {Bucket} from "aws-cdk-lib/aws-s3";
8+
9+
10+
export class RealtimeApplication extends Stage {
11+
constructor(scope: Construct, id: string, props?: StageProps) {
12+
super(scope, id, props);
13+
14+
const assetBucket = Bucket.fromBucketName(this, 'imported-asset-bucket', Fn.importValue(ASSET_BUCKET_EXPORT_NAME));
15+
16+
const stream = new Stream(this, 'raw', {
17+
streamMode: StreamMode.PROVISIONED,
18+
shardCount: 1,
19+
encryption: StreamEncryption.MANAGED
20+
});
21+
22+
const dataSourceFn = new Function(this, 'data-source', {
23+
code: Code.fromInline(
24+
"import boto3\n" +
25+
"import os\n\n" +
26+
"kinesis = boto3.client('kinesis')\n\n" +
27+
"def lambda_handler(event, context):\n" +
28+
" kinesis.put_record(StreamName=os.environ['STREAM_NAME']), Data=b'{\"message\":\"This is the test message from the lambda\"}', PartitionKey='default')\n"
29+
),
30+
handler: "index.lambda_handler",
31+
runtime: Runtime.PYTHON_3_9,
32+
environment: {
33+
STREAM_NAME: stream.streamName
34+
}
35+
});
36+
37+
stream.grantWrite(dataSourceFn);
38+
39+
const application = new kda.Application(this, 'app', {
40+
code: kda.ApplicationCode.fromBucket(assetBucket, "jars/" + APPLICATION_NAME + "-1.0.0.jar"),
41+
runtime: kda.Runtime.FLINK_1_13,
42+
propertyGroups: {
43+
"KinesisReader": {
44+
"input.stream.name": stream.streamName,
45+
"aws.region": Aws.REGION,
46+
"flink.stream.initpos": "LATEST"
47+
},
48+
},
49+
snapshotsEnabled: false,
50+
parallelismPerKpu: 1
51+
}
52+
);
53+
54+
stream.grantRead(application);
55+
}
56+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const REPOSITORY_FILE_PATH = "aws-samples/automate-deployment-and-version-update-of-kda-application"
2+
export const APPLICATION_NAME = "kinesis-analytics-application"
3+
export const ASSET_BUCKET_EXPORT_NAME = "Blog::Artefact::BucketName"

0 commit comments

Comments
 (0)