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:
source_code_hash
of aws_lambda_function resource is stored in Terraform state at the moment Lambda is provisioned.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 runterraform apply
.
So to make it work we have the following options:
- Download Zip package from S3, calculate its hash and pass it to
source_code_hash
field of aws_lambda_function resource OR - 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:
- Generate hash using
openssl dgst -binary -sha256 lambda_package.zip | openssl base64
command. - 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. - 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
...
}