Skip to content

Commit

Permalink
feat(codepipeline):CannedACL should be kebab-cased (aws#5977)
Browse files Browse the repository at this point in the history
fixes aws#5963

Also, added unit tests for S3DeployAction

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
netroy and mergify[bot] authored Jan 31, 2020
1 parent 4bdd084 commit a6206eb
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 4 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"**/jszip/**",
"@aws-cdk/assets/minimatch",
"@aws-cdk/assets/minimatch/**",
"@aws-cdk/aws-codepipeline-actions/case",
"@aws-cdk/aws-codepipeline-actions/case/**",
"@aws-cdk/aws-ecr-assets/minimatch",
"@aws-cdk/aws-ecr-assets/minimatch/**",
"@aws-cdk/cx-api/semver",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as s3 from '@aws-cdk/aws-s3';
import { Construct, Duration } from '@aws-cdk/core';
import { kebab as toKebabCase } from 'case';
import { Action } from '../action';
import { deployArtifactBounds } from '../common';

Expand Down Expand Up @@ -113,12 +114,13 @@ export class S3DeployAction extends Action {
// the Action Role also needs to read from the Pipeline's bucket
options.bucket.grantRead(options.role);

const acl = this.props.accessControl;
return {
configuration: {
BucketName: this.props.bucket.bucketName,
Extract: this.props.extract === false ? 'false' : 'true',
ObjectKey: this.props.objectKey,
CannedACL: this.props.accessControl,
CannedACL: acl ? toKebabCase(acl.toString()) : undefined,
CacheControl: this.props.cacheControl && this.props.cacheControl.map(ac => ac.value).join(', '),
},
};
Expand Down
8 changes: 6 additions & 2 deletions packages/@aws-cdk/aws-codepipeline-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@
"@aws-cdk/aws-s3": "1.22.0",
"@aws-cdk/aws-sns": "1.22.0",
"@aws-cdk/aws-sns-subscriptions": "1.22.0",
"@aws-cdk/core": "1.22.0"
"@aws-cdk/core": "1.22.0",
"case": "1.6.2"
},
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
Expand All @@ -111,6 +112,9 @@
"@aws-cdk/aws-sns-subscriptions": "1.22.0",
"@aws-cdk/core": "1.22.0"
},
"bundledDependencies": [
"case"
],
"engines": {
"node": ">= 10.3.0"
},
Expand Down Expand Up @@ -160,4 +164,4 @@
"props-default-doc:@aws-cdk/aws-codepipeline-actions.CodeDeployEcsDeployActionProps.containerImageInputs"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
"Ref": "DeployBucket67E2C076"
},
"Extract": "true",
"CannedACL": "PublicRead",
"CannedACL": "public-read",
"CacheControl": "public, max-age: 43200"
},
"InputArtifacts": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { expect, haveResourceLike } from "@aws-cdk/assert";
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as s3 from '@aws-cdk/aws-s3';
import { Duration, SecretValue, Stack } from "@aws-cdk/core";
import { Test } from 'nodeunit';
import * as cpactions from '../../lib';

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

export = {
'S3 Deploy Action': {
'by default extract artifacts'(test: Test) {
const stack = new Stack();
minimalPipeline(stack);

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{
"Name": "Source",
"Actions": [
{
"Name": "Source",
"ActionTypeId": {
"Category": "Source",
"Owner": "ThirdParty"
}
},
]
},
{
"Name": "Deploy",
"Actions": [
{
"ActionTypeId": {
"Category": "Deploy",
"Provider": "S3",
},
"Configuration": {
"Extract": "true"
},
"Name": "CopyFiles"
}
]
}
],
}));

test.done();
},

'grant the pipeline correct access to the target bucket'(test: Test) {
const stack = new Stack();
minimalPipeline(stack);

expect(stack).to(haveResourceLike('AWS::IAM::Policy', {
"PolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject*",
"s3:GetBucket*",
"s3:List*",
"s3:DeleteObject*",
"s3:PutObject*",
"s3:Abort*"
]
},
{},
{
"Effect": "Allow",
"Action": "sts:AssumeRole"
}
]
}
}));

test.done();
},

'kebab-case CannedACL value'(test: Test) {
const stack = new Stack();
minimalPipeline(stack, {
accessControl: s3.BucketAccessControl.PUBLIC_READ_WRITE
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{},
{
"Actions": [
{
"Configuration": {
"CannedACL": "public-read-write"
}
}
]
}
]
}));

test.done();
},

'allow customizing cache-control'(test: Test) {
const stack = new Stack();
minimalPipeline(stack, {
cacheControl: [
cpactions.CacheControl.setPublic(),
cpactions.CacheControl.maxAge(Duration.hours(12)),
]
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{},
{
"Actions": [
{
"Configuration": {
"CacheControl": "public, max-age: 43200"
}
}
]
}
]
}));

test.done();
},

'allow customizing objectKey (deployment path on S3)'(test: Test) {
const stack = new Stack();
minimalPipeline(stack, {
objectKey: "/a/b/c"
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
"Stages": [
{},
{
"Actions": [
{
"Configuration": {
"ObjectKey": "/a/b/c"
}
}
]
}
]
}));

test.done();
}
}
};

interface MinimalPipelineOptions {
readonly accessControl?: s3.BucketAccessControl;
readonly bucket?: s3.IBucket;
readonly cacheControl?: cpactions.CacheControl[];
readonly extract?: boolean;
readonly objectKey?: string;
}

function minimalPipeline(stack: Stack, options: MinimalPipelineOptions = {}): codepipeline.IStage {
const sourceOutput = new codepipeline.Artifact();
const sourceAction = new cpactions.GitHubSourceAction({
actionName: 'Source',
owner: 'aws',
repo: 'aws-cdk',
output: sourceOutput,
oauthToken: SecretValue.plainText('secret'),
});

const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline', {
stages: [
{
stageName: 'Source',
actions: [ sourceAction ],
}
]
});

const deploymentStage = pipeline.addStage({
stageName: 'Deploy',
actions: [
new cpactions.S3DeployAction({
accessControl: options.accessControl,
actionName: 'CopyFiles',
bucket: options.bucket || new s3.Bucket(stack, 'MyBucket'),
cacheControl: options.cacheControl,
extract: options.extract,
input: sourceOutput,
objectKey: options.objectKey,
}),
],
});

return deploymentStage;
}

0 comments on commit a6206eb

Please sign in to comment.