在API网关资源中创建可变数量的方法和资源

时间:2019-02-12 22:48:03

标签: terraform

我目前使用Lambda函数,该函数使用API​​网关作为触发器,并且API网关内的方法和端点是手动创建的。我正在尝试将其移至使用Terraform自动创建的位置。不过,我对Terraform还是很陌生,由于每个lambda函数的方法和端点的数量可能不同,因此我很难弄清楚如何创建循环结构。

我已经阅读了模板和内插法,但是由于我需要两层,所以我无法真正拼凑出最佳解决方案

这是我手动创建网关资源时可能会遇到的问题的一个示例。假设端点的数量可以变化,并且每个端点内的方法数量也可以变化。

{
  "api_name" : "branches",
  "api_description" : "Branches API",
  "endpoints" : [
    {
      "name" : "branch1",
      "path" : "branch1/Retail/GetData",
     "methods" : [
        {
          "type" : "get",
          "folder" : "branches",
          "handler" : "index.handler",
          "authenticator": false
        }
      ]
    },
    {
      "name" : "branch2",
      "path" : "branch2/Retail/GetData",
      "methods" : [
        {
          "type" : "get",
          "folder" : "branches",
          "handler" : "index.get_handler",
          "authenticator": false
        },
        {
          "type" : "post",
          "folder" : "branches",
          "handler" : "index.post_handler",
          "authenticator": false
        }
      ]
    }
  ]
} 

我希望最终结果产生这样的东西:

resource "aws_api_gateway_rest_api" "LambdaTrigger" {
  name        = "${var.API_NAME}"
  description = "${var.API_DESCRIPTION}"
}

resource "aws_api_gateway_resource" "Resource1" {
  rest_api_id = "${aws_api_gateway_rest_api.LambdaTrigger.id}"
  parent_id   = "${aws_api_gateway_rest_api.LambdaTrigger.root_resource_id}"
  path_part   = "GetData"
}

resource "aws_api_gateway_method" "Method1" {
  rest_api_id   = "${aws_api_gateway_rest_api.LambdaTrigger.id}"
  resource_id   = "${aws_api_gateway_resource.Resource1.id}"
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_resource" "Resource2" {
  rest_api_id = "${aws_api_gateway_rest_api.LambdaTrigger.id}"
  parent_id   = "${aws_api_gateway_rest_api.LambdaTrigger.root_resource_id}"
  path_part   = "GetData"
}

resource "aws_api_gateway_method" "Method2" {
  rest_api_id   = "${aws_api_gateway_rest_api.LambdaTrigger.id}"
  resource_id   = "${aws_api_gateway_resource.Resource2.id}"
  http_method   = "GET"
  authorization = "NONE"
}
resource "aws_api_gateway_method" "Method2" {
  rest_api_id   = "${aws_api_gateway_rest_api.LambdaTrigger.id}"
  resource_id   = "${aws_api_gateway_resource.Resource2.id}"
  http_method   = "POST"
  authorization = "NONE"
}

1 个答案:

答案 0 :(得分:0)

由于您无法按需要进行循环,并且模块当前不支持count,因此可以通过module创建资源/方法组,然后每次调用模块以获取资源/模块组。

我使用path_part字段调整了元数据对象。

{
  "api_name" : "branches",
  "api_description" : "Branches API",
  "endpoints" : [
    {
      "name" : "branch1",
      "path" : "branch1/Retail/GetData",
      "path_part": "GetData",  // added for simplicity
     "methods" : [
        {
          "type" : "get",
          "folder" : "branches",
          "handler" : "index.handler",
          "authenticator": false
        }
      ]
    },
    {
      "name" : "branch2",
      "path" : "branch2/Retail/GetData",
      "path_part": "GetData",  //added for simplicity
      "methods" : [
        {
          "type" : "get",
          "folder" : "branches",
          "handler" : "index.get_handler",
          "authenticator": false
        },
        {
          "type" : "post",
          "folder" : "branches",
          "handler" : "index.post_handler",
          "authenticator": false
        }
      ]
    }
  ]
} 

这是用于制作资源及其方法的模块。它会放在一个单独的文件夹中,供您的主文件引用。对于任何terraform项目,我倾向于为所有模块都拥有一个modules文件夹,因此类似./modules/api_resources

# variables.tf
variable "rest_api_id" {
  type = "string"
}
variable "rest_api_root_resource_id" {
  type = "string"
}
variable "endpoints" {
  type = "list"
}
# main.tf
resource "aws_api_gateway_resource" "resource" {
  rest_api_id = "${var.rest_api_id}"
  parent_id   = "${var.rest_api_root_resource_id}"

  path_part   = "${var.endpoints[count.index].path_part}"
}

resource "aws_api_gateway_method" "method" {
  count = "${length(var.endpoint.methods)}"

  rest_api_id = "${var.rest_api_id}"
  resource_id   = "${aws_api_gateway_resource.resource.id}"
  http_method   = "${var.endpoint.methods[count.index].type}"
  authorization = "${var.endpoint.methods[count.index].authenticator ? "WHATEVER_AUTH_TYPE_YOU_ARE_USING" : "NONE"}"
}
#outputs.tf
output "resource_id" {
  value = "${aws_api_gateway_resource.resource.id}"
}
output "resource_path" {
  value = "${aws_api_gateway_resource.resource.path}"
}

现在,您可以在main.tf中为endpoints的每个部分使用一次该模块。

resource "aws_api_gateway_rest_api" "lambda_trigger" {
  name        = "${var.api_name}"
  description = "${var.api_description}"
}

module "resource1" {
  source = "./modules/api_resources"
  rest_api_id = "${aws_api_gateway_rest_api.lambda_trigger.id}"
  rest_api_root_resource_id = "${aws_api_gateway_rest_api.lambda_trigger.root_resource_id}"
  endpoints = "${var.endpoints[0]}"
}


module "resource2" {
  source = "./modules/api_resources"
  rest_api_id = "${aws_api_gateway_rest_api.lambda_trigger.id}"
  rest_api_root_resource_id = "${aws_api_gateway_rest_api.lambda_trigger.root_resource_id}"
  endpoints = "${var.endpoints[1]}"
}