Skip to content

Commit

Permalink
Merge pull request #33 from HyperBrain/support-cw-events
Browse files Browse the repository at this point in the history
Support CW events.
  • Loading branch information
HyperBrain committed May 9, 2017
2 parents 47c8106 + 94c83f7 commit 1f2b387
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ hook into the deployment process.
Additionally the new `alias` command is added to Serverless which offers some
functionality for aliases.

## Interoperability

Care has to be taken when using other plugins that modify the CF output too.
I will add configuration instructions in this section for these plugin combinations.

## Deploy the default alias

The default alias (for the stage) is deployed just by doing a standard stage
Expand Down Expand Up @@ -226,6 +221,19 @@ the alias stack has been removed.
The alias plugin is compatible with all standard Serverless commands and switches.
For example, you can use `--noDeploy` and the plugin will behave accordingly.

## Interoperability

Care has to be taken when using other plugins that modify the CF output too.
I will add configuration instructions in this section for these plugin combinations.

### [serverless-plugin-warmup](https://github.com/FidelLimited/serverless-plugin-warmup)

The warmup plugin will keep your Lambdas warm and reduce the cold start time
effectively. When using the plugin, it must be listed **before** the alias plugin
in the plugin list of _serverless.yml_. The warmup lambda created by the plugin
will be aliased too, so that the warmup plugin can be configured differently
per deployed alias.

## Test it

In case you wanna test how it behaves, I provided a predefined test service in
Expand Down Expand Up @@ -307,6 +315,8 @@ and _serverless.service.provider.deployedAliasTemplates[]_.

* 0.5.0-alpha1 Fixes a bug with deploying event sources introduced with 0.4.0
Use new event model introduced in SLS 1.12. Needs SLS 1.12 or greater from now on.
Add support for CW events.
Set SERVERLESS_ALIAS environment variable on deployed functions.
* 0.4.0-alpha1 APIG support fixed. Support external IAM roles. BREAKING.
* 0.3.4-alpha1 Bugfixes. IAM policy consolitaion. Show master alias information.
* 0.3.3-alpha1 Bugfixes. Allow manual resource overrides. Allow methods attached to APIG root resource.
Expand Down
56 changes: 56 additions & 0 deletions lib/aliasRestructureStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ module.exports = {
}
};

// Set SERVERLESS_ALIAS environment variable
_.forOwn(stageStack.Resources, resource => {
if (resource.Type === 'AWS::Lambda::Function') {
_.set(resource, 'Properties.Environment.Variables.SERVERLESS_ALIAS', this._alias);
}
});

const versions = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Version' ]));
if (!_.isEmpty(versions)) {
Expand Down Expand Up @@ -313,6 +319,55 @@ module.exports = {
return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
},

aliasHandleCWEvents(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {

const stageStack = this._serverless.service.provider.compiledCloudFormationTemplate;
const aliasStack = this._serverless.service.provider.compiledCloudFormationAliasTemplate;

const cwEvents = _.assign({}, _.pickBy(_.get(stageStack, 'Resources', {}), [ 'Type', 'AWS::Events::Rule' ]));
const cwEventLambdaPermissions =
_.assign({},
_.pickBy(_.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Permission' ]),
['Properties.Principal', 'events.amazonaws.com']));

_.forOwn(cwEvents, (cwEvent, name) => {
// Reference alias as FunctionName
const targetRefs = utils.findAllReferences(_.get(cwEvent, 'Properties.Targets'));
cwEvent.DependsOn = cwEvent.DependsOn || [];
_.forEach(targetRefs, ref => {
const functionName = _.replace(ref.ref, /LambdaFunction$/, '');
_.set(cwEvent.Properties.Targets, ref.path, { Ref: `${functionName}Alias` });
cwEvent.DependsOn.push(`${functionName}Alias`);
});

// Remove mapping from stage stack
delete stageStack.Resources[name];
});

// Move event subscriptions to alias stack
_.defaults(aliasStack.Resources, cwEvents);

// Adjust permission to reference the function aliases
_.forOwn(cwEventLambdaPermissions, (permission, name) => {
const targetFunctionRef = utils.findAllReferences(_.get(permission, 'Properties.FunctionName'));
const functionName = _.replace(targetFunctionRef[0].ref, /LambdaFunction$/, '');

// Adjust references and alias permissions
permission.Properties.FunctionName = { Ref: `${functionName}Alias` };

// Add dependency on function alias
permission.DependsOn = [ `${functionName}Alias` ];

delete stageStack.Resources[name];
});

// Add all alias stack owned resources
_.defaults(aliasStack.Resources, cwEventLambdaPermissions);

// Forward inputs to the promise chain
return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
},

aliasFinalize(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
const aliasStack = this._serverless.service.provider.compiledCloudFormationAliasTemplate;

Expand All @@ -336,6 +391,7 @@ module.exports = {
.spread(this.aliasHandleFunctions)
.spread(this.aliasHandleApiGateway)
.spread(this.aliasHandleEvents)
.spread(this.aliasHandleCWEvents)
.spread(this.aliasFinalize)
.then(() => BbPromise.resolve());
}
Expand Down
6 changes: 5 additions & 1 deletion lib/stackops/apiGateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,11 @@ module.exports = function(currentTemplate, aliasStackTemplates, currentAliasStac
}

// Fetch lambda permissions, methods and resources. These have to be updated later to allow the aliased functions.
const apiLambdaPermissions = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Permission' ]));
const apiLambdaPermissions =
_.assign({},
_.pickBy(_.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Permission' ]),
['Properties.Principal', 'apigateway.amazonaws.com']));

const apiMethods = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Method' ]));
//const apiResources = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Resource' ]));
const aliases = _.assign({}, _.pickBy(aliasStack.Resources, [ 'Type', 'AWS::Lambda::Alias' ]));
Expand Down

0 comments on commit 1f2b387

Please sign in to comment.