Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDK based API Gateway Stage updates #6084

Merged
merged 5 commits into from May 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 8 additions & 15 deletions docs/providers/aws/events/apigateway.md
Expand Up @@ -48,10 +48,9 @@ layout: Doc
- [Resource Policy](#resource-policy)
- [Compression](#compression)
- [Binary Media Types](#binary-media-types)
- [Stage specific setups](#stage-specific-setups)
- [AWS X-Ray Tracing](#aws-x-ray-tracing)
- [Tags / Stack Tags](#tags--stack-tags)
- [Logs](#logs)
- [AWS X-Ray Tracing](#aws-x-ray-tracing)
- [Tags / Stack Tags](#tags--stack-tags)
- [Logs](#logs)

_Are you looking for tutorials on using API Gateway? Check out the following resources:_

Expand Down Expand Up @@ -1432,13 +1431,7 @@ provider:

In your Lambda function you need to ensure that the correct `content-type` header is set. Furthermore you might want to return the response body in base64 format.

## Stage specific setups

**IMPORTANT:** Due to CloudFormation limitations it's not possible to enable API Gateway stage settings on existing deployments. Please remove your old API Gateway and re-deploy with your new stage configuration. Once done, subsequent deployments should work without any issues.

Disabling settings might result in unexpected behavior. We recommend to remove and re-deploy your service without such stage settings.

### AWS X-Ray Tracing
## AWS X-Ray Tracing

API Gateway supports a form of out of the box distributed tracing via [AWS X-Ray](https://aws.amazon.com/xray/) though enabling [active tracing](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-xray.html). To enable this feature for your serverless application's API Gateway add the following to your `serverless.yml`

Expand All @@ -1451,7 +1444,7 @@ provider:
apiGateway: true
```

### Tags / Stack Tags
## Tags / Stack Tags

API Gateway stages will be tagged with the `tags` and `stackTags` values defined at the `provider` level:

Expand All @@ -1466,16 +1459,16 @@ provider:
tagKey: tagValue
```

### Logs
## Logs

Use the following configuration to enable API Gateway logs:

```yml
# serverless.yml
provider:
name: aws
apiGateway:
logs: true
logs:
restApi: true
```

The log streams will be generated in a dedicated log group which follows the naming schema `/aws/api-gateway/{service}-{stage}`.
5 changes: 3 additions & 2 deletions docs/providers/aws/guide/serverless.yml.md
Expand Up @@ -63,7 +63,6 @@ provider:
apiKeySourceType: HEADER # Source of API key for usage plan. HEADER or AUTHORIZER.
minimumCompressionSize: 1024 # Compress response when larger than specified size in bytes (must be between 0 and 10485760)
description: Some Description # Optional description for the API Gateway stage deployment
logs: true # Optional configuration which specifies if API Gateway logs are used
binaryMediaTypes: # Optional binary media types the API might return
- '*/*'
usagePlan: # Optional usage plan configuration
Expand Down Expand Up @@ -126,7 +125,9 @@ provider:
baz: qux
tracing:
apiGateway: true
lambda: true # optional, can be true (true equals 'Active'), 'Active' or 'PassThrough'
lambda: true # Optional, can be true (true equals 'Active'), 'Active' or 'PassThrough'
logs:
restApi: true # Optional configuration which specifies if API Gateway logs are used
pmuens marked this conversation as resolved.
Show resolved Hide resolved

package: # Optional deployment packaging configuration
include: # Specify the directories and files which should be included in the deployment package
Expand Down
21 changes: 19 additions & 2 deletions lib/plugins/aws/package/compile/events/apiGateway/index.js
@@ -1,5 +1,7 @@
'use strict';

/* eslint-disable global-require */

const BbPromise = require('bluebird');

const validate = require('./lib/validate');
Expand Down Expand Up @@ -68,10 +70,25 @@ class AwsCompileApigEvents {
.then(this.compileStage);
},

// TODO should be removed once AWS fixes the CloudFormation problems using a separate Stage
'after:deploy:deploy': () => {
const updateStage = require('./lib/hack/updateStage').updateStage;

this.validated = this.validate();

if (this.validated.events.length === 0) {
return BbPromise.resolve();
}

return updateStage.call(this);
},

// TODO should be removed once AWS fixes the removal via CloudFormation
'before:remove:remove': () => {
const validate = require('../../../../lib/validate').validate; // eslint-disable-line
const disassociateUsagePlan = require('./lib/disassociateUsagePlan').disassociateUsagePlan; // eslint-disable-line
// eslint-disable-next-line no-shadow
const validate = require('../../../../lib/validate').validate;
// eslint-disable-next-line max-len
const disassociateUsagePlan = require('./lib/hack/disassociateUsagePlan').disassociateUsagePlan;

return BbPromise.bind(this)
.then(validate)
Expand Down
43 changes: 42 additions & 1 deletion lib/plugins/aws/package/compile/events/apiGateway/index.test.js
Expand Up @@ -6,7 +6,8 @@ const AwsProvider = require('../../../../provider/awsProvider');
const AwsCompileApigEvents = require('./index');
const Serverless = require('../../../../../../Serverless');
const validate = require('../../../../lib/validate');
const disassociateUsagePlan = require('./lib/disassociateUsagePlan');
const updateStage = require('./lib/hack/updateStage');
const disassociateUsagePlan = require('./lib/hack/disassociateUsagePlan');

describe('AwsCompileApigEvents', () => {
let awsCompileApigEvents;
Expand Down Expand Up @@ -42,6 +43,7 @@ describe('AwsCompileApigEvents', () => {
let compileUsagePlanStub;
let compilePermissionsStub;
let compileStageStub;
let updateStageStub;
let disassociateUsagePlanStub;

beforeEach(() => {
Expand All @@ -59,6 +61,8 @@ describe('AwsCompileApigEvents', () => {
.stub(awsCompileApigEvents, 'compilePermissions').resolves();
compileStageStub = sinon
.stub(awsCompileApigEvents, 'compileStage').resolves();
updateStageStub = sinon
.stub(updateStage, 'updateStage').resolves();
disassociateUsagePlanStub = sinon
.stub(disassociateUsagePlan, 'disassociateUsagePlan').resolves();
});
Expand All @@ -71,6 +75,7 @@ describe('AwsCompileApigEvents', () => {
awsCompileApigEvents.compileUsagePlan.restore();
awsCompileApigEvents.compilePermissions.restore();
awsCompileApigEvents.compileStage.restore();
updateStage.updateStage.restore();
disassociateUsagePlan.disassociateUsagePlan.restore();
});

Expand Down Expand Up @@ -110,6 +115,42 @@ describe('AwsCompileApigEvents', () => {
});
});

describe('when running the "after:deploy:deploy" promise chain', () => {
afterEach(() => {
awsCompileApigEvents.validate.restore();
});

it('should run the promise chain in order', () => {
const validateStub = sinon.stub(awsCompileApigEvents, 'validate').returns({
events: [
{
functionName: 'first',
http: {
path: 'users',
method: 'POST',
},
},
],
});

awsCompileApigEvents.hooks['after:deploy:deploy']().then(() => {
expect(validateStub.calledOnce).to.equal(true);
expect(updateStageStub.calledAfter(validateStub)).to.equal(true);
});
});

it('should skip the updateStage step when no http events are found', () => {
const validateStub = sinon.stub(awsCompileApigEvents, 'validate').returns({
events: [],
});

awsCompileApigEvents.hooks['after:deploy:deploy']().then(() => {
expect(validateStub.calledOnce).to.equal(true);
expect(updateStageStub.calledOnce).to.equal(false);
});
});
});

it('should run "before:remove:remove" promise chain in order', () => {
const validateStub = sinon.stub(validate, 'validate').returns();

Expand Down
@@ -0,0 +1,5 @@
# Hack

This directory contains code which performs raw SDK calls rather than going through CloudFormation template compilations.

We're planning to port the logic of these code snippets to raw CloudFormation once AWS fixes the problems currently preventing us from solely relying on CloudFormation.
Expand Up @@ -2,8 +2,8 @@

const expect = require('chai').expect;
const sinon = require('sinon');
const Serverless = require('../../../../../../../Serverless');
const AwsProvider = require('../../../../../provider/awsProvider');
const Serverless = require('../../../../../../../../Serverless');
const AwsProvider = require('../../../../../../provider/awsProvider');
const disassociateUsagePlan = require('./disassociateUsagePlan');

describe('#disassociateUsagePlan()', () => {
Expand Down