Aws lambda Terraform API网关与Swagger的集成(Localstack)

Aws lambda Terraform API网关与Swagger的集成(Localstack),aws-lambda,swagger,terraform,aws-api-gateway,localstack,Aws Lambda,Swagger,Terraform,Aws Api Gateway,Localstack,我使用mongoDb和nodeJs创建了一个简单的CRUDAPI lambda,它运行良好。于是我转到另一个步骤 我目前正在使用terraform通过使用来自yaml文件的开放API规范创建一个AWS API网关。 这是我的招摇过市文件: info: description: "API Ankan-v2" version: "V0.0.1" title: "ANKAN V2 API" host: "localhost:4567" basePath: "/restapis/api/{a

我使用mongoDb和nodeJs创建了一个简单的CRUDAPI lambda,它运行良好。于是我转到另一个步骤 我目前正在使用terraform通过使用来自yaml文件的开放API规范创建一个AWS API网关。 这是我的招摇过市文件:

info:
  description: "API Ankan-v2"
  version: "V0.0.1"
  title: "ANKAN V2 API"
host: "localhost:4567"
basePath: "/restapis/api/{apiId}/test/_user_request_"
tags:
  - name: "user"
    description: "Operations about user"
schemes:
  - "http"
#    - "https"
paths:
  /documents/{documentId}:
    get:
      tags:
        - "document"
      summary: "Find document by ID"
      description: "Returns a single document"
      operationId: "readOneDocument"
      produces:
        - "application/json"
      parameters:
        - name: "documentId"
          in: "path"
          description: "Id of document"
          required: true
          type: "string"
      responses:
        200:
          description: "successful operation"
          schema:
            $ref: "#/definitions/Document"
        404:
          description: "document not found"
      x-amazon-apigateway-integration:
        uri: ${get_lambda_arn}
        passthroughBehavior: "WHEN_NO_MATCH"
        httpMethod: "POST"
        type: "AWS_PROXY"
    options:
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - name: "documentId"
          in: "path"
          description: "Id of document"
          required: true
          type: "string"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Document"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "when_no_match"
        type: "mock"
    x-amazon-apigateway-any-method:
      produces:
        - "application/json"
      parameters:
        - name: "documentId"
          in: "path"
          description: "Id of document"
          required: true
          type: "string"
      responses: {}
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
        uri: ${get_lambda_arn}
        passthroughBehavior: "WHEN_NO_MATCH"
        httpMethod: "POST"
        cacheNamespace: "1rnijn"
        cacheKeyParameters:
          - "method.request.path.documentId"
        type: "AWS"
definitions:
  Document:
    type: "object"
    required:
      - "documentName"
      - "documentPath"
      - "miniature"
      - "status"
      - "date"
    properties:
      _id:
        type: "string"
        readOnly: true
      documentName:
        type: "string"
      documentPath:
        type: "string"
      miniature:
        type: "string"
      status:
        type: "string"
        enum:
          - "VALID"
          - "ERROR"
          - "ONLOAD"
      date:
        type: "string"
        format: "date"
    xml:
      name: "Document" 
在我的terraform中,我删除了集成和方法,因为我在招摇中添加了它们。 因此,我需要导入aws_api_gateway_rest_api中的swagger文件,并使用
body=data.template_file.swagger.rendered

resource "aws_api_gateway_rest_api" "api" {
  name = "api-gateway"
  description = "document api"
  body = data.template_file.swagger.rendered

}


data "template_file" "swagger" {
  template = jsonencode("${path.module}/../../../../shared/swagger.yaml")

  vars = {
    get_lambda_arn = local.get_lambda_arn
  }
}
output "json" {
  value = data.template_file.swagger.rendered
}

locals {
  get_lambda_arn = aws_lambda_function.lambda_document.invoke_arn
}

resource "aws_api_gateway_resource" "documents" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  parent_id   = aws_api_gateway_rest_api.api.root_resource_id
  path_part   = "documents"
  depends_on  = [aws_api_gateway_rest_api.api]
}

resource "aws_api_gateway_resource" "document_by_id" {
  parent_id   = aws_api_gateway_resource.documents.id
  path_part   = "{documentId}"
  rest_api_id = aws_api_gateway_rest_api.api.id
}


resource "aws_api_gateway_deployment" "ApiDeloyment" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  stage_name = "INT"

  depends_on = [aws_api_gateway_rest_api.api]
}


resource "aws_lambda_function" "lambda_document" {
  function_name = "lambda_document"
  handler = "lambda.handler"
  role = "arn:aws::iam::123456:role/irrelevant"
  runtime = "nodejs10.x"
  filename = "${path.module}/lambda.zip"

  source_code_hash = filebase64sha256("${path.module}/lambda.zip")
}
在terraform应用之后,我在terraform日志中得到了这条消息

terraform apply --auto-approve
module.backend_api.module.document.aws_api_gateway_rest_api.api: Creating...
module.backend_api.module.document.aws_lambda_function.lambda_document: Creating...
module.backend_api.module.document.aws_lambda_function.lambda_document: Creation complete after 5s [id=lambda_document]
module.backend_api.module.document.data.template_file.swagger: Refreshing state...
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [10s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [20s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [30s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [40s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [50s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [1m0s elapsed]
module.backend_api.module.document.aws_api_gateway_rest_api.api: Still creating... [1m10s elapsed]
我的docker compose日志显示了这一点

localstack        | 2020-01-13T07:37:56:ERROR:localstack.services.generic_proxy: Error forwarding request: Expecting value: line 1 column 1 (char 0) Traceback (most recent call last):
localstack        |   File "/opt/code/localstack/localstack/services/generic_proxy.py", line 242, in forward
localstack        |     path=path, data=data, headers=forward_headers)
localstack        |   File "/opt/code/localstack/localstack/services/apigateway/apigateway_listener.py", line 53, in forward_request
localstack        |     data = data and json.loads(to_str(data))
localstack        |   File "/usr/lib/python3.7/json/__init__.py", line 348, in loads
localstack        |     return _default_decoder.decode(s)
localstack        |   File "/usr/lib/python3.7/json/decoder.py", line 337, in decode
localstack        |     obj, end = self.raw_decode(s, idx=_w(s, 0).end())
localstack        |   File "/usr/lib/python3.7/json/decoder.py", line 355, in raw_decode
localstack        |     raise JSONDecodeError("Expecting value", s, err.value) from None
localstack        | json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
PS:我试过使用JSON,但也有同样的问题


有什么解决办法吗?我想在localstack中使用terraform将swagger与api网关集成这是moto库的一个问题。在后台,本地堆栈使用moto创建其资源,包括模拟api网关。不幸的是,moto目前不支持将swagger文件定义作为api网关部署的一部分的body参数。因此,即使您提供了有效的swagger文件和api网关配置(即在aws中工作的配置),localstack也无法构建它。

它对“真正的”aws有效吗?不,我没有尝试过,我使用的是带有localstack的aws。这似乎是aws的限制。我不这么认为,因为它与aws cli一起工作,在我的情况下,我希望将terraform和localstack与代码一起使用,而不是aws cli。