-
Notifications
You must be signed in to change notification settings - Fork 56
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
0 parents
commit 889de92
Showing
9 changed files
with
380 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,14 @@ | ||
# IntelliJ | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# OS X | ||
.DS_Store | ||
|
||
node_modules | ||
target | ||
|
||
xunit-*.xml | ||
npm-debug.log |
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,27 @@ | ||
# Introduction to CloudFormation for API Gateway | ||
|
||
Sample project that shows how [AWS CloudFormation](https://aws.amazon.com/cloudformation/) can be | ||
used to create an [AWS API Gateway](https://aws.amazon.com/api-gateway/) backed by [AWS Lambda](https://aws.amazon.com/lambda/). | ||
|
||
Please read the [blog post](https://www.jayway.com/2016/08/17/introduction-to-cloudformation-for-api-gateway/) for details. | ||
|
||
## CloudFormation Template | ||
|
||
[cloudformation.template](cloudformation.template) | ||
|
||
|
||
## Tools | ||
|
||
In order to execute the scripts, you need to install the following tools: | ||
|
||
- [AWS CLI](https://aws.amazon.com/cli/) (AWS Command Line Interface) | ||
- [npm](https://www.npmjs.com/) (JavaScript package manager) | ||
|
||
|
||
## Scripts | ||
|
||
| Script | Description | | ||
| ------------------------------------------------------------- | -------------------------- | | ||
| [create-stack.sh](scripts/create-stack.sh) | Creates the stack | | ||
| [integration-test.sh](scripts/integration-test.sh) | Executes integration tests | | ||
| [update-stack.sh](scripts/update-stack.sh) | Updates the stack | |
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,180 @@ | ||
{ | ||
"AWSTemplateFormatVersion": "2010-09-09", | ||
"Description": "AWS CloudFormation sample template that contains a single Lambda function behind an API Gateway", | ||
|
||
"Resources": { | ||
|
||
"GreetingLambda": { | ||
"Type": "AWS::Lambda::Function", | ||
"Properties": { | ||
"Code": { | ||
"ZipFile": { "Fn::Join": ["\n", [ | ||
"'use strict';", | ||
"", | ||
"// Greeter Lambda", | ||
"exports.handler = (event, context, callback) => {", | ||
" console.log('Event:', JSON.stringify(event));", | ||
" const name = event.name || 'World';", | ||
" const response = {greeting: `Hello, ${name}!`};", | ||
" callback(null, response);", | ||
"};" | ||
]]} | ||
}, | ||
"Description": "A greeting function", | ||
"FunctionName": "GreetingLambda", | ||
"Handler": "index.handler", | ||
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"]}, | ||
"Runtime": "nodejs4.3" | ||
} | ||
}, | ||
|
||
"LambdaExecutionRole": { | ||
"Type": "AWS::IAM::Role", | ||
"Properties": { | ||
"AssumeRolePolicyDocument": { | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Principal": { "Service": ["lambda.amazonaws.com"] }, | ||
"Action": ["sts:AssumeRole"] | ||
}] | ||
}, | ||
"ManagedPolicyArns": ["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"] | ||
} | ||
}, | ||
|
||
"GreetingApi": { | ||
"Type": "AWS::ApiGateway::RestApi", | ||
"Properties": { | ||
"Name": "Greeting API", | ||
"Description": "API used for Greeting requests", | ||
"FailOnWarnings": true | ||
} | ||
}, | ||
|
||
"LambdaPermission": { | ||
"Type": "AWS::Lambda::Permission", | ||
"Properties": { | ||
"Action": "lambda:invokeFunction", | ||
"FunctionName": {"Fn::GetAtt": ["GreetingLambda", "Arn"]}, | ||
"Principal": "apigateway.amazonaws.com", | ||
"SourceArn": {"Fn::Join": ["", ["arn:aws:execute-api:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":", {"Ref": "GreetingApi"}, "/*"]]} | ||
} | ||
}, | ||
|
||
"ApiGatewayCloudWatchLogsRole": { | ||
"Type": "AWS::IAM::Role", | ||
"Properties": { | ||
"AssumeRolePolicyDocument": { | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Principal": { "Service": ["apigateway.amazonaws.com"] }, | ||
"Action": ["sts:AssumeRole"] | ||
}] | ||
}, | ||
"Policies": [{ | ||
"PolicyName": "ApiGatewayLogsPolicy", | ||
"PolicyDocument": { | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"logs:CreateLogGroup", | ||
"logs:CreateLogStream", | ||
"logs:DescribeLogGroups", | ||
"logs:DescribeLogStreams", | ||
"logs:PutLogEvents", | ||
"logs:GetLogEvents", | ||
"logs:FilterLogEvents" | ||
], | ||
"Resource": "*" | ||
}] | ||
} | ||
}] | ||
} | ||
}, | ||
|
||
"ApiGatewayAccount": { | ||
"Type": "AWS::ApiGateway::Account", | ||
"Properties": { | ||
"CloudWatchRoleArn": {"Fn::GetAtt": ["ApiGatewayCloudWatchLogsRole", "Arn"] } | ||
} | ||
}, | ||
|
||
"GreetingApiStage": { | ||
"DependsOn": ["ApiGatewayAccount"], | ||
"Type": "AWS::ApiGateway::Stage", | ||
"Properties": { | ||
"DeploymentId": {"Ref": "ApiDeployment"}, | ||
"MethodSettings": [{ | ||
"DataTraceEnabled": true, | ||
"HttpMethod": "*", | ||
"LoggingLevel": "INFO", | ||
"ResourcePath": "/*" | ||
}], | ||
"RestApiId": {"Ref": "GreetingApi"}, | ||
"StageName": "LATEST" | ||
} | ||
}, | ||
|
||
"ApiDeployment": { | ||
"Type": "AWS::ApiGateway::Deployment", | ||
"DependsOn": ["GreetingRequest"], | ||
"Properties": { | ||
"RestApiId": {"Ref": "GreetingApi"}, | ||
"StageName": "DummyStage" | ||
} | ||
}, | ||
|
||
"GreetingResource": { | ||
"Type": "AWS::ApiGateway::Resource", | ||
"Properties": { | ||
"RestApiId": {"Ref": "GreetingApi"}, | ||
"ParentId": {"Fn::GetAtt": ["GreetingApi", "RootResourceId"]}, | ||
"PathPart": "greeting" | ||
} | ||
}, | ||
|
||
"GreetingRequest": { | ||
"DependsOn": "LambdaPermission", | ||
"Type": "AWS::ApiGateway::Method", | ||
"Properties": { | ||
"AuthorizationType": "NONE", | ||
"HttpMethod": "GET", | ||
"Integration": { | ||
"Type": "AWS", | ||
"IntegrationHttpMethod": "POST", | ||
"Uri": {"Fn::Join": ["", | ||
["arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["GreetingLambda", "Arn"]}, "/invocations"] | ||
]}, | ||
"IntegrationResponses": [{ | ||
"StatusCode": 200 | ||
}], | ||
"RequestTemplates": { | ||
"application/json": {"Fn::Join": ["", [ | ||
"{", | ||
" \"name\": \"$input.params('name')\"", | ||
"}" | ||
]]} | ||
} | ||
}, | ||
"RequestParameters": { | ||
"method.request.querystring.name": false | ||
}, | ||
"ResourceId": {"Ref": "GreetingResource"}, | ||
"RestApiId": {"Ref": "GreetingApi"}, | ||
"MethodResponses": [{ | ||
"StatusCode": 200 | ||
}] | ||
} | ||
} | ||
}, | ||
|
||
"Outputs": { | ||
"RootUrl": { | ||
"Description": "Root URL of the API gateway", | ||
"Value": {"Fn::Join": ["", ["https://", {"Ref": "GreetingApi"}, ".execute-api.", {"Ref": "AWS::Region"}, ".amazonaws.com"]]} | ||
} | ||
} | ||
} |
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,44 @@ | ||
'use strict'; | ||
|
||
const expect = require('chai').expect; | ||
const AWS = require('aws-sdk'); | ||
const AWS_REGION = process.env.AWS_DEFAULT_REGION || 'eu-west-1'; | ||
AWS.config.update({region: AWS_REGION}); | ||
const lambda = new AWS.Lambda({apiVersion: '2015-03-31'}); | ||
|
||
function callGreeterLambda(name) { | ||
const params = { | ||
FunctionName: 'GreetingLambda' | ||
}; | ||
if (name) { | ||
params.Payload = JSON.stringify({name: name}); | ||
} | ||
return lambda.invoke(params).promise(); | ||
} | ||
|
||
|
||
describe('Greeting Lambda integration tests', () => { | ||
|
||
it('Returns the name if it is provided', done => { | ||
callGreeterLambda('Superman') | ||
.then(data => { | ||
expect(data.StatusCode).to.eql(200); | ||
const payload = JSON.parse(data.Payload); | ||
expect(payload.greeting).to.eql('Hello, Superman!'); | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
|
||
it('Defaults to Hello World if no name is provided', done => { | ||
callGreeterLambda() | ||
.then(data => { | ||
expect(data.StatusCode).to.eql(200); | ||
const payload = JSON.parse(data.Payload); | ||
expect(payload.greeting).to.eql('Hello, World!'); | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
|
||
}); |
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,53 @@ | ||
'use strict'; | ||
|
||
const expect = require('chai').expect; | ||
const querystring = require('querystring'); | ||
const url = require('url'); | ||
const requestPromise = require('request-promise'); | ||
|
||
const APP_ID = // insert your API Gateway app id here | ||
const AWS_REGION = process.env.AWS_DEFAULT_REGION || 'eu-west-1'; | ||
const HOST = `${APP_ID}.execute-api.${AWS_REGION}.amazonaws.com`; | ||
const STAGE = 'LATEST'; | ||
const RESOURCE = 'greeting'; | ||
|
||
|
||
function callGreeterEndpoint(name) { | ||
const query = querystring.stringify({name: name}); | ||
const requestUrl = url.format({ | ||
protocol: 'https', | ||
host: HOST, | ||
pathname: `${STAGE}/${RESOURCE}`, | ||
search: query | ||
}); | ||
const params = { | ||
method: 'GET', | ||
uri: url.format(requestUrl), | ||
}; | ||
return requestPromise(params); | ||
} | ||
|
||
|
||
describe('Greeting REST integration tests', () => { | ||
|
||
it('Returns the name if it is provided', done => { | ||
callGreeterEndpoint('Superman') | ||
.then(json => { | ||
const response = JSON.parse(json); | ||
expect(response.greeting).to.eql('Hello, Superman!'); | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
|
||
it('Defaults to Hello World if no name is provided', done => { | ||
callGreeterEndpoint() | ||
.then(json => { | ||
const response = JSON.parse(json); | ||
expect(response.greeting).to.eql('Hello, World!'); | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
|
||
}); |
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,17 @@ | ||
{ | ||
"name": "api-gateway-lambda", | ||
"version": "1.0.0", | ||
"private": true, | ||
"scripts": { | ||
"itest": "mocha --recursive integration-test", | ||
"xunit-itest": "XUNIT_FILE=xunit-itest.xml mocha --recursive integration-test -R xunit-file" | ||
}, | ||
"devDependencies": { | ||
"aws-sdk": "2.4.6", | ||
"chai": "3.5.0", | ||
"mocha": "2.5.3", | ||
"request": "2.74.0", | ||
"request-promise": "4.1.1", | ||
"xunit-file": "1.0.0" | ||
} | ||
} |
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,17 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Creates the stack | ||
|
||
set -e | ||
|
||
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) | ||
template_file="$script_dir/../cloudformation.template" | ||
stack_name=greeting-stack | ||
|
||
if [ -z "$AWS_DEFAULT_REGION" ]; then | ||
aws_region="eu-west-1" | ||
else | ||
aws_region=$AWS_DEFAULT_REGION | ||
fi | ||
|
||
aws cloudformation create-stack --stack-name $stack_name --template-body fileb://"$template_file" --capabilities CAPABILITY_IAM --region $aws_region |
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,11 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Executes integration tests against version $LATEST | ||
|
||
set -e | ||
|
||
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) | ||
cd "$script_dir/.." | ||
|
||
npm install | ||
npm run xunit-itest |
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,17 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Creates the stack | ||
|
||
set -e | ||
|
||
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) | ||
template_file="$script_dir/../cloudformation.template" | ||
stack_name=greeting-stack | ||
|
||
if [ -z "$AWS_DEFAULT_REGION" ]; then | ||
aws_region="eu-west-1" | ||
else | ||
aws_region=$AWS_DEFAULT_REGION | ||
fi | ||
|
||
aws cloudformation update-stack --stack-name $stack_name --template-body fileb://"$template_file" --capabilities CAPABILITY_IAM --region $aws_region |