pulumi / pulumi-aws-apigateway

Apache License 2.0
13 stars 5 forks source link

How to use Lambda container images with the API Gateway? #76

Closed theogravity closed 1 year ago

theogravity commented 1 year ago

Example of how to do it in native AWS: https://aws.amazon.com/blogs/architecture/field-notes-three-steps-to-port-your-containerized-application-to-aws-lambda/

Pulumi article: https://www.pulumi.com/docs/clouds/aws/guides/api-gateway/#lambda-request-handling

I have a container-based lambda, and want to associate it to an API Gateway in AWS. The article here assumes a standalone (non-container)-based lambda. I'd like to create a REST-style API Gateway and assign these container images per route.

FunctionUrl() does generate a dedicated URL, but that's not what I want.

I'd like to use a single API Gateway vs an individual FunctionUrl() because it's easier to export and maintain a API Gateway resource vs multiple FunctionUrl() references.

kpitzen commented 1 year ago

Hi @theogravity - thank you for raising this question! I'm going to try to work up an example here, as I've recently spent some time using container-based lambdas, and am also curious how well they integrate with API Gateway. I'll set a reminder to look at this on Monday. Thanks!

theogravity commented 1 year ago

I figured it out after a day's worth of experimentation. Should also work with non-container image lambdas too:

import { apigatewayv2, lambda } from '@pulumi/aws';
import * as pulumi from '@pulumi/pulumi';

const lambda = newlambda.Function({
    name: ...
    packageType: 'Image',
    imageUri: ...
}) 

// Create the base API gateway
const gateway = new apigatewayv2.Api('api-gateway', {
  protocolType: 'HTTP',
});

const stage = new apigatewayv2.Stage('default-stage', { apiId: gateway.id, name: '$default', autoDeploy: true });

// Create the lambda-specific route and integration
const integration = new apigatewayv2.Integration('my-lambda-integration', {
  apiId: gateway.id,
  integrationType: 'AWS_PROXY',
  connectionType: 'INTERNET',
  integrationMethod: 'POST',
  payloadFormatVersion: '2.0',
  integrationUri: lambda.invokeArn,
  passthroughBehavior: 'WHEN_NO_MATCH',
});

const route = new apigatewayv2.Route('lambda-route', {
  apiId: gateway.id,
  routeKey: 'POST /my/route',
  target: pulumi.interpolate`integrations/${integration.id}`,
});

// give the api gateway permission to call the lambda
new lambda.Permission('api-gateway-perm', {
  action: 'lambda:InvokeFunction',
  function: lambda,
  principal: 'apigateway.amazonaws.com',
  sourceArn: pulumi.interpolate`${gateway.executionArn}/*/*/my/route`,
});

export const LAMBDA_API_URL = gateway.apiEndpoint;
kpitzen commented 1 year ago

That's great to hear, @theogravity ! Let us know if we can help any further.

theogravity commented 1 year ago

@kpitzen It'd be nice if it'd be apart of the official documentation as this will probably be difficult to search for from a search engine

If you do create docs from it, you're free to alter / modify it appropriately. No credit / attribution required.