-
Notifications
You must be signed in to change notification settings - Fork 881
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
venv/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
name: aws-py-apigateway-lambda-serverless | ||
runtime: | ||
name: python | ||
options: | ||
virtualenv: venv | ||
description: A minimal AWS Python Pulumi program |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# [App Description] using [Service or Tool] | ||
|
||
<!-- Use Title Case for all Titles --> | ||
<!-- Most of the examples are transformed into tutorials on https://www.pulumi.com/docs/tutorials/ and are sorted by cloud and language. There is no need to include the cloud provider name or the language in the title. | ||
<!-- Our examples have a specific structure. Learn more at CONTRIBUTING.md --> | ||
|
||
Set up two lambda-backed API Gateways: an API Gateway V1 (REST) and an API Gateway V2 (HTTP). AWS provides some information on the differences between these two API Gateway types, here: (Announcing HTTP APIs for Amazon API Gateway)[https://aws.amazon.com/blogs/compute/announcing-http-apis-for-amazon-api-gateway/] & (API Gateway V2 FAQs)[https://aws.amazon.com/api-gateway/faqs/] | ||
|
||
# Lambda-backed API Gateway | ||
|
||
This example provides API endpoints which are executed by lambda using TypeScript and AWS. | ||
|
||
This sample uses the following AWS products: | ||
|
||
- [Amazon API Gateway](https://aws.amazon.com/api-gateway/) is used as an API proxy | ||
- [AWS Lambda](https://aws.amazon.com/lambda/) is used to process API events by executing typescript/javascript code | ||
|
||
## Prerequisites | ||
|
||
<!-- The Prerequisites section includes an ordered list of required installation and configuration steps before the reader can deploy the Pulumi example. --> | ||
|
||
1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) | ||
2. Create a new stack: | ||
|
||
```bash | ||
$ pulumi stack init aws-py-apigateway-lambda-serverless | ||
``` | ||
|
||
3. Set the AWS region: | ||
|
||
```bash | ||
$ pulumi config set aws:region us-east-2 | ||
``` | ||
|
||
## Deploy the App | ||
|
||
1. Run `pulumi up` to preview and deploy changes: | ||
|
||
2. To view the runtime logs of the Lambda function, use the `pulumi logs` command. To get a log stream, use `pulumi logs --follow`. | ||
|
||
## Clean Up | ||
|
||
1. Run `pulumi destroy` to tear down all resources. | ||
|
||
2. To delete the stack itself, run `pulumi stack rm`. Note that this command deletes all deployment history from the Pulumi Console. | ||
|
||
<!-- Example: | ||
1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) | ||
1. [Configure your AWS Credentials](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/) | ||
1. [Install Node.js](https://www.pulumi.com/docs/intro/languages/javascript/) | ||
--> | ||
|
||
## Summary | ||
|
||
In this tutorial, you built a lambda-backed API on AWS using API Gateway, lambda functions, and Pulumi. This serverless solution is highly scaleable, resilient, and stateless. | ||
|
||
<!-- Give a quick recap of what the readers have learned and optionally provide places for further exploration. --> | ||
|
||
## Next Steps | ||
|
||
- [Create a frontend to interact with this api](https://www.pulumi.com/docs/tutorials/aws/s3-website/) | ||
<!-- Optionally include an unordered list of relevant Pulumi tutorials. --> | ||
|
||
<!-- Example: | ||
- [Create a load-balanced, hosted NGINX container service](https://www.pulumi.com/docs/tutorials/aws/ecs-fargate/) | ||
- [Create an EC2-based WebServer and associated infrastructure](https://www.pulumi.com/docs/tutorials/aws/ec2-webserver/) | ||
--> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
"""An AWS Python Pulumi program""" | ||
|
||
import pulumi | ||
import pulumi_aws as aws | ||
import iam | ||
import json | ||
|
||
region = aws.config.region | ||
|
||
custom_stage_name = 'example' | ||
|
||
################## | ||
## Lambda Function | ||
################## | ||
|
||
# Create a Lambda function, using code from the `./app` folder. | ||
|
||
lambda_func = aws.lambda_.Function("mylambda", | ||
role=iam.lambda_role.arn, | ||
runtime="python3.7", | ||
handler="hello.handler", | ||
code=pulumi.AssetArchive({ | ||
'.': pulumi.FileArchive('./hello_lambda') | ||
}) | ||
) | ||
|
||
|
||
#################################################################### | ||
## | ||
## API Gateway REST API (API Gateway V1 / original) | ||
## /{proxy+} - passes all requests through to the lambda function | ||
## | ||
#################################################################### | ||
|
||
# Create a single Swagger spec route handler for a Lambda function. | ||
def swagger_route_handler(arn): | ||
return ({ | ||
"x-amazon-apigateway-any-method": { | ||
"x-amazon-apigateway-integration": { | ||
"uri": f'arn:aws:apigateway:{region}:lambda:path/2015-03-31/functions/{arn}/invocations', | ||
"passthroughBehavior": "when_no_match", | ||
"httpMethod": "POST", | ||
"type": "aws_proxy", | ||
}, | ||
}, | ||
}) | ||
|
||
# Create the API Gateway Rest API, using a swagger spec. | ||
rest_api = aws.apigateway.RestApi("api", | ||
body=lambda_func.arn.apply(lambda arn: json.dumps({ | ||
"swagger": "2.0", | ||
"info": {"title": "api", "version": "1.0"}, | ||
"paths": { | ||
"/{proxy+}": swagger_route_handler(arn), | ||
}, | ||
}))) | ||
|
||
# Create a deployment of the Rest API. | ||
deployment = aws.apigateway.Deployment("api-deployment", | ||
rest_api=rest_api.id, | ||
# Note: Set to empty to avoid creating an implicit stage, we'll create it | ||
# explicitly below instead. | ||
stage_name="", | ||
) | ||
|
||
# Create a stage, which is an addressable instance of the Rest API. Set it to point at the latest deployment. | ||
stage = aws.apigateway.Stage("api-stage", | ||
rest_api=rest_api.id, | ||
deployment=deployment.id, | ||
stage_name=custom_stage_name, | ||
) | ||
|
||
# Give permissions from API Gateway to invoke the Lambda | ||
invoke_permission = aws.lambda_.Permission("api-lambda-permission", | ||
action="lambda:invokeFunction", | ||
function=lambda_func.name, | ||
principal="apigateway.amazonaws.com", | ||
source_arn=deployment.execution_arn.apply(lambda arn: arn + "*/*"), | ||
) | ||
|
||
######################################################################### | ||
# Create an HTTP API and attach the lambda function to it | ||
######################################################################### | ||
|
||
http_endpoint = aws.apigatewayv2.Api("http-api-pulumi-example", | ||
protocol_type="HTTP" | ||
) | ||
|
||
# Note to self: example provided her ew as incorrect: https://www.pulumi.com/docs/reference/pkg/aws/apigatewayv2/integration/ | ||
http_lambda_backend = aws.apigatewayv2.Integration("example", | ||
api_id= http_endpoint.id, | ||
integration_type="AWS_PROXY", | ||
connection_type="INTERNET", | ||
description="Lambda example", | ||
integration_method="POST", | ||
integration_uri=lambda_func.arn, | ||
passthrough_behavior="WHEN_NO_MATCH" | ||
) | ||
|
||
url = http_lambda_backend.integration_uri.apply(lambda l: "" + l) | ||
|
||
http_route = aws.apigatewayv2.Route("example-route", | ||
api_id=http_endpoint.id, | ||
route_key="ANY /example-route/{proxy+}", | ||
target=http_lambda_backend.id.apply(lambda targetUrl: "integrations/" + targetUrl) | ||
) | ||
|
||
http_stage = aws.apigatewayv2.Stage("example-stage", | ||
api_id=http_endpoint.id, | ||
route_settings= [ | ||
{ | ||
"route_key": http_route.route_key.apply(lambda route_key: "" + route_key) | ||
} | ||
], | ||
auto_deploy=True | ||
) | ||
|
||
# http_deployment = aws.apigatewayv2.Deployment("example-deployment", | ||
# api_id=http_endpoint.id, | ||
# description="Example deployment" | ||
# ) | ||
|
||
# pulumi.export("http-endpoint", http_endpoint.api_endpoint) | ||
# Export the https endpoint of the running Rest API | ||
pulumi.export("apigateway-rest-endpoint", deployment.invoke_url.apply(lambda url: url + custom_stage_name)) | ||
# See "Outputs" for (Inputs and Outputs)[https://www.pulumi.com/docs/intro/concepts/inputs-outputs/] the usage of the pulumi.Output.all function to do string concatenation | ||
pulumi.export("apigatewayv2-http-endpoint", pulumi.Output.all(http_endpoint.api_endpoint, http_stage.name).apply(lambda values: values[0] + '/' + values[1])) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import json | ||
|
||
def handler(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps('Cheers from AWS Lambda!!') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Copyright 2016-2018, Pulumi Corporation. All rights reserved. | ||
|
||
from pulumi_aws import iam | ||
|
||
lambda_role = iam.Role('lambdaRole', | ||
assume_role_policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"Service": "lambda.amazonaws.com" | ||
}, | ||
"Effect": "Allow", | ||
"Sid": "" | ||
} | ||
] | ||
}""" | ||
) | ||
|
||
lambda_role_policy = iam.RolePolicy('lambdaRolePolicy', | ||
role=lambda_role.id, | ||
policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"logs:CreateLogGroup", | ||
"logs:CreateLogStream", | ||
"logs:PutLogEvents" | ||
], | ||
"Resource": "arn:aws:logs:*:*:*" | ||
}] | ||
}""" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pulumi>=2.0.0,<3.0.0 | ||
pulumi-aws>=3.2.0,<4.0.0 |