3
votes

I am creating the APIs in AWS API Gateway. All the infrastructure in AWS is managed by using terraform In order to continue the same would like add the API config in terraform. I have the API resource definition in swagger generated by swagger dependency tool added in the application.

I need to integrate it with terraform, but when I try to apply I have to import each resource from the AWS created by swagger multiple times. Only the API Gateway configuration should be in terraform and the resource definition should be from the swagger, Is there any way to achieve that. Also I need to automate the flow for 100s of APIs, please suggest how it can be done.

Please share any relevant github links

Here is what I have tried so far,

resource "aws_api_gateway_rest_api" "api" {
  name = "Hello-API"
  description  = "Proxy to handle requests to our API"
  body = "${file("api_swagger_example.json")}"
}


//Resource created by swagger
data "aws_api_gateway_resource" "helloApp" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  path        = "/api/v1/hello"
}


//Need to import from first, since it was created using swagger
resource "aws_api_gateway_method" "helloApp-POST" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "POST"
  authorization = "NONE"
}

//Importing first
resource "aws_api_gateway_method_response" "response_200" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "200"
  response_parameters = "${var.method_response_parameters}"
}

//Importing first
resource "aws_api_gateway_method_response" "response_401" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "401"
  response_parameters = "${var.method_response_parameters}"
}

resource "aws_api_gateway_integration_response" "helloApp-ok" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "${aws_api_gateway_method_response.response_200.status_code}"
  response_parameters = "${var.integration_response_parameters}"
}

resource "aws_api_gateway_integration_response" "helloApp-401" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "${aws_api_gateway_method_response.response_401.status_code}"
  selection_pattern = "4\\d{2}"
  response_parameters = "${var.integration_response_parameters}"
}



//Importing first
resource "aws_api_gateway_method_response" "helloApp_response_200" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "200"
  response_parameters = "${var.method_response_parameters}"
}

//Importing first
resource "aws_api_gateway_method_response" "helloApp_response_401" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "401"
  response_parameters = "${var.method_response_parameters}"
}


resource "aws_api_gateway_integration" "helloAppIntegration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  type = "HTTP"
  integration_http_method = "POST"
  connection_type = "VPC_LINK"
  connection_id   = "${data.aws_api_gateway_vpc_link.hello_vpc_link.id}"
  uri = "${var.hello-endpoint-url}"
  request_templates = {
    "application/json" =  <<REQUEST_TEMPLATE
        $input.json('$')
        REQUEST_TEMPLATE
  }
}


resource "aws_api_gateway_integration_response" "helloApp-ok" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "${aws_api_gateway_method_response.helloApp_response_200.status_code}"
  response_parameters = "${var.integration_response_parameters}"
}

resource "aws_api_gateway_integration_response" "helloApp-401" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${data.aws_api_gateway_resource.helloApp.id}"
  http_method = "${aws_api_gateway_method.helloApp-POST.http_method}"
  status_code = "${aws_api_gateway_method_response.helloApp_response_401.status_code}"
  selection_pattern = "4\\d{2}"
  response_parameters = "${var.integration_response_parameters}"
}

resource "aws_api_gateway_deployment" "deploy-dev" {
  depends_on  = [
    "aws_api_gateway_integration.helloAppIntegration",
    "aws_api_gateway_method.helloApp-POST"
  ]
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name  = "dev"
}

resource "aws_api_gateway_stage" "dev" {
  stage_name    = "dev"
  rest_api_id   = "${aws_api_gateway_rest_api.api.id}"
  deployment_id = "${aws_api_gateway_deployment.deploy-dev.id}"
}

resource "aws_api_gateway_usage_plan" "dev-usage-plan" {
  name         = "hello-usage-plan"
  description  = "hello API Basic Usage Plan"

  api_stages {
    api_id = "${aws_api_gateway_rest_api.api.id}"
    stage  = "${aws_api_gateway_deployment.deploy-dev.stage_name}"
  }

  throttle_settings {
    burst_limit = 5
    rate_limit  = 10
  }
}
resource "aws_api_gateway_method_settings" "helloApp-POST" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  stage_name  = "${aws_api_gateway_stage.dev.stage_name}"
  method_path = "${data.aws_api_gateway_resource.helloApp.path_part}/${aws_api_gateway_method.helloApp-POST.http_method}"

  settings {
    metrics_enabled = true
    logging_level   = "INFO"
  }
}

It was so annoying and practically not possible to import every resource for all the APIs and updating. Any better way to integrate?

1
What have you tried so far? Have you looked at the body argument in the aws_api_gateway_rest_api resource?ydaetskcoR
Yes, I have used the "body" to integrate swagger with terraform. Adding my implementation in the questionAli

1 Answers

5
votes

You need to use a template_file resource which will create a swagger file template for AWS API gateway by reading a source swagger file.

Then just use aws_api_gateway_rest_api resource by passing rendered swagger file as body. To create Integration, you need to add it in swagger file itself.

 data "template_file" "aws_api_swagger" 
 {
  template = "${file(var.swagger-file-path)}"

  #Pass the varible value if needed in swagger file
  vars = {
   connectionType = "${var.connectiontype}"
   type           = "${var.type}"
   backend_uri   = "https://api.endpoint.url"
  }
}

resource "aws_api_gateway_rest_api" "api-gateway" 
{
  name        = "${var.name}"
  description = "${var.description}"
  body        = "${data.template_file.aws_api_swagger.rendered}"
}

Swagger file snippet to refer

paths:
/:
get:
  tags:
    - sample
  description: sample
  responses:
    "200":
      description: Success
  x-amazon-apigateway-integration:
    uri: ${backend_url}/health-check
    connectionType: ${connectionType}
    passthroughBehavior: "when_no_match"
    httpMethod: "GET"
    type: ${type}

Also refer here to use x-amazon-apigateway-integration in swagger file in details