Skip to content

Commit

Permalink
Add API Gateway-EventBridge examples (#1149)
Browse files Browse the repository at this point in the history
* Add the TypeScript example
* Add the Python example
* Add API Gateway v1 example
* Apply suggestions from code review

Co-authored-by: Laura Santamaria <[email protected]>
  • Loading branch information
cnunciato and nimbinatus authored Jan 12, 2022
1 parent ccfed98 commit 091390f
Show file tree
Hide file tree
Showing 18 changed files with 794 additions and 0 deletions.
2 changes: 2 additions & 0 deletions aws-py-apigatewayv2-eventbridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
venv/
11 changes: 11 additions & 0 deletions aws-py-apigatewayv2-eventbridge/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: aws-py-apigatewayv2-eventbridge
runtime:
name: python
options:
virtualenv: venv
description: An example that integrates API Gateway, EventBridge, and Lambda.
template:
config:
aws:region:
description: The AWS region to deploy into
default: us-east-2
70 changes: 70 additions & 0 deletions aws-py-apigatewayv2-eventbridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# API Gateway V2 to EventBridge

[![Deploy with Pulumi](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/examples/tree/master/aws-py-apigatewayv2-eventbridge)

This example creates an AWS API Gateway proxy integration with EventBridge and Lambda. It defines a single API Gateway endpoint that publishes events to an EventBridge event bus and an accompanying event rule that matches those events and invokes a Lambda function.

## Prerequisites

1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/).
1. [Install Python](https://www.pulumi.com/docs/intro/languages/python/).
1. Configure your [AWS credentials](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/).

### Deploying the App

1. Clone this repo, change to this directory, then create a new [stack](https://www.pulumi.com/docs/intro/concepts/stack/) for the project:

```bash
pulumi stack init
```

1. Specify an AWS region to deploy into:

```bash
pulumi config set aws:region us-west-2
```

1. Install Python dependencies and run Pulumi:

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pulumi up
```

1. In a few moments, the API Gateway instance service will be up and running and its public URL emitted as a Pulumi [stack output](https://www.pulumi.com/docs/intro/concepts/stack/#outputs).

```bash
...
Outputs:
url: "https://andchh8hg8.execute-api.us-west-2.amazonaws.com/dev"
```

1. Verify the deployment with `curl` and `pulumi logs`:

```bash
curl --data '{"some-key": "some-value"}' --header "Content-Type: application/json" "$(pulumi stack output url)/uploads"
{"Entries":[{"EventId":"cdc44763-6976-286c-9378-7cce674dff81"}],"FailedEntryCount":0}
```

```bash
pulumi logs --follow
Collecting logs for stack dev since 2022-01-06T16:18:48.000-08:00.
...
{
source: 'my-event-source',
detail: { 'some-key': 'some-value' }
}
```
1. When you're ready, destroy your stack and remove it:
```bash
pulumi destroy --yes
pulumi stack rm --yes
```
133 changes: 133 additions & 0 deletions aws-py-apigatewayv2-eventbridge/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Copyright 2016-2022, Pulumi Corporation. All rights reserved.

import json
import pulumi
import pulumi_aws as aws

# Create an HTTP API.
api = aws.apigatewayv2.Api("example",
protocol_type="HTTP"
)

# Create a stage and set it to deploy automatically.
stage = aws.apigatewayv2.Stage("stage",
api_id=api.id,
name=pulumi.get_stack(),
auto_deploy=True
)

# Create an event bus.
bus = aws.cloudwatch.EventBus("bus")

# Create an event rule to watch for events.
rule = aws.cloudwatch.EventRule("rule",
event_bus_name=bus.name,
event_pattern=json.dumps({"source": ["my-event-source"]})
)

# Define a policy granting API Gateway permission to publish to EventBridge.
api_gateway_role = aws.iam.Role("api-gateway-role",
assume_role_policy=json.dumps({
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com",
},
},
],
}),
managed_policy_arns=[
"arn:aws:iam::aws:policy/AmazonEventBridgeFullAccess",
],
)

# Create an API Gateway integration to forward requests to EventBridge.
integration = aws.apigatewayv2.Integration("integration",
api_id=api.id,

# The integration type and subtype.
integration_type="AWS_PROXY",
integration_subtype="EventBridge-PutEvents",
credentials_arn=api_gateway_role.arn,

# The body of the request to be sent to EventBridge. Note the
# event source matches pattern defined on the EventRule, and the
# Detail expression, which just forwards the body of the original
# API Gateway request (i.e., the uploaded document).
request_parameters={
"EventBusName": bus.name.apply(lambda name: name),
"Source": "my-event-source",
"DetailType": "my-detail-type",
"Detail": "$request.body",
},
)

# Finally, define the route.
route = aws.apigatewayv2.Route("route",
api_id=api.id,
route_key="POST /uploads",
target=integration.id.apply(lambda id: f"integrations/{id}"),
)

# Define a role and policy allowing Lambda functions to log to CloudWatch.
lambda_role = aws.iam.Role("lambda-role",
assume_role_policy=json.dumps({
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow"
}
]
})
)
lambda_role_policy = aws.iam.RolePolicy("lambda-role-policy",
role=lambda_role.id,
policy=json.dumps({
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}]
})
)

# Create a Lambda function handler.
lambda_function = aws.lambda_.Function("lambda",
role=lambda_role.arn,
runtime="python3.7",
handler="handlers.capture_order",
code=pulumi.AssetArchive({
".": pulumi.FileArchive('./api')
})
)

# Create an EventBridge target associating the event rule with the function.
lambda_target = aws.cloudwatch.EventTarget("lambda-target",
arn=lambda_function.arn,
rule=rule.name,
event_bus_name=bus.name,
)

# Give EventBridge permission to invoke the function.
lambda_permission = aws.lambda_.Permission("lambda-permission",
action="lambda:InvokeFunction",
principal="events.amazonaws.com",
function=lambda_function.arn,
source_arn=rule.arn,
)

# Export the API Gateway URL to give us something to POST to.
pulumi.export("url", pulumi.Output.concat(api.api_endpoint, "/", stage.name))

9 changes: 9 additions & 0 deletions aws-py-apigatewayv2-eventbridge/api/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright 2016-2022, Pulumi Corporation. All rights reserved.

import json

def capture_order(event, context):
# For now, just log the event, including the uploaded document.
# That'll be enough to verify everything's working.
print(json.dumps({"source": event["source"], "detail": event["detail"]}))

2 changes: 2 additions & 0 deletions aws-py-apigatewayv2-eventbridge/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pulumi>=3.0.0,<4.0.0
pulumi-aws>=4.0.0,<5.0.0
2 changes: 2 additions & 0 deletions aws-ts-apigateway-eventbridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
3 changes: 3 additions & 0 deletions aws-ts-apigateway-eventbridge/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: aws-ts-apigateway-eventbridge
runtime: nodejs
description: A minimal AWS TypeScript Pulumi program
81 changes: 81 additions & 0 deletions aws-ts-apigateway-eventbridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# API Gateway V1 to EventBridge

[![Deploy with Pulumi](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/examples/tree/master/aws-ts-apigateway-eventbridge)

This example demonstrates an API Gateway V1 integration with EventBridge and Lambda that also validates request bodies (using an API Gateway model) and returns a custom HTTP response.

## Prerequisites

1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/).
1. [Install Node.js](https://www.pulumi.com/docs/intro/languages/javascript/).
1. Configure your [AWS credentials](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/).

### Deploying the App

1. Clone this repo, change to this directory, then create a new [stack](https://www.pulumi.com/docs/intro/concepts/stack/) for the project:

```bash
pulumi stack init
```

1. Specify an AWS region to deploy into:

```bash
pulumi config set aws:region us-west-2
```

1. Install Node dependencies and run Pulumi:

```bash
npm install
pulumi up
```

1. In a few moments, the API Gateway instance service will be up and running and its public URL emitted as a Pulumi [stack output](https://www.pulumi.com/docs/intro/concepts/stack/#outputs).

```bash
...
Outputs:
url: "https://andchh8hg8.execute-api.us-west-2.amazonaws.com/dev"
```

1. Verify the deployment with `curl`:

With invalid POST data:

```bash
curl --data '{"some-invalid-property-name": "Chris"}' --header "Content-Type: application/json" "$(pulumi stack output url)/uploads"
HTTP/2 400
{"message": "Invalid request body"}
```

With valid POST data:

```bash
curl --data '{"name": "Chris"}' --header "Content-Type: application/json" "$(pulumi stack output url)/uploads"
HTTP/2 201
{"accepted":true}
```

1. Verify the Lambda was invoked with `pulumi logs`:

```bash
pulumi logs --follow
Collecting logs for stack dev since 2022-01-06T16:18:48.000-08:00.
...
{
source: 'my-event-source',
detail: { 'name': 'Chris' }
}
```
1. When you're ready, destroy your stack and remove it:
```bash
pulumi destroy --yes
pulumi stack rm --yes
```
Loading

0 comments on commit 091390f

Please sign in to comment.