12
votes

In the Terraform documentation for AWS_API_GATEWAY_INTEGRATION, the following parameters are supported:

  • rest_api_id
  • resource_id
  • http_method
  • type
  • uri
  • integration_http_method

They give this example:

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}"
  type = "MOCK"
}

But I would like to specify a mapping template (as well as a Lambda integration), as you can with the UI:

enter image description here

However I see no way of doing that with Terraform. Is is possible ?

Note: What I am currently doing is applying the rest of the configuration (lambda, s3, iam etc...), and then adding mapping template manually afterwards (as well as the integration type of lambda).

But then every time I terraform apply to apply some other config (eg: s3), Terraform reverts back the mapping template and the integration type.

The "reverting" plan looks like this:

~ aws_api_gateway_integration.post_hit_integration
    request_templates.#:                "1" => "0"
    request_templates.application/json: "{\n  \"body\" : $input.json('$'),\n  \"headers\": {\n    #foreach($param in $input.params().header.keySet())\n    \"$param\": \"$util.escapeJavaScript($input.params().header.get($param))\" #if($foreach.hasNext),#end\n    \n    #end  \n  },\n  \"stage\" : \"$context.stage\"\n}" => ""
    uri:                                "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-1:000000000000:function:create_hit/invocations" => ""
4

4 Answers

21
votes

Based on this issue, here is a config that works:

(You have to use the params uri, type, integration_http_method and request_templates)

# API
resource "aws_api_gateway_rest_api" "my_api" {
  name = "my_api"
  description = "My Api for adding pets"
}

# Resource
resource "aws_api_gateway_resource" "pets_resource" {
  rest_api_id = "${aws_api_gateway_rest_api.my_api.id}"
  parent_id = "${aws_api_gateway_rest_api.my_api.root_resource_id}"
  path_part = "pets"
}

# Method
resource "aws_api_gateway_method" "post_pet_method" {
  rest_api_id = "${aws_api_gateway_rest_api.my_api.id}"
  resource_id = "${aws_api_gateway_resource.pets_resource.id}"
  http_method = "POST"
  authorization = "NONE"
}

# Integration
resource "aws_api_gateway_integration" "post_pet_integration" {
  rest_api_id = "${aws_api_gateway_rest_api.my_api.id}"
  resource_id = "${aws_api_gateway_resource.pets_resource.id}"
  http_method = "${aws_api_gateway_method.post_pet_method.http_method}"
  uri = "arn:aws:apigateway:${var.region}:lambda:path/2015-03-31/functions/${aws_lambda_function.create_pet.arn}/invocations"
  type = "AWS"                           # Documentation not clear
  integration_http_method = "POST"       # Not documented
  request_templates = {                  # Not documented
    "application/json" = "${file("api_gateway_body_mapping.template")}"
  }
}

And contents of api_gateway_body_mapping.template:

{
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end  
  },
  "stage" : "$context.stage"
}
3
votes

If you are using a Lambda function as the endpoint, the integration type would be "AWS".

Here is the AWS documentation that explains creating a Lambda integration.

Here is a GitHub post that shows how this can be done using Terraform.

Hope that helps! Let us know if you have any questions.

2
votes

If you want to have it inline rather than in a separate template you can do:

request_templates = {                  
  "application/json" =  <<REQUEST_TEMPLATE
  {
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end  
  },
  "stage" : "$context.stage"
  }
  REQUEST_TEMPLATE
}
0
votes

I had similar issue, I couldn't add the Mapping templates as my Integration type was "AWS_PROXY". I changed it to "AWS" and it worked.

Terraform wouldn't consider about mapping templates if the integration type is "AWS_PROXY"

You can learn more about Integration types here.