My clients are always asking for things like a contact form, a poll, an opt-in form and I don't want to clutter my Rails app for these "micro-apps". I thought it would be smart if I could create a repo with a CloudFormation template that I could then fork for each use-case. If I needed to make minor adjustments I would just push to the forked repo and the changes would automatically deploy.
So I set out to create this golden CloudFormation template that would set up:
- A DymanmoDB table - to store the data
- An SNS Topic - to email when someone used the form
- An APIGateway - a way to trigger the lambda function
- A Lambda Function - to store the submitted data and send me an email
- A S3 bucket - store a js file that would be an embeddable script
- CloudFront - serve the js file
- CodePipeline - automatically build and deploy the changes
A weekend project became a week-long death march into configuration hell. I do plan to do a tutorial on how I built said golden template but I wanted to share what I thought could save someone else significant time creating their own golden CloudFormation Template
AWS CodeStar is a glorified dashboard for pre-made CloudFormation templates that set up various deployment configurations with CodePipeline. I personally would never use AWS CodeStar because I don't need to add another layer to the onion of complexity.
However. What I did find useful was the templates themselves. It's very hard online to find good CloudFormation templates that setup CodePipeline to deploy Lambda functions.
I would suggest spinning up a CodeStar project and then go over to CloudFormation service and then download the template. It will save you hours figuring how to compose the stages for your pipeline.
When you setup CodePipeline to deploy a lambda function you add a Deploy stage and you would think that you would want to add CodeDeploy. What you actually do is deploy a SAM CloudFormation template that will automatically setup CodeDeploy and deploy your Lambda function.
All AWS tutorials/resources will tell you to use a SAM (Serverless Application Model) template. SAM is just a less verbose way to configure a CloudFormation template. SAM can be frustrating for various reasons:
- it will create more resources than you may want
- SAM has several limitations so you have to, in the end, use a CloudFormation template
- there's lots of magic happening, which can make things confusing
All SAM does is transforms your template into the full verbose CloudFormation template. You can view the output under the Template tab for the stack and select processed template. Then I use an online service to convert the json to yaml for readability. Reading the processed template makes it easier to debug obscure errors since you have a better idea of what's being created.
When you create a CloudFormation template to create a CodePipeline for a Lambda function you'll end up with two stacks. The second one being the lambda itself. When you need to delete your stacks because you are fine-tuning or debugging the process you best delete them in reverse order and wait for each to be deleted before the other.
The reason I say this is because if CodePipeline stack is deleted first you may end up with deleted resources such as roles and you'll see a DELETE_FAILED error from your stack. Save yourself the trouble and heed my advice
You may end up with the DELETE_FAILED error when deleting your stack.
It happens generally for two reasons:
- Your stack had an S3 bucket that it wanted to delete but the bucket was not empty.
- Your role no longer exists and your stack is trying to delete a resource that does not exist.
I always have to empty my S3 buckets before I delete my stacks which is tiring but that's just what you have to do.
For missing roles, you will have to delete your stack via the CLI and provide it with a role that exists.
This should be obvious but I didn't think myself to check the Github Issue on SAM to see template examples. Here I was able to find syntax configuration for SAM I could not find easily via AWS documentation.