为什么使用terraform创建API网关的方法响应不同?

Bri*_*ian 9 amazon-web-services terraform aws-api-gateway

我有以下 terraform 脚本,它创建一个 API 网关,将请求传递给 lambda 函数。

provider "aws" {

  access_key = "${var.access_key}"

  secret_key = "${var.secret_key}"
  # 
  region     = "${var.region}"

  version = "~> 2.6"
}

resource "aws_api_gateway_rest_api" "MyDemoAPI" {
  name        = "MyDemoAPI"
  description = "This is my API for demonstration purposes"
}

resource "aws_api_gateway_resource" "MyDemoResource" {
  rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
  parent_id   = "${aws_api_gateway_rest_api.MyDemoAPI.root_resource_id}"
  path_part   = "mydemoresource"
}

resource "aws_api_gateway_method" "MyDemoMethod" {
  rest_api_id   = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
  resource_id   = "${aws_api_gateway_resource.MyDemoResource.id}"
  http_method   = "POST"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "MyDemoIntegration" {
  rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
  resource_id = "${aws_api_gateway_resource.MyDemoResource.id}"
  http_method = "${aws_api_gateway_method.MyDemoMethod.http_method}"
  integration_http_method = "POST"
  type        = "AWS_PROXY"
  uri         = "arn:aws:apigateway:ap-southeast-1:lambda:path/2015-03-31/functions/${aws_lambda_function.test_lambda_function.arn}/invocations"
  content_handling = "CONVERT_TO_TEXT"
}

resource "aws_api_gateway_method_response" "200" {
  rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
  resource_id = "${aws_api_gateway_resource.MyDemoResource.id}"
  http_method = "${aws_api_gateway_method.MyDemoMethod.http_method}"
  status_code = "200"
  response_models {
     "application/json" = "Empty"
  }
}

resource "aws_lambda_function" "test_lambda_function" {
  filename         = "lambda.zip"
  description      = "test build api gateway and lambda function using terraform"
  function_name    = "test_lambda_function"
  role             = "arn:aws:iam::123456789123:role/my_labmda_role"
  handler          = "gateway.lambda_handler"
  runtime          = "python3.6"
  memory_size      = 128
  timeout          = 60
}
Run Code Online (Sandbox Code Playgroud)

Method ResponseAPI网关资源显示的部分Select an integration response.

在此处输入图片说明

但是,如果我使用 AWS 控制台创建相同的 API 网关,该 Method Response部分会显示不同的内容:

在此处输入图片说明

为什么会发生这种情况?

以下步骤是我使用 AWS 控制台创建 API 网关的方法:

  1. Create Method在资源下选择。 在此处输入图片说明

  2. 选择POST方法。 在此处输入图片说明

  3. 选择所需的选项。 在此处输入图片说明

我尝试先手动创建上述资源,然后执行terraform apply. 然后 terraform 告诉我什么都不需要改变。

terraform apply
aws_api_gateway_rest_api.MyDemoAPI: Refreshing state... (ID: 1qa34vs1k7)
aws_lambda_function.test_lambda_function: Refreshing state... (ID: test_lambda_function)
aws_api_gateway_resource.MyDemoResource: Refreshing state... (ID: 4xej81)
aws_api_gateway_method.MyDemoMethod: Refreshing state... (ID: agm-1qa34vs1k7-4xej81-POST)
aws_api_gateway_method_response.200: Refreshing state... (ID: agmr-1qa34vs1k7-4xej81-POST-200)
aws_api_gateway_integration.MyDemoIntegration: Refreshing state... (ID: agi-1qa34vs1k7-4xej81-POST)

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Run Code Online (Sandbox Code Playgroud)

这似乎意味着手动构建的结构与terraform构建的结构相同。

Tha*_*ssi 10

因为 API Gateway 是一个复杂的 AWS 组件,您几乎可以控制其上的所有内容(基本上它的每个部分都是独立管理的,让您可以对自己创建的内容进行大量控制,但同时也让事情变得更难处理)。

看到它说“选择一个集成响应”,但由于您的 Terraform 代码没有创建一个,因此它是空的。

几周前我遇到了同样的问题,我在 Terraform 的GitHub 上找到了解决方案。我认为 Terraform 应该更好地记录这一点,因为您不是第一个提出这个问题的人,也不会是最后一个提出这个问题的人。好吧,至少我们现在已经在 StackOverflow 中记录了这一点:)

长话短说,您需要向aws_api_gateway_integration_responseAPI 网关添加terraform 资源。

resource "aws_api_gateway_integration_response" "MyDemoIntegrationResponse" {
   rest_api_id = "${aws_api_gateway_rest_api.MyDemoAPI.id}"
   resource_id = "${aws_api_gateway_resource.MyDemoResource.id}"
   http_method = "${aws_api_gateway_method.MyDemoMethod.http_method}"
   status_code = "${aws_api_gateway_method_response.200.status_code}"

   response_templates = {
       "application/json" = ""
   } 
}
Run Code Online (Sandbox Code Playgroud)

但是,如果可以,我建议您使用适当的框架将事件挂钩到您的 Lambda 函数(如无服务器框架AWS SAM),因为在 Terraform 中创建它们非常冗长且容易出错。

通常,我将 Terraform 和无服务器框架结合在一起:我使用 Terraform 创建基础设施资源——即使它们是无服务器的——比如 DynamoDB 表、SQS 队列、SNS 主题等,并使用无服务器框架来创建 Lambda 函数及其相应的事件。


bab*_*s21 8

我遇到过同样的问题。泰雷兹的建议对我不起作用(使用 terraform 0.11.14 和 AWS 插件 2.52.0)。

相反,我使用api_gateway_method_response资源并将response_models参数设置为:

response_models = {
    "application/json" = "Empty"
}
Run Code Online (Sandbox Code Playgroud)

然后它向我显示了我通过控制台创建的所有其他 API 所显示的默认响应!

在此输入图像描述

在 Terraform 文档中不太清楚这应该是什么样子,必须经过多次尝试才能弄清楚。