Skip to content

Commit

Permalink
fix(codepipeline-actions): correctly serialize the userParameters pas…
Browse files Browse the repository at this point in the history
…sed to the Lambda invoke Action. (#2537)

BREAKING CHANGE: removed the `addPutJobResultPolicy` property when creating LambdaInvokeAction.
  • Loading branch information
skinny85 authored May 30, 2019
1 parent 0f553ee commit ceaf54a
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export interface LambdaInvokeActionProps extends codepipeline.CommonActionProps
*/
readonly inputs?: codepipeline.Artifact[];

// tslint:enable:max-line-length

/**
* The optional names of the output Artifacts of the Action.
* A Lambda Action can have up to 5 outputs.
Expand All @@ -34,30 +32,14 @@ export interface LambdaInvokeActionProps extends codepipeline.CommonActionProps
readonly outputs?: codepipeline.Artifact[];

/**
* String to be used in the event data parameter passed to the Lambda
* function
*
* See an example JSON event in the CodePipeline documentation.
* A set of key-value pairs that will be accessible to the invoked Lambda
* inside the event that the Pipeline will call it with.
*
* https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html#actions-invoke-lambda-function-json-event-example
* @see https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html#actions-invoke-lambda-function-json-event-example
*/
readonly userParameters?: any;
readonly userParameters?: { [key: string]: any };

/**
* Adds the "codepipeline:PutJobSuccessResult" and
* "codepipeline:PutJobFailureResult" for '*' resource to the Lambda
* execution role policy.
*
* NOTE: the reason we can't add the specific pipeline ARN as a resource is
* to avoid a cyclic dependency between the pipeline and the Lambda function
* (the pipeline references) the Lambda and the Lambda needs permissions on
* the pipeline.
*
* @see https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html#actions-invoke-lambda-function-create-function
*
* @default true
*/
readonly addPutJobResultPolicy?: boolean;
// tslint:enable:max-line-length

/**
* The lambda function to invoke.
Expand Down Expand Up @@ -86,8 +68,8 @@ export class LambdaInvokeAction extends codepipeline.Action {
},
configuration: {
FunctionName: props.lambda.functionName,
UserParameters: props.userParameters
}
UserParameters: props.lambda.node.stringifyJson(props.userParameters),
},
});

this.props = props;
Expand All @@ -104,13 +86,12 @@ export class LambdaInvokeAction extends codepipeline.Action {
.addAction('lambda:InvokeFunction')
.addResource(this.props.lambda.functionArn));

// allow lambda to put job results for this pipeline.
const addToPolicy = this.props.addPutJobResultPolicy !== undefined ? this.props.addPutJobResultPolicy : true;
if (addToPolicy) {
this.props.lambda.addToRolePolicy(new iam.PolicyStatement()
.addAllResources() // to avoid cycles (see docs)
.addAction('codepipeline:PutJobSuccessResult')
.addAction('codepipeline:PutJobFailureResult'));
}
// allow lambda to put job results for this pipeline
// CodePipeline requires this to be granted to '*'
// (the Pipeline ARN will not be enough)
this.props.lambda.addToRolePolicy(new iam.PolicyStatement()
.addAllResources()
.addAction('codepipeline:PutJobSuccessResult')
.addAction('codepipeline:PutJobFailureResult'));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { expect, haveResourceLike } from "@aws-cdk/assert";
import codepipeline = require('@aws-cdk/aws-codepipeline');
import lambda = require('@aws-cdk/aws-lambda');
import { Aws, SecretValue, Stack, Token } from "@aws-cdk/cdk";
import { Test } from 'nodeunit';
import cpactions = require('../../lib');

// tslint:disable:object-literal-key-quotes

export = {
'Lambda invoke Action': {
'properly serializes the object passed in userParameters'(test: Test) {
const stack = stackIncludingLambdaInvokeCodePipeline({
key: 1234,
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
'Stages': [
{},
{
'Actions': [
{
'Configuration': {
'UserParameters': '{"key":1234}',
},
},
],
},
],
}));

test.done();
},

'properly resolves any Tokens passed in userParameters'(test: Test) {
const stack = stackIncludingLambdaInvokeCodePipeline({
key: new Token(() => Aws.region),
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
'Stages': [
{},
{
'Actions': [
{
'Configuration': {
'UserParameters': {
'Fn::Join': [
'',
[
'{"key":"',
{
'Ref': 'AWS::Region',
},
'"}',
],
],
},
},
},
],
},
],
}));

test.done();
},

'properly resolves any stringified Tokens passed in userParameters'(test: Test) {
const stack = stackIncludingLambdaInvokeCodePipeline({
key: new Token(() => null).toString(),
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
'Stages': [
{},
{
'Actions': [
{
'Configuration': {
'UserParameters': '{"key":null}',
},
},
],
},
],
}));

test.done();
},
},
};

function stackIncludingLambdaInvokeCodePipeline(userParams: { [key: string]: any }) {
const stack = new Stack();

new codepipeline.Pipeline(stack, 'Pipeline', {
stages: [
{
name: 'Source',
actions: [
new cpactions.GitHubSourceAction({
actionName: 'GitHub',
output: new codepipeline.Artifact(),
oauthToken: SecretValue.plainText('secret'),
owner: 'awslabs',
repo: 'aws-cdk',
}),
],
},
{
name: 'Invoke',
actions: [
new cpactions.LambdaInvokeAction({
actionName: 'Lambda',
lambda: new lambda.Function(stack, 'Lambda', {
code: lambda.Code.cfnParameters(),
handler: 'index.handler',
runtime: lambda.Runtime.NodeJS810,
}),
userParameters: userParams,
}),
],
},
],
});

return stack;
}
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ export = {
const lambdaAction = new cpactions.LambdaInvokeAction({
actionName: 'InvokeAction',
lambda: lambdaFun,
userParameters: 'foo-bar/42',
inputs: [
source2Output,
source1Output,
Expand Down Expand Up @@ -510,7 +509,6 @@ export = {
"FunctionName": {
"Ref": "Function76856677"
},
"UserParameters": "foo-bar/42"
},
"InputArtifacts": [
{ "Name": "sourceArtifact2" },
Expand Down

0 comments on commit ceaf54a

Please sign in to comment.