Terraform - AWS - API 网关依赖性难题

Terraform - AWS - API Gateway dependency conundrum

我正在尝试提供一些 AWS 资源,特别是连接到 Lambda 的 API 网关。我正在使用 Terraform v0.8.8。

我有一个提供 Lambda 和 returns lambda 函数 ARN 作为输出的模块,然后我将其作为参数提供给以下 API 网关配置代码(基于the example in the TF docs):

provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

# Variables
variable "myregion" { default = "eu-west-2" }
variable "accountId" { default = "" }
variable "lambdaArn" { default = "" }
variable "stageName" { default = "lab" }

# API Gateway
resource "aws_api_gateway_rest_api" "api" {
  name = "myapi"
}

resource "aws_api_gateway_method" "method" {
  rest_api_id   = "${aws_api_gateway_rest_api.api.id}"
  resource_id   = "${aws_api_gateway_rest_api.api.root_resource_id}"
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "integration" {
  rest_api_id             = "${aws_api_gateway_rest_api.api.id}"
  resource_id             = "${aws_api_gateway_rest_api.api.root_resource_id}"
  http_method             = "${aws_api_gateway_method.method.http_method}"
  integration_http_method = "POST"
  type                    = "AWS"
  uri                     = "arn:aws:apigateway:${var.myregion}:lambda:path/2015-03-31/functions/${var.lambdaArn}/invocations"
}

# Lambda
resource "aws_lambda_permission" "apigw_lambda" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = "${var.lambdaArn}"
  principal     = "apigateway.amazonaws.com"
  source_arn    = "arn:aws:execute-api:${var.myregion}:${var.accountId}:${aws_api_gateway_rest_api.api.id}/*/${aws_api_gateway_method.method.http_method}/resourcepath/subresourcepath"
}

resource "aws_api_gateway_deployment" "deployment" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name = "${var.stageName}"
}

当我 运行 从头开始​​执行上述操作时(即当 none 的资源存在时)我得到以下错误:

Error applying plan:

1 error(s) occurred:

* aws_api_gateway_deployment.deployment: Error creating API Gateway Deployment: BadRequestException: No integration defined for method
    status code: 400, request id: 15604135-03f5-11e7-8321-f5a75dc2b0a3

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

如果我执行第二次 TF 应用程序,它始终会成功应用,但每次我销毁时,我都会在第一次应用程序时收到上述错误。

这让我想知道是否有一个依赖项需要在某处显式声明,我发现 #7486,它描述了一个类似的模式(尽管与 aws_api_gateway_integration_response 而不是 aws_api_gateway_deployment).我尝试手动添加从 aws_api_gateway_deploymentaws_api_gateway_integration 的显式依赖项,但这没有效果。

感谢任何想法,包括这是否确实是一个 TF 错误,在这种情况下我会在问题跟踪器中提出它。我想我会在这样做之前先与社区核实一下,以防遗漏一些明显的东西。

非常感谢,

埃德

P.S。我已经问过 this question on the Terraform user group,但这似乎对回复的影响很小,我还没有弄清楚问题的原因,因此现在在这里提问。

关于显式依赖声明,你是对的。

通常情况下,Terraform 能够找出关系并据此安排 create/update/delete 操作 - 由于引擎盖下的插值机制 (${resource_type.ref_name.attribute}),这很可能是可能的。您可以通过 terraform graph.

在图表中显示影响此的关系

不幸的是,在这种特定情况下,API 网关部署和集成之间没有直接关系 - 这意味着用于管理 API 网关资源的 API 接口不需要您参考集成ID 或类似的东西来创建部署和 api_gateway_deployment 资源反过来也不需要。

documentation for aws_api_gateway_deployment 确实在页面顶部提到了这个警告。诚然,部署不仅需要方法存在,还需要集成。

以下是修改代码以绕过它的方法:

resource "aws_api_gateway_deployment" "deployment" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name = "${var.stageName}"
  depends_on = ["aws_api_gateway_method.method", "aws_api_gateway_integration.integration"]
}

理论上 "aws_api_gateway_method.method" 是多余的,因为集成已经引用了配置中的方法:

http_method             = "${aws_api_gateway_method.method.http_method}"

因此无论哪种方式都将安排在 creation/update 集成之前,但是如果您要将其更改为

http_method             = "GET"

那就有必要了。

我有 submitted PR 相应地更新文档。