aws-blueprint example for an API backed by single lambda
MIT License
aws-blueprint example for an API backed by a single lambda
Each branch of this repo is a different language for the same example app.
This example sets up a CI/CD for a single lambda, fronted by CloudFront and API Gateway.
Run the setup script from your local git repo dir:
wget -q https://raw.githubusercontent.com/rynop/abp-single-lambda-api/master/bin/setup.sh; bash setup.sh; rm setup.sh
This:
master
branch.NestedStacksS3Bucket
and s3 versions of your nested-stacks
in your resources CloudFormation file.Create a s3 bucket that will hold your lambda zips. Only need one bucket per AWS. Ex: deploy.yourdomain.com
Create your "resources" (CloudFront, API Gateway etc) stacks using aws/cloudformation/cf-apig-single-lambda-resources.yaml
in your repo. Stack naming convention is [stage]--[repo]--[branch]--[eyecatcher]--r
. Ex: prod--abp-single-lambda-api--master--ImageManip--r
:
test
and prod
stages. You will have 2 root stacks. The prod
stack takes care of both prod
and staging
resources.Outputs
tab in the CloudFormation UI for each root stack has commands you will run in the next steps. Outputs that start with Run*
you should run from your CLI.Some of the Lambda configuration is stored in Systems manager parameter store with the convention based prefix /<stage>/<repoName>/<branch>/<lambdaName>/
. Ex: aws ssm put-parameter --name "/prod/abp-single-lambda-api/master/ResizeImage/lambdaExecutionRoleArn" --type "String" --value 'arn:aws:iam::accountId:role/roleName'
. These keys are required per stage:
/<stage>/<repoName>/<branch>/<lambdaName>/lambdaExecutionRoleArn
(don't create for staging
stage. staging
uses the prod
lambdaExecutionRoleArn
). The output of the Resources CloudFormation stack contains a SsmSetLambdaExecutionRoleCmd
value that is an aws CLI command that sets this for you./<stage>/<repoName>/<branch>/<lambdaName>/lambdaTimeout
/<stage>/<repoName>/<branch>/<lambdaName>/lambdaMemory
/<stage>/<repoName>/<branch>/<lambdaName>/vpcConfig
. Optional. If your lambda needs to be in vpc, value should be like SubnetIds=string,string,SecurityGroupIds=string,string
. See AWS CLI docs for more info.Setup env vars per stage. All keys in the lambdaEnvs
namespace are automatically added your your lambda's env. They can optionally be encrypted in systems manager param store, we handle all the decoding complexity (if you use the default KMS key). You can use this script help set them.
/<stage>/<repoName>/<branch>/<lambdaName>/lambdaEnvs/<env var name>
. Ex: /prod/abp-single-lambda-api/master/ResizeImage/lambdaEnvs/MY_VAR
SsmSetXFromCdnEnvVarCmd
output value from the Resources CloudFormation stack. It sets X_FROM_CDN
(used by the example code in this repo).APP_STAGE
Create a Github user (acct will just be used to read repos for CI/CD), give it read auth to your github repo. Create a personal access token for this user at https://github.com/settings/tokens. This token will be used by the CI/CD to pull code.
Go through the README.md
of the language branch you copied, language specific setup and for stack parameter values that will be used in CI/CD stack creation (next step).
Create a CloudFormation stack for your CI/CD using single-lambda-test-staging-prod.yaml with the stack naming convention of [repo]--[branch]--[eyecatcher]--cicd
. Ex: abp-single-lambda-api--master--ResizeImage--cicd
.
Commit your code and the CI/CD CodePipline will automatically run. The buildspec files assume you check in your dependencies (aka node_modules
). Prevents version issues when working in teams, also prevents deploy issues during github outage.
The domain your app can be reached, is located in the Outputs
tab of the resources CloudFormation stack at key CNAME
.
Create a DNS entry in route53 for production that consumers will use. The cloud formation creates one for prod--
but you do not want to use this as the CloudFormation can be deleted.
Want a lambda that does not need a web API (that is invoked by something like sns)? Follow the steps above, but instead of using aws/cloudformation/cf-apig-single-lambda-resources.yaml
for your resources CloudFormation, use aws/cloudformation/no-web-api-single-lambda-resources.yaml
. You will use the same codebuild files and same CI/CD.
Astute developers may notice an APIG line in aws/codebuild/lambda-publish, however this has no impact and will not fail the build.
The publishing process is multi-stage, with manual approvals, all handled in an automated fashion. Here are the details:
PublishTest
step:
/test/[repo]/[branch]/[LAMBDA_NAME]/lambdaEnvs
, role from /test/[repo]/[branch]/[LAMBDA_NAME]/lambdaExecutionRoleArn
, timeout from /test/[repo]/[branch]/[LAMBDA_NAME]/lambdaTimeout
, memory from /test/[repo]/[branch]/[LAMBDA_NAME]/lambdaMemory
,test
ApproveTest
approved, PublishStaging
step: :
/staging/[repo]/[branch]/[LAMBDA_NAME]/lambdaEnvs
, role from /prod/[repo]/[branch]/[LAMBDA_NAME]/lambdaExecutionRoleArn
, timeout from /staging/[repo]/[branch]/[LAMBDA_NAME]/lambdaTimeout
, memory from /test/[repo]/[branch]/[LAMBDA_NAME]/lambdaMemory
.s3://${S3_BUCKET_CONTAINING_PACKAGES}/${S3_PATH_TO_PACKAGES}/${codeSha256}.zip
where codeSha256
is the just deployed staging
lambda CodeSha256
configuration value. This ensures the code deployed to staging is the code that will be deployed to prod
.staging
ApproveStaging
approved, PublishProd
step: :
${codeSha256}.zip
. Set env vars from ssm namespace /prod/[repo]/[branch]/[LAMBDA_NAME]/lambdaEnvs
, role from /prod/[repo]/[branch]/[LAMBDA_NAME]/lambdaExecutionRoleArn
, timeout from /staging/[repo]/[branch]/[LAMBDA_NAME]/lambdaTimeout
, memory from /prod/[repo]/[branch]/[LAMBDA_NAME]/lambdaMemory
.prod