This helps creating an AWS API GW with a POST
method on the root resource (i.e /
) targetting a given Lambda.
The current Terraform documentation is exposing a Mock integration. Thus, a few options are missing when wanting to expose a Lambda integration instead.
There are a few things to know:
First of all, you will need to add the integration_http_method
alongside the http_method
, as in:
resource "aws_api_gateway_integration" "dummy_integration" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy_method.http_method}"
integration_http_method = "${aws_api_gateway_method.dummy_method.http_method}"
type = "AWS"
uri = "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${aws_lambda_function.dummy_lambda.arn}/invocations"
}
Not setting it would lead to this error:
[...] Error creating API Gateway Integration: BadRequestException: Enumeration value for HttpMethod must be non-empty
Even if it is explicitely written in the documentation, it is not really highlighted so this may be forgotten ;-)
Then you will need to explicitely set the depends_on
on the integration response as per this thread.
resource "aws_api_gateway_integration_response" "dummy_integration_response" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy_method.http_method}"
status_code = "${aws_api_gateway_method_response.200.status_code}"
depends_on = ["aws_api_gateway_integration.dummy_integration"]
}
Not setting it would lead to this error:
[...] Error creating API Gateway Integration Response: NotFoundException: No integration defined for method
A future Terraform release might remove the need for this.
Finally, if you want to add a method on the root resource (i.e the first slash in the URL, /
), the first idea that might come out would be to create a aws_api_gateway_resource
resource and use it afterthat, as in:
resource "aws_api_gateway_resource" "dummy" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
parent_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
path_part = ""
}
...
resource "aws_api_gateway_integration_response" "dummy_integration_response" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_resource.dummy.id}"
http_method = "${aws_api_gateway_method.dummy.http_method}"
status_code = "${aws_api_gateway_method_response.200.status_code}"
}
...
However, as the path_part
can not be empty nor be set to /
, this is not the way to go (spoiler: it would throw an error for each case).
In order to target the root resource (i.e /
), you will need to use the root_resource_id
of your API Gateway, as in aws_api_gateway_rest_api.dummy.root_resource_id
. The above code would then be (the third line changed):
resource "aws_api_gateway_integration_response" "dummy_integration_response" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy.http_method}"
status_code = "${aws_api_gateway_method_response.200.status_code}"
}
resource "aws_api_gateway_rest_api" "dummy" {
name = "dummy-apigw"
description = "Dummy API GW"
}
resource "aws_api_gateway_method" "dummy_method" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "POST"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "dummy_integration" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy_method.http_method}"
integration_http_method = "${aws_api_gateway_method.dummy_method.http_method}"
type = "AWS"
uri = "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${aws_lambda_function.dummy_lambda.arn}/invocations"
}
resource "aws_api_gateway_method_response" "200" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy_method.http_method}"
status_code = "200"
}
resource "aws_api_gateway_integration_response" "dummy_integration_response" {
rest_api_id = "${aws_api_gateway_rest_api.dummy.id}"
resource_id = "${aws_api_gateway_rest_api.dummy.root_resource_id}"
http_method = "${aws_api_gateway_method.dummy_method.http_method}"
status_code = "${aws_api_gateway_method_response.200.status_code}"
depends_on = ["aws_api_gateway_integration.dummy_integration"]
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "dummy_lambda" {
filename = "mydummyfile.zip"
function_name = "dummy_lambda"
role = "${aws_iam_role.iam_for_lambda.arn}"
handler = "entrypoint.handler"
runtime = "python2.7"
source_code_hash = "${base64sha256(file('mydummyfile.zip'))}"
}
thanks a lot