Skip to content

Commit

Permalink
feat: add example that mixes CDKTF and AWS CDK resources
Browse files Browse the repository at this point in the history
lambdas are defined using CDKTF constructs and the step function state machine is defined using AWS CDK constructs
  • Loading branch information
ansgarm committed Mar 17, 2022
1 parent 02f2687 commit a37039e
Show file tree
Hide file tree
Showing 16 changed files with 4,746 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions examples/typescript-step-functions-mixed/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
*.d.ts
*.js
node_modules
cdktf.out
cdktf.log
*terraform.*.tfstate*
.gen
.terraform
tsconfig.tsbuildinfo
!jest.config.js
!setupJest.js
!tsconfig.json
4 changes: 4 additions & 0 deletions examples/typescript-step-functions-mixed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Code inspired by
https://sbstjn.com/blog/aws-cdk-state-machine-step-functions-lambda/

This version of the step functions example defines the lambda functions using CDKTF constructs
4 changes: 4 additions & 0 deletions examples/typescript-step-functions-mixed/cdktf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"app": "npm run --silent compile && node main.js",
"language": "typescript"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions examples/typescript-step-functions-mixed/fn-generate-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const generate = () => Math.random().toString(36).substring(7);

export const handler = async () => ({ value: generate() });
3 changes: 3 additions & 0 deletions examples/typescript-step-functions-mixed/fn-reverse-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const handler = async (state: { value: string }) => ({
value: state.value.split("").reverse().join(""),
});
13 changes: 13 additions & 0 deletions examples/typescript-step-functions-mixed/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* For a detailed explanation regarding each configuration property, visit:
* https://jestjs.io/docs/configuration
*/

module.exports = {
testMatch: ['**/*.test.ts'],
modulePathIgnorePatterns: [".yalc"],
preset: "ts-jest",
clearMocks: true,
coverageProvider: "v8",
setupFilesAfterEnv: ["./setupJest.js"],
};
150 changes: 150 additions & 0 deletions examples/typescript-step-functions-mixed/main.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { Testing } from "cdktf";
import "cdktf/lib/testing/adapters/jest";
import { StepFunctionsStack } from "./main";

describe("typescript-state-machine", () => {
it("should synthesize", () => {
const stack = new StepFunctionsStack(Testing.app(), "test");

const synthResult = Testing.synth(stack);

expect(synthResult).toMatchInlineSnapshot(`
"{
\\"data\\": {
\\"aws_partition\\": {
\\"adapter_aws-partition_5B16AD9D\\": {
}
},
\\"aws_region\\": {
\\"adapter_aws-region_F8878EF0\\": {
}
}
},
\\"output\\": {
\\"generate-id_generate-id-c8e9be4a2f33ecc14e138a018899daed079e618acb-lambda-arn_39F35C88\\": {
\\"value\\": \\"\${aws_lambda_function.generate-id_fn_99320B4B.arn}\\"
},
\\"reverse-id_reverse-id-c80e28e7990db1dae069bd131f26434d1b4d867e38-lambda-arn_46CC1D58\\": {
\\"value\\": \\"\${aws_lambda_function.reverse-id_fn_A44557C2.arn}\\"
}
},
\\"provider\\": {
\\"aws\\": [
{
\\"region\\": \\"us-west-2\\"
}
]
},
\\"resource\\": {
\\"aws_cloudcontrolapi_resource\\": {
\\"adapter_StateMachine2E01A3A5_637DDDC7\\": {
\\"depends_on\\": [
\\"time_sleep.adapter_StateMachineRoleB840431D_sleep_StateMachineRoleB840431D_89BC4BE8\\"
],
\\"desired_state\\": \\"\${jsonencode({RoleArn = aws_iam_role.adapter_StateMachineRoleB840431D_34E24F0D.arn, DefinitionString = join(\\\\\\"\\\\\\", [\\\\\\"{\\\\\\\\\\\\\\"StartAt\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Generate ID\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"States\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"Generate ID\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"Next\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Wait 1 Second\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Retry\\\\\\\\\\\\\\":[{\\\\\\\\\\\\\\"ErrorEquals\\\\\\\\\\\\\\":[\\\\\\\\\\\\\\"Lambda.ServiceException\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Lambda.AWSLambdaException\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Lambda.SdkClientException\\\\\\\\\\\\\\"],\\\\\\\\\\\\\\"IntervalSeconds\\\\\\\\\\\\\\":2,\\\\\\\\\\\\\\"MaxAttempts\\\\\\\\\\\\\\":6,\\\\\\\\\\\\\\"BackoffRate\\\\\\\\\\\\\\":2}],\\\\\\\\\\\\\\"Type\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Task\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"OutputPath\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"$.Payload\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Resource\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"arn:\\\\\\", data.aws_partition.adapter_aws-partition_5B16AD9D.partition, join(\\\\\\"\\\\\\", [\\\\\\":states:::lambda:invoke\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Parameters\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"FunctionName\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"\\\\\\", aws_lambda_function.generate-id_fn_99320B4B.arn, \\\\\\"\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Payload.$\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"$\\\\\\\\\\\\\\"}},\\\\\\\\\\\\\\"Wait 1 Second\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"Type\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Wait\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Seconds\\\\\\\\\\\\\\":1,\\\\\\\\\\\\\\"Next\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Reverse ID\\\\\\\\\\\\\\"},\\\\\\\\\\\\\\"Reverse ID\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"End\\\\\\\\\\\\\\":true,\\\\\\\\\\\\\\"Retry\\\\\\\\\\\\\\":[{\\\\\\\\\\\\\\"ErrorEquals\\\\\\\\\\\\\\":[\\\\\\\\\\\\\\"Lambda.ServiceException\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Lambda.AWSLambdaException\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Lambda.SdkClientException\\\\\\\\\\\\\\"],\\\\\\\\\\\\\\"IntervalSeconds\\\\\\\\\\\\\\":2,\\\\\\\\\\\\\\"MaxAttempts\\\\\\\\\\\\\\":6,\\\\\\\\\\\\\\"BackoffRate\\\\\\\\\\\\\\":2}],\\\\\\\\\\\\\\"Type\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Task\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"OutputPath\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"$.Payload\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Resource\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"arn:\\\\\\"]), data.aws_partition.adapter_aws-partition_5B16AD9D.partition, join(\\\\\\"\\\\\\", [\\\\\\":states:::lambda:invoke\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Parameters\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\"FunctionName\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"\\\\\\", aws_lambda_function.reverse-id_fn_A44557C2.arn, \\\\\\"\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"Payload.$\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"$\\\\\\\\\\\\\\"}}},\\\\\\\\\\\\\\"TimeoutSeconds\\\\\\\\\\\\\\":300}\\\\\\"])])})}\\",
\\"type_name\\": \\"AWS::StepFunctions::StateMachine\\"
}
},
\\"aws_cloudwatch_log_group\\": {
\\"generate-id_snoop-log-group_D659273F\\": {
\\"name\\": \\"/aws/lambda/generate-id-c8e9be4a2f33ecc14e138a018899daed079e618acb\\",
\\"retention_in_days\\": 7
},
\\"reverse-id_snoop-log-group_FAF8FFFD\\": {
\\"name\\": \\"/aws/lambda/reverse-id-c80e28e7990db1dae069bd131f26434d1b4d867e38\\",
\\"retention_in_days\\": 7
}
},
\\"aws_iam_policy\\": {
\\"adapter_StateMachineRoleDefaultPolicyDF1E6607_28877BB8\\": {
\\"policy\\": \\"\${jsonencode({Statement = [{Action = \\\\\\"lambda:InvokeFunction\\\\\\", Effect = \\\\\\"Allow\\\\\\", Resource = aws_lambda_function.generate-id_fn_99320B4B.arn}, {Action = \\\\\\"lambda:InvokeFunction\\\\\\", Effect = \\\\\\"Allow\\\\\\", Resource = aws_lambda_function.reverse-id_fn_A44557C2.arn}], Version = \\\\\\"2012-10-17\\\\\\"})}\\"
},
\\"generate-id_server-role_role-policy_6FBD6C53\\": {
\\"name\\": \\"c8db9d3041a90e1d114b187c0e984994c2bd27ae7b-role-policy\\",
\\"path\\": \\"/\\",
\\"policy\\": \\"{\\\\\\"Version\\\\\\":\\\\\\"2012-10-17\\\\\\",\\\\\\"Statement\\\\\\":[{\\\\\\"Action\\\\\\":[\\\\\\"logs:CreateLogStream\\\\\\",\\\\\\"logs:PutLogEvents\\\\\\"],\\\\\\"Resource\\\\\\":[\\\\\\"\${aws_cloudwatch_log_group.generate-id_snoop-log-group_D659273F.arn}\\\\\\",\\\\\\"\${aws_cloudwatch_log_group.generate-id_snoop-log-group_D659273F.arn}:log-stream:*\\\\\\"],\\\\\\"Effect\\\\\\":\\\\\\"Allow\\\\\\"}]}\\"
},
\\"reverse-id_server-role_role-policy_BEA9EC5B\\": {
\\"name\\": \\"c8a001c1b2c37e8cea98f2ebcfb39a6834c9931a7d-role-policy\\",
\\"path\\": \\"/\\",
\\"policy\\": \\"{\\\\\\"Version\\\\\\":\\\\\\"2012-10-17\\\\\\",\\\\\\"Statement\\\\\\":[{\\\\\\"Action\\\\\\":[\\\\\\"logs:CreateLogStream\\\\\\",\\\\\\"logs:PutLogEvents\\\\\\"],\\\\\\"Resource\\\\\\":[\\\\\\"\${aws_cloudwatch_log_group.reverse-id_snoop-log-group_FAF8FFFD.arn}\\\\\\",\\\\\\"\${aws_cloudwatch_log_group.reverse-id_snoop-log-group_FAF8FFFD.arn}:log-stream:*\\\\\\"],\\\\\\"Effect\\\\\\":\\\\\\"Allow\\\\\\"}]}\\"
}
},
\\"aws_iam_role\\": {
\\"adapter_StateMachineRoleB840431D_34E24F0D\\": {
\\"assume_role_policy\\": \\"\${jsonencode({Statement = [{Action = \\\\\\"sts:AssumeRole\\\\\\", Effect = \\\\\\"Allow\\\\\\", Principal = {Service = join(\\\\\\"\\\\\\", [\\\\\\"states.\\\\\\", data.aws_region.adapter_aws-region_F8878EF0.name, \\\\\\".amazonaws.com\\\\\\"])}}], Version = \\\\\\"2012-10-17\\\\\\"})}\\"
},
\\"generate-id_server-role_62418FA4\\": {
\\"assume_role_policy\\": \\"{\\\\\\"Version\\\\\\":\\\\\\"2012-10-17\\\\\\",\\\\\\"Statement\\\\\\":[{\\\\\\"Action\\\\\\":[\\\\\\"sts:AssumeRole\\\\\\",\\\\\\"sts:SetSourceIdentity\\\\\\"],\\\\\\"Effect\\\\\\":\\\\\\"Allow\\\\\\",\\\\\\"Principal\\\\\\":{\\\\\\"Service\\\\\\":[\\\\\\"lambda.amazonaws.com\\\\\\"]}}]}\\",
\\"name\\": \\"c8db9d3041a90e1d114b187c0e984994c2bd27ae7b\\"
},
\\"reverse-id_server-role_3C5E949B\\": {
\\"assume_role_policy\\": \\"{\\\\\\"Version\\\\\\":\\\\\\"2012-10-17\\\\\\",\\\\\\"Statement\\\\\\":[{\\\\\\"Action\\\\\\":[\\\\\\"sts:AssumeRole\\\\\\",\\\\\\"sts:SetSourceIdentity\\\\\\"],\\\\\\"Effect\\\\\\":\\\\\\"Allow\\\\\\",\\\\\\"Principal\\\\\\":{\\\\\\"Service\\\\\\":[\\\\\\"lambda.amazonaws.com\\\\\\"]}}]}\\",
\\"name\\": \\"c8a001c1b2c37e8cea98f2ebcfb39a6834c9931a7d\\"
}
},
\\"aws_iam_role_policy_attachment\\": {
\\"adapter_StateMachineRoleDefaultPolicyDF1E6607_role0_4C4F3BCD\\": {
\\"policy_arn\\": \\"\${aws_iam_policy.adapter_StateMachineRoleDefaultPolicyDF1E6607_28877BB8.arn}\\",
\\"role\\": \\"\${aws_iam_role.adapter_StateMachineRoleB840431D_34E24F0D.id}\\"
},
\\"generate-id_server-role_PolicyAttachment_07FBFD85\\": {
\\"policy_arn\\": \\"\${aws_iam_policy.generate-id_server-role_role-policy_6FBD6C53.arn}\\",
\\"role\\": \\"\${aws_iam_role.generate-id_server-role_62418FA4.name}\\"
},
\\"reverse-id_server-role_PolicyAttachment_A9363212\\": {
\\"policy_arn\\": \\"\${aws_iam_policy.reverse-id_server-role_role-policy_BEA9EC5B.arn}\\",
\\"role\\": \\"\${aws_iam_role.reverse-id_server-role_3C5E949B.name}\\"
}
},
\\"aws_lambda_function\\": {
\\"generate-id_fn_99320B4B\\": {
\\"depends_on\\": [
\\"aws_cloudwatch_log_group.generate-id_snoop-log-group_D659273F\\"
],
\\"filename\\": \\"assets/generate-id_lambda-asset_D3DA57A3/29C871159DB99C8E6F96EDF0D540077F/archive.zip\\",
\\"function_name\\": \\"generate-id-c8e9be4a2f33ecc14e138a018899daed079e618acb\\",
\\"handler\\": \\"fn-generate-id.handler\\",
\\"memory_size\\": 512,
\\"role\\": \\"\${aws_iam_role.generate-id_server-role_62418FA4.arn}\\",
\\"runtime\\": \\"nodejs14.x\\",
\\"source_code_hash\\": \\"29C871159DB99C8E6F96EDF0D540077F\\",
\\"timeout\\": 15
},
\\"reverse-id_fn_A44557C2\\": {
\\"depends_on\\": [
\\"aws_cloudwatch_log_group.reverse-id_snoop-log-group_FAF8FFFD\\"
],
\\"filename\\": \\"assets/reverse-id_lambda-asset_4139ACFF/29C871159DB99C8E6F96EDF0D540077F/archive.zip\\",
\\"function_name\\": \\"reverse-id-c80e28e7990db1dae069bd131f26434d1b4d867e38\\",
\\"handler\\": \\"fn-reverse-id.handler\\",
\\"memory_size\\": 512,
\\"role\\": \\"\${aws_iam_role.reverse-id_server-role_3C5E949B.arn}\\",
\\"runtime\\": \\"nodejs14.x\\",
\\"source_code_hash\\": \\"29C871159DB99C8E6F96EDF0D540077F\\",
\\"timeout\\": 15
}
},
\\"time_sleep\\": {
\\"adapter_StateMachineRoleB840431D_sleep_StateMachineRoleB840431D_89BC4BE8\\": {
\\"create_duration\\": \\"20s\\",
\\"depends_on\\": [
\\"aws_iam_role.adapter_StateMachineRoleB840431D_34E24F0D\\"
],
\\"destroy_duration\\": \\"0s\\",
\\"provider\\": \\"time.awsadapter_eventual_consistency_workaround_aspect\\"
}
}
},
\\"terraform\\": {
\\"required_providers\\": {
\\"aws\\": {
\\"source\\": \\"aws\\",
\\"version\\": \\"~> 3.0\\"
}
}
}
}"
`);
});
});
73 changes: 73 additions & 0 deletions examples/typescript-step-functions-mixed/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import {
Duration,
aws_stepfunctions,
aws_stepfunctions_tasks,
aws_lambda,
} from "aws-cdk-lib";
import * as aws_cdk from "aws-cdk-lib";
import * as path from "path";

import { AwsTerraformAdapter, AwsProvider } from "@cdktf/aws-cdk";
import { NodejsFunction } from "@cdktf-plus/aws";

export class StepFunctionsStack extends TerraformStack {
constructor(scope: Construct, name: string) {
super(scope, name);

new AwsProvider(this, "aws", { region: "us-west-2" });

const awsAdapter = new AwsTerraformAdapter(this, "adapter");

const functionGenerateID = new NodejsFunction(this, "generate-id", {
path: path.join(__dirname, "fn-generate-id.ts"),
});

const functionReverseID = new NodejsFunction(this, "reverse-id", {
path: path.join(__dirname, "fn-reverse-id.ts"),
});

const definition = new aws_stepfunctions_tasks.LambdaInvoke(
awsAdapter,
"Generate ID",
{
lambdaFunction: aws_lambda.Function.fromFunctionArn(
awsAdapter,
"generate-id",
aws_cdk.Lazy.string({
produce: () => functionGenerateID.fn.arn,
})
),
outputPath: "$.Payload",
}
)
.next(
new aws_stepfunctions.Wait(awsAdapter, "Wait 1 Second", {
time: aws_stepfunctions.WaitTime.duration(Duration.seconds(1)),
})
)
.next(
new aws_stepfunctions_tasks.LambdaInvoke(awsAdapter, "Reverse ID", {
lambdaFunction: aws_lambda.Function.fromFunctionArn(
awsAdapter,
"reverse-id",
aws_cdk.Lazy.string({
produce: () => functionReverseID.fn.arn,
})
),
outputPath: "$.Payload",
})
);

new aws_stepfunctions.StateMachine(awsAdapter, "StateMachine", {
definition,
timeout: Duration.minutes(5),
});
}
}

const app = new App();
new StepFunctionsStack(app, "typescript-step-functions");

app.synth();
31 changes: 31 additions & 0 deletions examples/typescript-step-functions-mixed/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@cdktf/aws-adapter-example-typescript-step-functions-mixed",
"version": "0.0.0",
"main": "index.js",
"license": "MPL-2.0",
"scripts": {
"build": "tsc",
"compile": "tsc --pretty",
"synth": "cdktf synth",
"pretest": "yarn run build",
"test": "jest",
"pretest:ci": "yarn install",
"test:ci": "npm install --no-save \"../../dist/js/aws-cdk@$(node -e \"console.log(require('../../package.json').version)\").jsii.tgz\" && yarn test"
},
"devDependencies": {
"@types/jest": "27.0.1",
"@types/node": "^14.0.26",
"cdktf-cli": "0.8.0",
"jest": "27.1.0",
"ts-jest": "^27.0.5",
"typescript": "^3.9.7"
},
"dependencies": {
"cdktf": "0.8.0",
"constructs": "^10.0.5",
"@cdktf/aws-cdk": "0.2.2",
"@cdktf-plus/aws": "^0.2.2",
"iam-floyd": "^0.337.0",
"aws-cdk-lib": "2.0.0"
}
}
2 changes: 2 additions & 0 deletions examples/typescript-step-functions-mixed/setupJest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const cdktf = require("cdktf");
cdktf.Testing.setupJest();
34 changes: 34 additions & 0 deletions examples/typescript-step-functions-mixed/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"alwaysStrict": true,
"charset": "utf8",
"declaration": true,
"experimentalDecorators": true,
"inlineSourceMap": true,
"inlineSources": true,
"lib": [
"es2019"
],
"module": "CommonJS",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"stripInternal": true,
"target": "ES2018"
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules",
".yalc"
]
}
Loading

0 comments on commit a37039e

Please sign in to comment.