Skip to content

Commit

Permalink
feat(aws-codepipeline-actions): Add CAPABILITY_AUTO_EXPAND (aws#2851)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the capabilities property is now an array to support multiple capabilities.

Adds CAPABILITY_AUTO_EXPAND and support to define a list of capabilities for the CodePipeline action.
  • Loading branch information
ScOut3R committed Jun 13, 2019
1 parent f680247 commit 7479b26
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,13 @@ export enum CloudFormationCapabilities {
* @link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html#using-iam-capabilities
*/
NamedIAM = 'CAPABILITY_NAMED_IAM',

/**
* Capability to run CloudFormation macros
*
* Pass this capability if your template includes macros, for example AWS::Include or AWS::Serverless.
*
* @link https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html
*/
AutoExpand = 'CAPABILITY_AUTO_EXPAND'
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export interface CloudFormationDeployActionProps extends CloudFormationActionPro
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html#using-iam-capabilities
* @default None, unless `adminPermissions` is true
*/
readonly capabilities?: cloudformation.CloudFormationCapabilities;
readonly capabilities?: cloudformation.CloudFormationCapabilities[];

/**
* Whether to grant full permissions to CloudFormation while deploying this template.
Expand Down Expand Up @@ -221,12 +221,12 @@ export abstract class CloudFormationDeployAction extends CloudFormationAction {

constructor(props: CloudFormationDeployActionProps, configuration: any) {
const capabilities = props.adminPermissions && props.capabilities === undefined
? cloudformation.CloudFormationCapabilities.NamedIAM
? [cloudformation.CloudFormationCapabilities.NamedIAM]
: props.capabilities;
super(props, {
...configuration,
// None evaluates to empty string which is falsey and results in undefined
Capabilities: (capabilities && capabilities.toString()) || undefined,
Capabilities: parseCapabilities(capabilities),
RoleArn: cdk.Lazy.stringValue({ produce: () => this.deploymentRole.roleArn }),
ParameterOverrides: cdk.Lazy.stringValue({ produce: () => Stack.of(this.scope).toJsonString(props.parameterOverrides) }),
TemplateConfiguration: props.templateConfiguration ? props.templateConfiguration.location : undefined,
Expand Down Expand Up @@ -540,3 +540,13 @@ interface StatementTemplate {
}

type StatementCondition = { [op: string]: { [attribute: string]: string } };

function parseCapabilities(capabilities: any): any {
if (capabilities === undefined) {
return undefined;
} else if (capabilities.length === 1) {
return capabilities.toString();
} else if (capabilities.length > 1) {
return capabilities.join(',');
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert';
import { CloudFormationCapabilities } from '@aws-cdk/aws-cloudformation';
import { CodePipelineBuildArtifacts, CodePipelineSource, Project } from '@aws-cdk/aws-codebuild';
import { Repository } from '@aws-cdk/aws-codecommit';
import codepipeline = require('@aws-cdk/aws-codepipeline');
Expand Down Expand Up @@ -415,7 +416,94 @@ export = {
}));

test.done();
}
},

'Single capability is passed to template'(test: Test) {
// GIVEN
const stack = new TestFixture();

// WHEN
stack.deployStage.addAction(new cpactions.CloudFormationCreateUpdateStackAction({
actionName: 'CreateUpdate',
stackName: 'MyStack',
templatePath: stack.sourceOutput.atPath('template.yaml'),
adminPermissions: false,
capabilities: [
CloudFormationCapabilities.NamedIAM
]
}));

const roleId = "PipelineDeployCreateUpdateRole515CB7D4";

// THEN: Action in Pipeline has named IAM capabilities
expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{ "Name": "Source" /* don't care about the rest */ },
{
"Name": "Deploy",
"Actions": [
{
"Configuration": {
"Capabilities": "CAPABILITY_NAMED_IAM",
"RoleArn": { "Fn::GetAtt": [ roleId, "Arn" ] },
"ActionMode": "CREATE_UPDATE",
"StackName": "MyStack",
"TemplatePath": "SourceArtifact::template.yaml"
},
"InputArtifacts": [{"Name": "SourceArtifact"}],
"Name": "CreateUpdate",
},
],
}
]
}));

test.done();
},

'Multiple capabilities are passed to template'(test: Test) {
// GIVEN
const stack = new TestFixture();

// WHEN
stack.deployStage.addAction(new cpactions.CloudFormationCreateUpdateStackAction({
actionName: 'CreateUpdate',
stackName: 'MyStack',
templatePath: stack.sourceOutput.atPath('template.yaml'),
adminPermissions: false,
capabilities: [
CloudFormationCapabilities.NamedIAM,
CloudFormationCapabilities.AutoExpand
]
}));

const roleId = "PipelineDeployCreateUpdateRole515CB7D4";

// THEN: Action in Pipeline has named IAM and AUTOEXPAND capabilities
expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{ "Name": "Source" /* don't care about the rest */ },
{
"Name": "Deploy",
"Actions": [
{
"Configuration": {
"Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND",
"RoleArn": { "Fn::GetAtt": [ roleId, "Arn" ] },
"ActionMode": "CREATE_UPDATE",
"StackName": "MyStack",
"TemplatePath": "SourceArtifact::template.yaml"
},
"InputArtifacts": [{"Name": "SourceArtifact"}],
"Name": "CreateUpdate",
},
],
}
]
}));

test.done();
},
};

/**
Expand Down

0 comments on commit 7479b26

Please sign in to comment.