Creating AWS Lambdas through Terraform using archive_file

Preface

In Terraform the aws_lambda_function has a parameter called source_code_hash. This parameter is a base64-encoded SHA256 hash of the package file specified with either filename or s3_key. The file itself is typically a zip file.

Editing your code and zipping it up over and over can become a tedious process and if you use version control, it’s better practice to just edit a single file and have it zip itself automatically for terraform to use. 

The archive_file is also supported within Terraform Enterprise. 

Tutorial

For this tutorial we will be creating a hello world lambda. A variables.tf is missing however in the real-world you would still likely have one. 

1 Create your main.tf

This is where it gets juicy.

Create your main.tf file. In your main.tf you will have the following Terraform resources created which we will cover below. 

  • Lambda Function
  • Lambda Role
  • Lambda Role Policy for CloudWatch Logs
  • Archiving Lambda Code

At this point you will have an empty main.tf file.

2 Create your lambda source code file

We will be creating a nodejs lambda. So our code will be written in javascript. 

Create a file call example.js within a new folder called lambda. This “lambda” folder will also be used when terraform creates the zip file for you. 

Your handler is your filename.method. So for us it will be example.handler, this will be used later on in the tutorial.

exports.handler = function (event, context) {
  context.succeed('hello world');
};

3 Create Role and policies for Lambda

Your Lambda will likely take some sort of action. For example if your Lambda is rotating access keys then your policies would allow certain IAM functionality. 

Each one of your Lambda uses a Role have the permissions required to serve its purpose. 

Our Lambda role should be allowed to AssumeRole for the Principal Service lambda.amazonaws.com.

resource "aws_iam_role" "lambda_role" {
  name = "LambdaRole"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

Since this is just a simple hello world our policy is very basic. We want out our Lamba to be logged via CloudWatch logs. We want it to be able to

  • Create Log Group
  • Create Log Stream
  • Put Log Events
resource "aws_iam_role_policy" "lambda_role_policy" {
  name = "LambdaRolePolicy"
  role = "${aws_iam_role.lambda_role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",     
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

4 Archiving your source code file

Next, we will archive our hello world example.js

We will make our output_path the same as the source_file directory.

data "archive_file" "lambda_archive" {
  type        = "zip"
  source_file = "${path.module}/lambda/example.js"
  output_path = "${path.module}/lambda/example.zip"
}
You zip file will be generated when you run a terraform plan or terraform apply.

5 Create your Lambda

We now have the necessary components to create our Lambda function.

Things to note:

  • file_name should match your file and filepath.
  • function_name is just a custom name for your function.
  • role will be the role we created earlier.
  • handler like we covered before is filename.method or in our case example.handler.
  • source_code_hash is the base64sha256 output of our archive_file 
  • runtime is nodejs since our hello world is javascript.
resource "aws_lambda_function" "lambda_function" {
  filename         = "${path.module}/lambda/example.zip"
  function_name    = "hello_world_example"
  role             = "${aws_iam_role.lambda_role.arn}"
  handler          = "example.handler"
  source_code_hash = "${data.archive_file.lambda_archive.output_base64sha256}"
  runtime          = "nodejs8.10"
}

Conclusion

Now run your terraform fmt to format your code, terraform plan to make sure everything looks good, and finally terraform apply it!

Testing via Console

Login to your AWS Console and navigate to the Lambda, find and click on your lambda 

Notice how it automatically finds the CloudWatch Logs

Click on test on the top right corner. Give it an Event name. The Event Template Hello World provides some inputs, but we can ignore them as they will not be used. Click on Create.

Click on test once more and it’ll run your Lambda manually. 

If it was successful then it will be green.
Opening the details tab will show you more details including our hello world output

You can view the logs of your Lambda by clicking the “logs” link.

Clicking on a specific “Log Stream” will provide you information regarding the events within them. 

GitHub Repository:

https://github.com/zghafari/terraform-lambda-example

0 comments
3 likes
Prev post: Making GoDaddy (or any other hosting) initial load fasterNext post: Terraform Enterprise vs Open-Source

Related posts

Leave a Reply

Your email address will not be published. Required fields are marked *