Wednesday, March 11, 2020

Terraform Lambda resource lifecycle

Terraform Notes

Lambda resource lifecycle and conditional tags

This example will create Lambda function and initially tag the resource with creation_date and modified_date. But will ONLY update the modified_date IF the python file's hash has changed.
- To prevent creation_date from updating each run, just add this to lambda resource under lifecycle's ignore_changes list.
- To prevent modified_date from updating each run, see the logic in locals below

  • If file does not exist, then set new modified_date
  • If file exists, but hash of the file has changed then set new modified_date


lambda resource

resource "aws_lambda_function" "test_lambda_function" {
  filename = "${path.module}/${var.zip_filename}"
  ## this is the standard handler for python function
  handler = "lambda_function.lambda_handler"
  ## this is just a function name
  function_name = var.function_name
  ## the role arn is obtained from below
  role = aws_iam_role.test_lambda_role.arn
  runtime = "python3.8"
  ## Need this source_code_hash to ensure function is updated when the zip is updated
  source_code_hash = local.new_file_hash
  ## these are the variables that can be used by the code
  environment {
    variables = {
      myvar = var.test
    }
  }
  tags = local.tags
  # Only attributes defined by the resource type can be ignored.
  #  last_modified and source_code_size is only here for illustration purposes.
  #  for tags, any NEW tag creation can't be ignored. 
  # if you create a tag from AWS console that isn't listed, then it will cause update to occur
  # if you set to ignore any tag, this will NOT update the tag after the first run
  lifecycle {
    ignore_changes = [
      last_modified,
      source_code_size,
      tags["creation_date"]
    ]
  }
}

readme file resource

to manage trigger of modified_date tag
resource "local_file" "readme"{
  content = jsonencode({"name"=var.function_name,"lastmodified"=local.new_modified_date,"hash"=local.new_file_hash})
  filename = local.readme_file
}

data call 

to create the zip file from .py file
data "archive_file" "init"{
  type = "zip"
  output_path = local.zip_file_path
  source_dir = "${path.module}/${var.function_filepath}/"
}

variables

variable "region" {
  default = "us-east-1"
}

variable "function_name"{
  default = "test"
}

variable "function_filepath"{
  default = "files"
}

variable "zip_filename"{
  default = "test.zip"
}

variable "test"{
  default = "hello world"
}

locals


locals{
    ## Readme file should reside with the invoking root, because this file can be deleted
    readme_file = "${path.root}/readme.json"
    zip_file_path = "${path.module}/${var.zip_filename}"
    new_file_hash = data.archive_file.init.output_base64sha256
    current_time_stamp = formatdate("YYYY-MM-DD hh:mm:ssZZZZZ", timestamp())
}

## If readme files exists, use existing data
locals{
    ## if this is a new file, then old_mod_date will be current date
    old_modified_date = fileexists(local.readme_file) ? jsondecode(file(local.readme_file)).lastmodified : local.current_time_stamp
    ## if this is a new file, then old_file_hash will be the current hash
    old_file_hash     = fileexists(local.readme_file) ? jsondecode(file(local.readme_file)).hash : local.new_file_hash
}

locals{
    ## if old and new hash are equal then new_mod_date will be old_mod_date, otherwise use the current date, 
    new_modified_date = local.new_file_hash == local.old_file_hash ? local.old_modified_date : local.current_time_stamp
}

## Tags
locals{
  tags = {
    "creation_date" = local.current_time_stamp
    "modified_date" = local.new_modified_date
    "keep_until"    = "0"
    "hash"          = local.new_file_hash
  }
}


No comments:

Post a Comment

AWS WAF log4j query

How to query AWS WAF log for log4j attacks 1. Setup your Athena table using this instruction https://docs.aws.amazon.com/athena/latest/ug/wa...