-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a Lambda+Codepipeline Typescript example #269
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
71d87ca
chore: unpin cdk versions so they can serve as canaries for changes t…
shivlaks 3b719fa
feat: Add Lambda+ApiGateway+Codepipeline example. Fixes #267
39f935f
Merge branch 'master' into master
NGL321 9e7f3a7
Merge branch 'master' into master
NGL321 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -233,7 +233,6 @@ dist/ | |
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
*.js | ||
!jest.config.js | ||
*.d.ts | ||
node_modules | ||
|
||
# CDK asset staging directory | ||
.cdk.staging | ||
cdk.out | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
*.ts | ||
!*.d.ts | ||
|
||
# CDK asset staging directory | ||
.cdk.staging | ||
cdk.out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"printWidth": 100, | ||
"semi": false, | ||
"tabWidth": 4 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# What's this? | ||
This is code sample that uses CDK to: | ||
* Create a Lambda function that can be invoked using API Gateway | ||
* Create a CI using CodeSuite that deploys the Lambda+ApiGateway resources using `cdk deploy` | ||
|
||
# How do I start using it? | ||
* Ensure you've followed the [guide to Getting Started to AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html), and you have CDK installed, and the AWS SDK installed and credentials configured. | ||
* [Bootstrap your AWS environment](https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html#serverless_example_deploy_and_test) | ||
* Create a CodeCommit repository. See [this documentation](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-create-repository.html) for help. | ||
* Place the contents of this folder inside it | ||
* Set the repository name in the `repositoryName` prop in `bin/ci.ts`. | ||
* Build the stack with `npm run build` | ||
* Deploy the CI stack with `cdk deploy` | ||
* `Todo` summarize permissions | ||
* If you'd like to deploy just the Lambda+ApiGateway stack, you can do so with `cdk deploy -a "npx ts-node bin/lambda.ts"` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env node | ||
import "source-map-support/register" | ||
import cdk = require("@aws-cdk/core") | ||
import { CIStack } from "../lib/ci-stack" | ||
|
||
const app = new cdk.App() | ||
new CIStack(app, "CDKExampleLambdaApiCIStack", { | ||
repositoryName: "lambda-api-ci", | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/usr/bin/env node | ||
import "source-map-support/register" | ||
import cdk = require("@aws-cdk/core") | ||
import { CDKExampleLambdaApiStack } from "../lib/lambda-api-stack" | ||
|
||
export const lambdaApiStackName = "CDKExampleLambdaApiStack" | ||
export const lambdaFunctionName = "CDKExampleWidgetStoreFunction" | ||
|
||
const app = new cdk.App() | ||
new CDKExampleLambdaApiStack(app, lambdaApiStackName, { | ||
functionName: lambdaFunctionName, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
version: 0.2 | ||
|
||
phases: | ||
install: | ||
runtime-versions: | ||
nodejs: 12 | ||
commands: | ||
- npm install | ||
|
||
build: | ||
commands: | ||
- npm run build | ||
- npm run -- cdk deploy --ci --require-approval never -a "npx ts-node bin/lambda.ts" | ||
artifacts: | ||
files: | ||
- "cdk.out/**/*" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"app": "npx ts-node bin/ci.ts" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module.exports = { | ||
"roots": [ | ||
"<rootDir>/test" | ||
], | ||
testMatch: [ '**/*.test.ts'], | ||
"transform": { | ||
"^.+\\.tsx?$": "ts-jest" | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { CodeCommitSourceAction, CodeBuildAction } from "@aws-cdk/aws-codepipeline-actions" | ||
import { PolicyStatement } from "@aws-cdk/aws-iam" | ||
import { Construct, Stack, StackProps } from "@aws-cdk/core" | ||
import { PipelineProject, LinuxBuildImage } from "@aws-cdk/aws-codebuild" | ||
import { Artifact, Pipeline } from "@aws-cdk/aws-codepipeline" | ||
import { Repository } from "@aws-cdk/aws-codecommit" | ||
import { lambdaApiStackName, lambdaFunctionName } from "../bin/lambda" | ||
|
||
interface CIStackProps extends StackProps { | ||
repositoryName: string | ||
} | ||
|
||
export class CIStack extends Stack { | ||
constructor(scope: Construct, name: string, props: CIStackProps) { | ||
super(scope, name, props) | ||
|
||
const pipeline = new Pipeline(this, "Pipeline", {}) | ||
|
||
const repo = Repository.fromRepositoryName( | ||
this, | ||
"WidgetsServiceRepository", | ||
props.repositoryName | ||
) | ||
const sourceOutput = new Artifact("SourceOutput") | ||
const sourceAction = new CodeCommitSourceAction({ | ||
actionName: "CodeCommit", | ||
repository: repo, | ||
output: sourceOutput, | ||
}) | ||
pipeline.addStage({ | ||
stageName: "Source", | ||
actions: [sourceAction], | ||
}) | ||
|
||
this.createBuildStage(pipeline, sourceOutput) | ||
} | ||
|
||
private createBuildStage(pipeline: Pipeline, sourceOutput: Artifact) { | ||
const project = new PipelineProject(this, `BuildProject`, { | ||
environment: { | ||
buildImage: LinuxBuildImage.STANDARD_3_0, | ||
}, | ||
}) | ||
|
||
const cdkDeployPolicy = new PolicyStatement() | ||
cdkDeployPolicy.addActions( | ||
"cloudformation:GetTemplate", | ||
"cloudformation:CreateChangeSet", | ||
"cloudformation:DescribeChangeSet", | ||
"cloudformation:ExecuteChangeSet", | ||
"cloudformation:DescribeStackEvents", | ||
"cloudformation:DeleteChangeSet", | ||
"cloudformation:DescribeStacks", | ||
"s3:*Object", | ||
"s3:ListBucket", | ||
"s3:getBucketLocation", | ||
"lambda:UpdateFunctionCode", | ||
"lambda:GetFunction", | ||
"lambda:CreateFunction", | ||
"lambda:DeleteFunction", | ||
"lambda:GetFunctionConfiguration", | ||
"lambda:AddPermission", | ||
"lambda:RemovePermission" | ||
) | ||
cdkDeployPolicy.addResources( | ||
this.formatArn({ | ||
service: "cloudformation", | ||
resource: "stack", | ||
resourceName: "CDKToolkit/*", | ||
}), | ||
this.formatArn({ | ||
service: "cloudformation", | ||
resource: "stack", | ||
resourceName: `${lambdaApiStackName}/*`, | ||
}), | ||
this.formatArn({ | ||
service: "lambda", | ||
resource: "function", | ||
sep: ":", | ||
resourceName: lambdaFunctionName, | ||
}), | ||
"arn:aws:s3:::cdktoolkit-stagingbucket-*" | ||
) | ||
const editOrCreateLambdaDependencies = new PolicyStatement() | ||
editOrCreateLambdaDependencies.addActions( | ||
"iam:GetRole", | ||
"iam:PassRole", | ||
"iam:CreateRole", | ||
"iam:AttachRolePolicy", | ||
"iam:PutRolePolicy", | ||
"apigateway:GET", | ||
"apigateway:DELETE", | ||
"apigateway:PUT", | ||
"apigateway:POST", | ||
"apigateway:PATCH", | ||
"s3:CreateBucket", | ||
"s3:PutBucketTagging" | ||
) | ||
editOrCreateLambdaDependencies.addResources("*") | ||
project.addToRolePolicy(cdkDeployPolicy) | ||
project.addToRolePolicy(editOrCreateLambdaDependencies) | ||
|
||
const buildOutput = new Artifact(`BuildOutput`) | ||
const buildAction = new CodeBuildAction({ | ||
actionName: `Build`, | ||
project, | ||
input: sourceOutput, | ||
outputs: [buildOutput], | ||
}) | ||
|
||
pipeline.addStage({ | ||
stageName: "build", | ||
actions: [buildAction], | ||
}) | ||
|
||
return buildOutput | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { LambdaIntegration, MethodLoggingLevel, RestApi } from "@aws-cdk/aws-apigateway" | ||
import { PolicyStatement } from "@aws-cdk/aws-iam" | ||
import { Function, Runtime, AssetCode, Code } from "@aws-cdk/aws-lambda" | ||
import { Construct, Duration, Stack, StackProps } from "@aws-cdk/core" | ||
import s3 = require("@aws-cdk/aws-s3") | ||
|
||
interface LambdaApiStackProps extends StackProps { | ||
functionName: string | ||
} | ||
|
||
export class CDKExampleLambdaApiStack extends Stack { | ||
private restApi: RestApi | ||
private lambdaFunction: Function | ||
private bucket: s3.Bucket | ||
|
||
constructor(scope: Construct, id: string, props: LambdaApiStackProps) { | ||
super(scope, id, props) | ||
|
||
this.bucket = new s3.Bucket(this, "WidgetStore") | ||
|
||
this.restApi = new RestApi(this, this.stackName + "RestApi", { | ||
deployOptions: { | ||
stageName: "beta", | ||
metricsEnabled: true, | ||
loggingLevel: MethodLoggingLevel.INFO, | ||
dataTraceEnabled: true, | ||
}, | ||
}) | ||
|
||
const lambdaPolicy = new PolicyStatement() | ||
lambdaPolicy.addActions("s3:ListBucket") | ||
lambdaPolicy.addResources(this.bucket.bucketArn) | ||
|
||
this.lambdaFunction = new Function(this, props.functionName, { | ||
functionName: props.functionName, | ||
handler: "handler.handler", | ||
runtime: Runtime.NODEJS_10_X, | ||
code: new AssetCode(`./src`), | ||
memorySize: 512, | ||
timeout: Duration.seconds(10), | ||
environment: { | ||
BUCKET: this.bucket.bucketName, | ||
}, | ||
initialPolicy: [lambdaPolicy], | ||
}) | ||
|
||
this.restApi.root.addMethod("GET", new LambdaIntegration(this.lambdaFunction, {})) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
{ | ||
"name": "lambda-api-ci", | ||
"version": "0.1.0", | ||
"bin": { | ||
"lambda-api-ci": "bin/lambda-api-ci.js" | ||
}, | ||
"scripts": { | ||
"build": "npm run prettier && tsc && npm run build-lambda", | ||
"build-lambda": "cd src && npm run build", | ||
"watch": "tsc -w", | ||
"test": "jest", | ||
"cdk": "cdk", | ||
"prettier": "prettier --write '**/{bin,lib,src,tst}/*.ts'" | ||
}, | ||
"devDependencies": { | ||
"aws-cdk": "*", | ||
"@aws-cdk/core": "*", | ||
"@aws-cdk/assert": "*", | ||
"@aws-cdk/aws-apigateway": "*", | ||
"@aws-cdk/aws-codebuild": "*", | ||
"@aws-cdk/aws-codecommit": "*", | ||
"@aws-cdk/aws-codepipeline": "*", | ||
"@aws-cdk/aws-codepipeline-actions": "*", | ||
"@aws-cdk/aws-cloudformation": "*", | ||
"@types/jest": "^24.0.18", | ||
"@types/node": "^13.7.0", | ||
"jest": "^24.9.0", | ||
"ts-jest": "^24.0.2", | ||
"ts-node": "^8.1.0", | ||
"typescript": "^3.8.3", | ||
"prettier": "^2.0.4" | ||
}, | ||
"dependencies": { | ||
"aws-sdk": "^2.617.0", | ||
"source-map-support": "^0.5.9" | ||
}, | ||
"description": "* `npm run build` compile typescript to js * `npm run watch` watch for changes and compile * `npm run test` perform the jest unit tests * `cdk deploy` deploy this stack to your default AWS account/region * `cdk diff` compare deployed stack with current state * `cdk synth` emits the synthesized CloudFormation template", | ||
"main": "jest.config.js", | ||
"directories": { | ||
"lib": "lib", | ||
"test": "test" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { S3 } from "aws-sdk" | ||
|
||
const bucketName = process.env.BUCKET! | ||
|
||
// From https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html | ||
const handler = async function (event: any, context: any) { | ||
const S3Client = new S3() | ||
|
||
try { | ||
var method = event.httpMethod | ||
|
||
if (method === "GET") { | ||
if (event.path === "/") { | ||
const data = await S3Client.listObjectsV2({ Bucket: bucketName }).promise() | ||
var body = { | ||
widgets: data.Contents!.map(function (e) { | ||
return e.Key | ||
}), | ||
} | ||
return { | ||
statusCode: 200, | ||
headers: {}, | ||
body: JSON.stringify(body), | ||
} | ||
} | ||
} | ||
|
||
// We only accept GET for now | ||
return { | ||
statusCode: 400, | ||
headers: {}, | ||
body: "We only accept GET /", | ||
} | ||
} catch (error) { | ||
const body = error.stack || JSON.stringify(error, null, 2) | ||
return { | ||
statusCode: 400, | ||
headers: {}, | ||
body: JSON.stringify(body), | ||
} | ||
} | ||
} | ||
|
||
export { handler } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've run the following commands to compare the directories that are evaluated:
Here is the diff. Directories removed are shown in grey on the left-hand side:
Link
These directories are now excluded as they're Lambda NPM packages, not CDK packages:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the catch! I had not noticed this. The fix is logical and LGTM.
😸