The Programs of the Week We Caught Pokémon
This Week’s Program: July 11 - July 15
I am a veritable Thundurus this week. Because of my prowess with Cloud computing. I don’t know it’s a Pokémon I guess.
49b9b22164c3927d93c6947e7b75f9ebd6cdf592
In my CloudFormation template I add instructions to install the AWS CodeDeploy Agent. This is used to get code from CodeDeploy onto an instance.
41c49c64a8de9716521d339b8c3b1e0e6988760c
I build up a
Deployment Group
and choose a recent revision of sonic-sketches
to deploy onto a
machine.
cda4f095269f62dd4cfd6bf8bd7f11e644a9eed1
I bring back the CodeDeploy Appspec file, and begin a series of commits where I tweak the parameters and permissions of this file.
At this point, I’m bringing up CloudFormation stacks and tearing them down, each time tweaking the Appspec file. I can get my code onto the box. Each revision of the Appspec brings me closer to running the code. This is Monday.
81b35621e118735468e5c68f745889692e88684f
It’s Tuesday. I’m adding a hook for the CodeDeploy BeforeInstall event. Later, I would change this to AfterInstall and continue to tweak it.
8aa61334e3a437619349462bcece36f32d1d0c8f
I parameterize the GitHub revision commit to be deployed on initial stack creation.
Eventually, I am able to reliably use CodeDeploy to ensure that the
sonic-sketches
program is in place on the filesystem after stack
creation. I am able to run sonic-sketches
successfully.
Now to automate it further.
bb6087d68c924553293608c1981bb457665828fd
I parameterize the GitHub repository that houses sonic-sketches
. Of
course the default is mine, but if anybody wants to fork the repo and
this cloud-formation template, they should be able to see similar
success.
I also have have my nohup
jackd script run during
provisioning. After a typo fix I can just log-in to the box once the
CloudFormation stack has been created and run lein trampoline run
in
my sonic-sketches
directory and a song pops in to S3.
92f5af7aacac114e634e635b189fa7abd9875532
I create a new IAM User with access keys for the purposes of deploying through CodeDeploy. At this point, I’m just following along with this tutorial published by Amazon: Automatically Deploy from GitHub Using AWS CodeDeploy. Using the GitHub Auto-Deployment webhook/service works like a charm. When I push to GitHub, it is automatically deployed to my EC2 instance. This is Wednesday.
Then I get a wacky idea in my head.
576f7a8e2a0fe8ff57ddd85fa577511256cf82c8
I change the CodeDeploy tag filter to use the CloudFormation stack ID. This is what CodeDeploy uses to determine what instances to deploy to. By using the Stack ID tag, I can be sure that CodeDeploy only deploys to the instances within its CloudFormation stack.
I spend some time Thursday and today on this next commit.
ab8d28b078e5e3ef5c658abfe0a1c1ba2972a09d
When I pull up the CloudFormation stack for sonic-sketches
I want to
automatically create the AWS CodeDeploy webhook on the Git
repository. This takes some doing.
First, I create a
Custom Resource
in CloudFormation. This resource represents the GitHub webhook. The
Custom Resource is backed by an
AWS Lambda
function. This function uses the Node runtime in Lambda and uses the
cfn-response
module
to respond to the CloudFormation custom resource: this module tells
CloudFormation whether or not that custom resource was able to be
created.
Within the template I type out the Lambda function code. After a bunch of trial and error, I put my finished Lambda fn in a gist. This was my first time really using ECMAScript® 2015 in anger and my first time really using NodeJS in several years. Here’s how this function works:
- The Custom Resource in CloudFormation calls this Lambda function and says “Hey, I’ve got a Custom Resource here. Can you make this for me?”
- This Lambda function pulls out a bunch of properties I’ve explicitly
passed to the Custom Resource, like a GitHub
personal access token
with the
admin:repo_hook
scope, the CodeDeploy Application name and Deployment Group, and the IAM User keys. - Using these properties, the function makes a POST request to the GitHub API to create a webhook, specifying that this is for the CodeDeploy service. (I find making a straightforward HTTP request in Node cumbersome).
- If the webhook is successfully created, CloudFormation is signaled that this Custom Resource creation was a success. Otherwise, it signals a failure.
I also build another IAM Role so that this Lambda function can write logs to CloudWatch.
After a bunch of trial and error, and watching the CloudWatch logs like a hawk, I can now successfully create a GitHub repository webhook for my CodeDeploy service as a resource within my CloudFormation stack.
Theoretically, this Lambda function should also be triggered when it’s time to delete this resource, but I found in my experiments that this branch of code was never called.
So now that I’ve overengineered the hell out of this I feel quite good
about the results. This was my first exposure doing something with
Lambda and it is awesome. I have now automated the deploy of my code
to my AWS stack whenever I git push
.
Next week, I need to make some changes to the application to support some of these new stack ideas. I also intend on setting up a scheduled job to generate a song at regular intervals.
CloudFormation, I choose you!
– Mark