Leveraging services with Terraform
By: David Calder
Tags: Terraform

The objective

Now that I’ve learnt the basics of creating EC2 instances and provisioning them, I want to learn how to configure services, particularly Serverless infrastructure, a.k.a. Lambda in the AWS world.

The tutorials

There are two tutorials on Hashicorp’s website: one for configuring IAM Policy Documents (which sounds terrifically exciting) and the other for Lambda. As the first is only four minutes long, I start with that one.

IAM Policy Documents…

So this tutorial isn’t really a tutorial at all. It’s telling me that there are multiple ways to configure IAM policies, but the best is the aws_iam_policy_document and here’s a link to the docs. So I have a read and a think. If it was me, I’d like to have the policy document in JSON so I could read it and understand it at a glance. However, I am mindful that Terraform does checks that a manually created file won’t be subjected to. It feels like six of one and half a dozen of the other, so I move on to the next tutorial.

Serverless Applications with AWS Lambda and API Gateway…

Before starting this tutorial I was lucky enough to have attended a knowledge-sharing session at work where the Cloud Infrastructure team-lead gave a one-hour introduction to serverless in AWS. This was a good grounding in the subject. My background is in web application support too, which really helped. The tutorial is good and works perfectly. It didn’t cover S3 bucket creation (with Terraform) though and I created a bucket and uploaded a file to it using the AWS CLI directly. Sounds like configuring storage is a likely candidate for the next steps!

What I’ve learnt

I’ve learnt that there’s not much difference between configuring serverless and creating servers.

One things I’ve noticed is that blocks of code in Terraform build on the previous one, and often reference IDs and variables created by the preceding block(s). For example:

resource "aws_api_gateway_rest_api" "example" {

name = "ServerlessExample"

description = "Terraform Serverless Application Example"

}

Information created by the block above can be referenced in subsequent blocks, like so:

resource "aws_api_gateway_resource" "proxy" {

rest_api_id = aws_api_gateway_rest_api.example.id

parent_id = aws_api_gateway_rest_api.example.root_resource_id

path_part = "{proxy+}"

}

Here’s a diagram of what I’ve done today:

In conclusion

I’ve used the AWS CLI to create an S3 bucket and upload a simple Javascript file that returns a HTML file with a Hello World! message. I gave it a version number of 1.0.0.

I then used Terraform to create a Lambda function that calls main.js, and an API Gateway instance that acts as a proxy, i.e. it passes any request it receives on to the Lambda function. I gave the API Gateway the permission to invoke the Lambda function. I also used the output function to tell me the URL I needed to call from my browser.

Finally, I deployed version 1.0.1 of main.js with the AWS CLI, this time with the French version of Hello World! I then made an amendment to the Lambda function to use version 1.0.1, but this time I used a variable to specify the version, which was passed when I ran terraform apply .

terraform apply -var="app_version=1.0.0"