每次应用都会替换Terraform 0.12 aws_lambda_permission资源

时间:2019-12-17 07:01:50

标签: amazon-web-services terraform terraform-provider-aws

我正在Terraform v0.12模块中动态创建以下资源:

variables.tf:

variable "stages" {
  type = list(string)
  default = ["v1", "v2"]
}

variable "rest_api_id" {
  description = "The ID of the associated REST API"
}

variable "api_root_resource_id" {
  description = "The API resource ID"
}

variable "region" {
  description = "The AWS region"
}

variable "method" {
  description = "The HTTP method"
  default     = "GET"

variable "lambda" {
  description = "The lambda name to invoke"
}

variable "account_id" {
  description = "The AWS account ID"
}

main.tf

resource "aws_lambda_permission" "lambda_permision" {
  count         = length(var.stages)
  statement_id  = "${var.lambda}${element(var.stages, count.index)}Invoke"
  action        = "lambda:InvokeFunction"
  function_name = "${var.lambda}:${element(var.stages, count.index)}"
  principal     = "apigateway.amazonaws.com"
  source_arn    = "arn:aws:execute-api:${var.region}:${var.account_id}:${var.rest_api_id}/*/${var.method}${aws_api_gateway_resource.api_resource.path}"
}

输入不变。但是每一次申请我都会收到以下通知:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.signurl_get.aws_lambda_permission.lambda_permision[0] must be replaced
-/+ resource "aws_lambda_permission" "lambda_permision" {
        action        = "lambda:InvokeFunction"
      ~ function_name = "peng_lambda_test_version_eu_dev" -> "peng_lambda_test_version_eu_dev:v1" # forces replacement
      ~ id            = "peng_lambda_test_version_eu_devv1Invoke" -> (known after apply)
        principal     = "apigateway.amazonaws.com"
      - qualifier     = "v1" -> null # forces replacement
        source_arn    = "arn:aws:execute-api:eu-west-1:887428995966:t4m0c9z1uk/*/GET/signurl"
        statement_id  = "peng_lambda_test_version_eu_devv1Invoke"
    }

  # module.signurl_get.aws_lambda_permission.lambda_permision[1] must be replaced
-/+ resource "aws_lambda_permission" "lambda_permision" {
        action        = "lambda:InvokeFunction"
      ~ function_name = "peng_lambda_test_version_eu_dev" -> "peng_lambda_test_version_eu_dev:v2" # forces replacement
      ~ id            = "peng_lambda_test_version_eu_devv2Invoke" -> (known after apply)
        principal     = "apigateway.amazonaws.com"
      - qualifier     = "v2" -> null # forces replacement
        source_arn    = "arn:aws:execute-api:eu-west-1:887428995966:t4m0c9z1uk/*/GET/signurl"
        statement_id  = "peng_lambda_test_version_eu_devv2Invoke"
    }

1 个答案:

答案 0 :(得分:4)

使用aws_lambda_permission资源时,您的函数名称应为unqualified Lambda function name。如果您需要指定别名来版本化Lambda,则应使用qualifier parameter代替。

现在,Terraform正在尝试将函数名称设置为包括限定符,并将限定符设置为nil。 AWS API很乐意接受此操作并执行您想要的操作,但是随后当Terraform刷新并更新其状态时,它会看到该函数名称已去除了限定符并且已设置了qualifier参数,因此它尝试将其强制返回到代码告诉它应该的方式。不幸的是,此操作也不支持对Lambda权限资源进行适当的升级,因此它还需要删除现有的Lambda权限并重新创建。

从函数名称中删除限定符并将其添加到适当的qualifier参数中可以解决此问题:

resource "aws_lambda_permission" "lambda_permision" {
  count         = length(var.stages)
  statement_id  = "${var.lambda}${var.stages[count.index]}Invoke"
  action        = "lambda:InvokeFunction"
  function_name = "${var.lambda}"
  qualifier     = ${var.stages[count.index]}"
  principal     = "apigateway.amazonaws.com"
  source_arn    = "arn:aws:execute-api:${var.region}:${var.account_id}:${var.rest_api_id}/*/${var.method}${aws_api_gateway_resource.api_resource.path}"
}

在上面的示例中,我还用带有方括号符号的直线列表索引替换了element函数。如果您需要多次循环遍历列表而不对索引取模,element很有用,否则方括号表示法会更易读且具有相同的行为。

如前所述,当您使用Terraform 0.12时,也可以在不连接字符串和变量时使用新的语法:

resource "aws_lambda_permission" "lambda_permision" {
  count         = length(var.stages)
  statement_id  = "${var.lambda}${var.stages[count.index]}Invoke"
  action        = "lambda:InvokeFunction"
  function_name = var.lambda
  qualifier     = var.stages[count.index]
  principal     = "apigateway.amazonaws.com"
  source_arn    = "arn:aws:execute-api:${var.region}:${var.account_id}:${var.rest_api_id}/*/${var.method}${aws_api_gateway_resource.api_resource.path}"
}