Relative paths in Terraform

Manoj Acharya picture Manoj Acharya · Dec 19, 2018 · Viewed 9.1k times · Source

I am trying to create an AWS lambda Function using terraform. My terraform directory looks like

  • terraform
    • iam-policies
      • main.tf
    • lambda
      • files/
      • main.tf
    • main.tf

I have my lambda function stored inside /terraform/lambda/files/lambda_function.py.

Whenever I terraform apply, I have a "null_resource" that executes some commands in local machine that will zip the python file

variable "pythonfile" {
  description = "lambda function python filename"
  type        = "string"
}

resource "null_resource" "lambda_preconditions" {
  triggers {
    always_run = "${uuid()}"
  }
  provisioner "local-exec" {
    command = "rm -rf ${path.module}/files/zips"
  }
  provisioner "local-exec" {
    command = "mkdir -p ${path.module}/files/zips"
  }
  provisioner "local-exec" {
    command = "cp -R ${path.module}/files/${var.pythonfile} ${path.module}/files/zips/lambda_function.py"
  }
  provisioner "local-exec" {
    command = "cd ${path.module}/files/zips && zip -r lambda.zip ."
  }
}

My "aws_lambda_function" resource looks like this.

resource "aws_lambda_function" "lambda_function" {
  filename         = "${path.module}/files/zips/lambda.zip"
  function_name    = "${format("%s-%s-%s-lambda-function", var.name, var.environment, var.function_name)}"
  role             = "${aws_iam_role.iam_for_lambda.arn}"
  handler          = "lambda_function.lambda_handler"
  source_code_hash = "${base64sha256(format("%s/files/zips/lambda.zip", path.module))}", length(path.cwd) + 1, -1)}")}"
  runtime          = "${var.function_runtime}"
  timeout          = "${var.function_timeout}"
  memory_size      = "${var.function_memory}"

  environment {
    variables = {
      region      = "${var.region}"
      name        = "${var.name}"
      environment = "${var.environment}"
    }
  }

  vpc_config {
    subnet_ids         = ["${var.subnet_ids}"]
    security_group_ids = ["${aws_security_group.lambda_sg.id}"]
  }

  depends_on = [
    "null_resource.lambda_preconditions"
  ]
}

Problem: Whenever I change the lambda_function.py file and terraform apply again, everything works fine but the actual code in the lambda function do not change. Also if I delete all the terraform state files and apply again, the new change is propagated without any problem.

What could be the possible reason for this?

Answer

Manoj Acharya picture Manoj Acharya · Feb 5, 2019

Instead of using null_resource, I used the archive_file data source that creates the zip file automatically if new changes are detected. Next I took a reference from the archive_file data in the lambda resource source_code_hash attribute.

archive_file data source

data "archive_file" "lambda_zip" {
  type        = "zip"
  output_path = "${path.module}/files/zips/lambda.zip"

  source {
    content  = "${file("${path.module}/files/ebs_cleanup_lambda.py")}"
    filename = "lambda_function.py"
  }
}

The lambda resource

resource "aws_lambda_function" "lambda_function" {
  filename         = "${path.module}/files/zips/lambda.zip"
  function_name    = "${format("%s-%s-%s-lambda-function", var.name, var.environment, var.function_name)}"
  role             = "${aws_iam_role.iam_for_lambda.arn}"
  handler          = "lambda_function.lambda_handler"
  source_code_hash = "${data.archive_file.lambda_zip.output_base64sha256}"
  runtime          = "${var.function_runtime}"
  timeout          = "${var.function_timeout}"
  memory_size      = "${var.function_memory}"

  environment {
    variables = {
      region      = "${var.region}"
      name        = "${var.name}"
      environment = "${var.environment}"
    }
  }

  vpc_config {
    subnet_ids         = ["${var.subnet_ids}"]
    security_group_ids = ["${aws_security_group.lambda_sg.id}"]
  }
}