I have to integrate more than 50 Lambda functions with relevant api gateway method. So that I create a terraform map with Lambda function name and api gateway resource path as below.
variable "lambdas" {
description = "Map of Lambda function names and API gateway resource paths."
type = map
default = {
user = {
name = "user-lambda-function"
path = "user"
},
products= {
name = "products-lambda-function"
path = "products"
},
orders= {
name = "orders-lambda-function"
path = "orders"
},
Then I iterate lambda function creation through this map using for_each as below.
resource "aws_lambda_function" "lambda_functions" {
for_each = var.lambdas
filename = "lambda_function_code.zip"
function_name = each.value.name
role = data.aws_iam_role.lambda_execution_role.arn
handler = "index.handler"
source_code_hash = filebase64sha256("lambda_function_code.zip")
runtime = "nodejs14.x"
}
After that I start to create API Gateway, resources and methods as below,
resource "aws_api_gateway_rest_api" "api_gateway" {
name = var.api-gateway-name
}
resource "aws_api_gateway_resource" "resources" {
for_each = var.lambdas
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
parent_id = aws_api_gateway_rest_api.api_gateway.root_resource_id
path_part = each.value.path
}
resource "aws_api_gateway_method" "methods" {
for_each = aws_api_gateway_resource.resources
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
resource_id = each.value.id
http_method = "POST"
authorization = "NONE"
api_key_required = false
}
Then I try to integrate above API Gateway method with relevant Lambda function by iterating above above methods. But here I have to input relevant lambda function invocation uri.
resource "aws_api_gateway_integration" "integration" {
for_each = aws_api_gateway_method.methods
rest_api_id = each.value.rest_api_id
resource_id = each.value.resource_id
http_method = each.value.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = ""
}
I am struggling to input this relevant lambda function uri to integrate with relevant method.
My question is, How do I get relevant lambda function uri to input here with this iteration? Or any solution to achieve this without code every lambdas, resources and methods.
The aws_lambda_function has invoke_arn which is:
ARN to be used for invoking Lambda Function from API Gateway - to be used in aws_api_gateway_integration's uri
So you have to use that in your aws_api_gateway_integration.
Related
I am working on a feature where we are uploading data to aws cloudsearch domain.
also to utilize this aws cloudsearch domain I need to create one api from aws cloudsearch domain.
I have gone through this blog which explains about how we can use aws cloudsearch with api : https://blog.devgenius.io/autocomplete-with-amazon-cloudsearch-8503b606c90d
The problem is I need to create APIgateway from terraform scripts and there is no particular documentation or reference available for me to look into how can we write terraform script to integrate APIgateway with AWS CLOUDSEARCH domain.
so far I have gone through terraform official documentation and have found below steps :
resource "aws_api_gateway_rest_api" "MyDemoAPI" {
name = "MyDemoAPI"
description = "This is my API for demonstration purposes"
}
resource "aws_api_gateway_resource" "MyDemoResource" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
parent_id = aws_api_gateway_rest_api.MyDemoAPI.root_resource_id
path_part = "mydemoresource"
}
resource "aws_api_gateway_method" "MyDemoMethod" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id`enter code here`
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = "GET"
authorization = "NONE"
}
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"
cache_key_parameters = ["method.request.path.param"]
cache_namespace = "foobar"
timeout_milliseconds = 29000
request_parameters = {
"integration.request.header.X-Authorization" = "'static'"
}
# Transforms the incoming XML request to JSON
request_templates = {
"application/xml" = <<EOF
{
"body" : $input.json('$')
}
EOF
}
}
but i am not sure how will it help me in my implementation.
I want to create an API Gateway that is connected to a kinesis stream:
resource "aws_api_gateway_integration" "kinesis_integration" {
rest_api_id = aws_api_gateway_rest_api.kinesis.id
resource_id = aws_api_gateway_resource.api_resource_kinesis.id
http_method = aws_api_gateway_method.post_kinesis.http_method
type = "AWS_PROXY"
uri = "arn:aws:apigateway:eu-central-1:kinesis:action/PutRecord"
integration_http_method = "POST"
depends_on = [
aws_api_gateway_resource.resource_kinesis
]
}
resource "aws_kinesis_firehose_delivery_stream" "kinesis-stream" {
name = "kinesis-stream"
destination = "extended_s3"
extended_s3_configuration {
role_arn = aws_iam_role.integration_role.arn
bucket_arn = aws_s3_bucket.mybucket.arn
processing_configuration {
enabled = "true"
processors {
type = "Lambda"
parameters {
parameter_name = "LambdaArn"
parameter_value = "${aws_lambda_function.mylambda.arn}:$LATEST"
}
}
}
}
}
Error creating API Gateway Integration: BadRequestException: AWS ARN for integration must contain path or action
│
│ with module.api.aws_api_gateway_integration.kinesis_integration,
│ on ../../modules/myapi.tf line 62, in resource "aws_api_gateway_integration" "kinesis_integration":
│ 62: resource "aws_api_gateway_integration" "kinesis_integration" {
Am I using the wrong syntax? Is it not supposed to be a string? I read in another SO answer that the format of the uri is supposed to be like this:
arn:aws:apigateway:{region}:{subdomain.service|service}:{path|action}/{service_api}
but it doesn't seem to work for me. I already tried both sols here but they give me the same error:
What should be service api for aws_api_gateway_integration with firehose in terraform
The links that you are trying to follow are for AWS integration, not AWS_PROXY. AWS_PROXY is only for lambda functions. I know that somewhere it says you can also use Firehose with it (I think some error messages), but its not really documented and advertised. It is either some internal AWS functionality, or something that hasn't been implemented yet.
I want to add a header (Content-Type) and a mapping template within the integration request of my AWS API Gateway. While following this tutorial, I could easily add those parameters via the console. https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-kinesis.html
However, I am unable to figure out the syntax to add them using Terraform. This is my integration request so far:
resource "aws_api_gateway_integration" "kinesis_integration" {
rest_api_id = aws_api_gateway_rest_api.shippeo_api_kinesis.id
resource_id = aws_api_gateway_resource.shippeo_api_resource_kinesis.id
http_method = aws_api_gateway_method.post_json_files_kinesis.http_method
credentials = aws_iam_role.shippeo_integration_role.arn
type = "AWS"
uri = "arn:aws:apigateway:eu-central-1:kinesis:action/PutRecord"
integration_http_method = "POST"
depends_on = [
aws_api_gateway_resource.shippeo_api_resource_kinesis
]
}
How can I specify the header (Content-Type)+Mapped From and the mapping templates as shown below using Terraform?
Mapping Template:
{
"StreamName": "$input.params('stream-name')",
"Data": "$util.base64Encode($input.json('$.Data'))",
"PartitionKey": "$input.path('$.PartitionKey')"
}
In the documentation, selection_pattern and response_templates is mentioned but I am not sure how to use it in my case.
I followed the instructions here for setting up a gateway and a lambda but it does not work. The symptoms appear to be the same as described here but the fixes suggested there did not work.
My infrastructure definition is as follows:
resource "aws_apigatewayv2_api" "lambda_api" {
name = "${upper(var.project)}-${upper(var.environment)}-${var.gateway_name}"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_stage" "lambda_default" {
name = "$default"
api_id = aws_apigatewayv2_api.lambda_api.id
auto_deploy = true
}
resource "aws_apigatewayv2_integration" "gateway_to_lambda" {
api_id = aws_apigatewayv2_api.lambda_api.id
integration_type = "AWS_PROXY"
connection_type = "INTERNET"
integration_method = "POST"
integration_uri = aws_lambda_function.executable.arn
payload_format_version = "2.0"
}
resource "aws_apigatewayv2_route" "route" {
api_id = aws_apigatewayv2_api.lambda_api.id
route_key = "GET /profile"
target = "integrations/${aws_apigatewayv2_integration.gateway_to_lambda.id}"
}
resource "aws_lambda_permission" "execution_lambda_from_gateway" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.executable.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.lambda_api.arn}/*/*"
}
On the gateway side it looks like things are created correctly: I have an integration that connects my path 'profile' to the lambda:
However, when I look on the lambda the trigger is missing:
When I try to hit the endpoint I get an "internal server error" message.
When I manually add the trigger in my lambda then it works but not under the 'profile' route key that I specified.
What am I missing here to correctly route my /profile in the API Gateway to my lambda?
Based on the comments. The solution was to modify the permissions (remove source_arn):
resource "aws_lambda_permission" "execution_lambda_from_gateway" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.executable.function_name
principal = "apigateway.amazonaws.com"
}
I have multiple Apigateway trigger a lambda. They can invoke lambda normally but when I want to see triggers of lambda after deployed by terraform or serverless framework, AWS often throws 429 error An error occurred while listing api-gateway relations: Too Many Requests. Can anyone shed any light please how can I fix it?
Sample
Here is my config:
data "aws_lambda_function" "lambda" {
function_name = var.function_name
}
locals {
resource_path = replace(var.resource_path, "/{.*}/", "*")
}
resource "aws_api_gateway_integration" "integration" {
rest_api_id = var.api_id
resource_id = var.resource_id
http_method = aws_api_gateway_method.method.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = data.aws_lambda_function.lambda.invoke_arn
}
# Create Lambda trigger to the method
resource "aws_lambda_permission" "allow_api" {
action = "lambda:InvokeFunction"
function_name = var.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${var.api_arn}/*/${var.http_method}${local.resource_path}"
}