Home > OS >  How to update aws_lambda_function Terraform resource when ZIP package is changed on S3?
How to update aws_lambda_function Terraform resource when ZIP package is changed on S3?

Time:10-04

Zip package is uploaded to S3 not by Terraform.
Lambda is provisioned by Terraform aws_lambda_function resource. When I change Zip package on S3 and run terraform apply command, Terraform says nothing is changed.
There is source_code_hash field in aws_lambda_function resource that can be set to a hash of package content. But whatever value for this hash I provide it's not updated in Terraform state.

How to tell Terraform to update Lambda in case of Zip package update in S3?

CodePudding user response:

After numerous experiments to verify how Terraform handles hash I found the following:

  1. source_code_hash of aws_lambda_function resource is stored in Terraform state at the moment Lambda is provisioned.
  2. source_code_hash is updated only if you provide a new value for it in aws_lambda_function resource and this new value corresponds to hash of actual Zip package in S3.
    So Terraform checks actual hash code of the package on S3 only at this moment, it doesn't check it when we run terraform apply.

So to make it work we have the following options:

  1. Download Zip package from S3, calculate its hash and pass it to source_code_hash field of aws_lambda_function resource OR
  2. Upload Zip package to S3 by Terraform using aws_s3_bucket_object resource. Set source_hash field in that resource to save it in Terraform state. This value can be used by aws_lambda_function resource for updates.

Unfortunately this behaviour is not documented and I spent lots of time discovering it. Moreover it can be changed any moment since it's not documented and nobody knows that :-(

So how I solved this problem?
I generate base64-encoded SHA256 hash of Lambda Zip file and store it as metadata for actual Zip file. Then I read this metadata in Terraform and pass it to source_code_hash.

Details:

  1. Generate hash using openssl dgst -binary -sha256 lambda_package.zip | openssl base64 command.
  2. Store hash as metadata during package uploading using aws s3 cp lambda_package.zip s3://my-best-bucket/lambda_package.zip --metadata hash=[HASH_VALUE] command.
  3. Pass hash to source_code_hash in Terraform
data "aws_s3_bucket_object" "package" {
  bucket = "my-best-bucket"
  key    = "lambda_package.zip"
}

resource "aws_lambda_function" "main" {
  ...
  source_code_hash = data.aws_s3_bucket_object.package.metadata.Hash
  ...
}
  • Related