Terraform - AWS - API网关依赖难题

时间:2017-03-13 09:37:29

标签: aws-api-gateway terraform

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

我有一个模块,它提供Lambda并返回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}"
}

当我从头开始运行上述内容时(即,当没有资源存在时),我收到以下错误:

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有关{1}})。我尝试手动添加aws_api_gateway_deploymentaws_api_gateway_integration的显式依赖项,但这没有效果。

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

非常感谢,

埃德

P.S。我已经问this question on the Terraform user group了,但这似乎对答案的方式很少,我现在还要弄清问题的原因,现在问这里。

1 个答案:

答案 0 :(得分:9)

您对显式依赖声明是正确的。

通常Terraform能够找出关系并相应地安排创建/更新/删除操作 - 这主要是因为引擎机制下的插值机制(${resource_type.ref_name.attribute})。您可以通过terraform graph在图表中显示影响此关系的关系。

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

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

以下是修改代码以解决问题的方法:

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}"

然后就有必要了。

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