来自 S3 数据的 Terraform lambda source_code_hash 不会留在状态缓存中

use*_*094 4 hash amazon-web-services terraform devops terraform-provider-aws

我有一个用于分配 AWS Lambda 的 Terraform 配置。我希望它在检测到更改时自动更新代码。为此,我正在使用该source_code_hash属性,如下所示。作为构建过程的一部分,我将所有代码压缩,然后用于openssl获取 zip 文件的 SHA256 哈希值,将其粘贴到文本文件中,然后将两者上传到 S3 存储桶。

这是我的 Terraform 配置:

data "aws_s3_bucket_object" "mylambdacode_sha256" {
  bucket = "myapp-builds"
  key    = "build.zip.sha256"
}

resource "aws_lambda_function" "my_lambda" {

  function_name = "${var.lambda_function_name}"
  role = "${aws_iam_role.iam_for_lambda.arn}"
  handler = "index.handler"

  runtime = "nodejs10.x"

  s3_bucket = "myapp-builds"
  s3_key = "build.zip"
  source_code_hash = "${data.aws_s3_bucket_object.mylambdacode_sha256.body}"

  timeout = 900

}
Run Code Online (Sandbox Code Playgroud)

我跑了terraform apply,它告诉我source_code_hash已经改变了:

 ~ source_code_hash               = <<~EOT
          - c9Nl4RRfuh/Z5fJvEOT69GDTJqY9n/QTB5cBGtOniYc=
          + 73d365e1145fba1fd9e5f26f10e4faf460d326a63d9ff4130797011ad3a78987
Run Code Online (Sandbox Code Playgroud)

73d365e1145fba1fd9e5f26f10e4faf460d326a63d9ff4130797011ad3a78987部分确实是 S3 上文件中的内容。所以,这一切看起来都是正确的。但是当我terraform apply之后立即再次运行时,它认为哈希再次发生了变化。

检查.tfstate文件我看到它刚刚说的新哈希没有被保存。

Terraform 是对我的哈希进行哈希处理还是进行其他一些操作并将结果保存到.tfstate? 或者我有什么配置不正确?

编辑:

根据下面的答案,我更新了source_code_hash语句以使用该base64encode函数,如下所示:

source_code_hash = "${base64encode(data.aws_s3_bucket_object.my_lambda_build_sha256.body)}"
Run Code Online (Sandbox Code Playgroud)

这是来自的输出 terraform state show aws_lambda_function.my_lambda && terraform apply && terraform state show aws_lambda_function.my_lambda

$ terraform state show aws_lambda_function.my_lambda && terraform apply && terraform state show aws_lambda_function.my_lambda
# aws_lambda_function.my_lambda:
resource "aws_lambda_function" "my_lambda" {
    arn                            = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda"
    function_name                  = "my_lambda"
    handler                        = "index.handler"
    id                             = "my_lambda"
    invoke_arn                     = "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda/invocations"
    last_modified                  = "2019-08-02T15:00:32.621+0000"
    layers                         = []
    memory_size                    = 128
    publish                        = false
    qualified_arn                  = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda:$LATEST"
    reserved_concurrent_executions = -1
    role                           = "arn:aws:iam::XXXXXXXXXX:role/my_lambda-role"
    runtime                        = "nodejs10.x"
    s3_bucket                      = "myapp-builds"
    s3_key                         = "myapp/build.zip"
    source_code_hash               = "r5D6o1FuCug6FD4QPQ43VdUlfYP4Qe1l1DcElNsf5E0="
    source_code_size               = 12793672
    tags                           = {}
    timeout                        = 900
    version                        = "$LATEST"

    tracing_config {
        mode = "PassThrough"
    }
}
postgresql_database.postgres: Refreshing state... [id=postgres]
aws_iam_policy.lambda_logging: Refreshing state... [id=arn:aws:iam::XXXXXXXXXX:policy/lambda_logging]
aws_cloudwatch_log_group.my_lambda: Refreshing state... [id=/aws/lambda/my_lambda]
aws_iam_role.iam_for_lambda: Refreshing state... [id=my_lambda-role]
aws_cloudwatch_event_rule.my_lambda-rule: Refreshing state... [id=my_lambda-rule]
data.aws_s3_bucket_object.myapp_lambda_build_sha256: Refreshing state...
data.aws_s3_bucket_object.myapp_lambda_build_zip: Refreshing state...
aws_iam_role_policy_attachment.lambda_logs: Refreshing state... [id=my_lambda-role-20190801190935907200000001]
aws_lambda_function.my_lambda: Refreshing state... [id=my_lambda]
aws_lambda_permission.allow_cloudwatch_to_call_trigger_lambda: Refreshing state... [id=AllowExecutionFromCloudWatch]
aws_cloudwatch_event_target.my_lambda-rule-event-target: Refreshing state... [id=my_lambda-rule-terraform-20190801192030362600000001]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_lambda_function.my_lambda will be updated in-place
  ~ resource "aws_lambda_function" "my_lambda" {
        arn                            = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda"
        function_name                  = "my_lambda"
        handler                        = "index.handler"
        id                             = "my_lambda"
        invoke_arn                     = "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda/invocations"
      ~ last_modified                  = "2019-08-02T15:00:32.621+0000" -> (known after apply)
        layers                         = []
        memory_size                    = 128
        publish                        = false
        qualified_arn                  = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda:$LATEST"
        reserved_concurrent_executions = -1
        role                           = "arn:aws:iam::XXXXXXXXXX:role/my_lambda-role"
        runtime                        = "nodejs10.x"
        s3_bucket                      = "myapp-builds"
        s3_key                         = "myapp/build.zip"
      ~ source_code_hash               = "r5D6o1FuCug6FD4QPQ43VdUlfYP4Qe1l1DcElNsf5E0=" -> "YWY5MGZhYTM1MTZlMGFlODNhMTQzZTEwM2QwZTM3NTVkNTI1N2Q4M2Y4NDFlZDY1ZDQzNzA0OTRkYjFmZTQ0ZAo="
        source_code_size               = 12793672
        tags                           = {}
        timeout                        = 900
        version                        = "$LATEST"

        tracing_config {
            mode = "PassThrough"
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_lambda_function.my_lambda: Modifying... [id=my_lambda]
aws_lambda_function.my_lambda: Modifications complete after 1s [id=my_lambda]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
# aws_lambda_function.my_lambda:
resource "aws_lambda_function" "my_lambda" {
    arn                            = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda"
    function_name                  = "my_lambda"
    handler                        = "index.handler"
    id                             = "my_lambda"
    invoke_arn                     = "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda/invocations"
    last_modified                  = "2019-08-02T15:05:08.079+0000"
    layers                         = []
    memory_size                    = 128
    publish                        = false
    qualified_arn                  = "arn:aws:lambda:us-east-2:XXXXXXXXXX:function:my_lambda:$LATEST"
    reserved_concurrent_executions = -1
    role                           = "arn:aws:iam::XXXXXXXXXX:role/my_lambda-role"
    runtime                        = "nodejs10.x"
    s3_bucket                      = "myapp-builds"
    s3_key                         = "myapp/build.zip"
    source_code_hash               = "r5D6o1FuCug6FD4QPQ43VdUlfYP4Qe1l1DcElNsf5E0="
    source_code_size               = 12793672
    tags                           = {}
    timeout                        = 900
    version                        = "$LATEST"

    tracing_config {
        mode = "PassThrough"
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

它适用于我在将其上传到 S3 之前生成“build.zip.sha256”:

openssl dgst -sha256 -binary build.zip | openssl enc -base64 > build.zip.sha256
Run Code Online (Sandbox Code Playgroud)

为了避免 <<~EOT 与我使用的原始 sha256 不匹配:

source_code_hash = chomp(data.aws_s3_bucket_object.my_lambda_build_sha256.body)
Run Code Online (Sandbox Code Playgroud)