-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
deploy-action.ts
156 lines (139 loc) · 5.92 KB
/
deploy-action.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { kebab as toKebabCase } from 'case';
import { Construct } from 'constructs';
import * as codepipeline from '../../../aws-codepipeline';
import * as kms from '../../../aws-kms';
import * as s3 from '../../../aws-s3';
import { Duration } from '../../../core';
import { Action } from '../action';
import { deployArtifactBounds } from '../common';
// Class copied verbatim from the aws-s3-deployment module.
// Yes, it sucks that we didn't abstract this properly in a common class,
// but having 2 different CacheControl classes that behave differently would be worse I think.
// Something to do when CDK 2.0.0 comes out.
/**
* Used for HTTP cache-control header, which influences downstream caches.
* Use the provided static factory methods to construct instances of this class.
* Used in the `S3DeployActionProps.cacheControl` property.
*
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
*/
export class CacheControl {
/** The 'must-revalidate' cache control directive. */
public static mustRevalidate() { return new CacheControl('must-revalidate'); }
/** The 'no-cache' cache control directive. */
public static noCache() { return new CacheControl('no-cache'); }
/** The 'no-transform' cache control directive. */
public static noTransform() { return new CacheControl('no-transform'); }
/** The 'no-store' cache control directive. */
public static noStore() { return new CacheControl('no-store'); }
/** The 'must-understand' cache control directive. */
public static mustUnderstand() { return new CacheControl('must-understand'); }
/** The 'public' cache control directive. */
public static setPublic() { return new CacheControl('public'); }
/** The 'private' cache control directive. */
public static setPrivate() { return new CacheControl('private'); }
/** The 'immutable' cache control directive. */
public static immutable() { return new CacheControl('immutable'); }
/** The 'proxy-revalidate' cache control directive. */
public static proxyRevalidate() { return new CacheControl('proxy-revalidate'); }
/** The 'max-age' cache control directive. */
public static maxAge(t: Duration) { return new CacheControl(`max-age=${t.toSeconds()}`); }
/** The 's-max-age' cache control directive. */
public static sMaxAge(t: Duration) { return new CacheControl(`s-maxage=${t.toSeconds()}`); }
/** The 'stale-while-revalidate' cache control directive. */
public static staleWhileRevalidate(t: Duration) { return new CacheControl(`stale-while-revalidate=${t.toSeconds()}`); }
/** The 'stale-if-error' cache control directive. */
public static staleIfError(t: Duration) { return new CacheControl(`stale-if-error=${t.toSeconds()}`); }
/**
* Allows you to create an arbitrary cache control directive,
* in case our support is missing a method for a particular directive.
*/
public static fromString(s: string) { return new CacheControl(s); }
/** @param value the actual text value of the created directive */
private constructor(public value: string) {}
}
/**
* Construction properties of the `S3DeployAction S3 deploy Action`.
*/
export interface S3DeployActionProps extends codepipeline.CommonAwsActionProps {
/**
* Should the deploy action extract the artifact before deploying to Amazon S3.
*
* @default true
*/
readonly extract?: boolean;
/**
* The key of the target object. This is required if extract is false.
*/
readonly objectKey?: string;
/**
* The input Artifact to deploy to Amazon S3.
*/
readonly input: codepipeline.Artifact;
/**
* The Amazon S3 bucket that is the deploy target.
*/
readonly bucket: s3.IBucket;
/**
* The specified canned ACL to objects deployed to Amazon S3.
* This overwrites any existing ACL that was applied to the object.
*
* @default - the original object ACL
*/
readonly accessControl?: s3.BucketAccessControl;
/**
* The caching behavior for requests/responses for objects in the bucket.
* The final cache control property will be the result of joining all of the provided array elements with a comma
* (plus a space after the comma).
*
* @default - none, decided by the HTTP client
*/
readonly cacheControl?: CacheControl[];
/**
* The AWS KMS encryption key for the host bucket.
* The encryptionKey parameter encrypts uploaded artifacts with the provided AWS KMS key.
* @default - none
*/
readonly encryptionKey?: kms.IKey;
}
/**
* Deploys the sourceArtifact to Amazon S3.
*/
export class S3DeployAction extends Action {
private readonly props: S3DeployActionProps;
constructor(props: S3DeployActionProps) {
super({
...props,
resource: props.bucket,
category: codepipeline.ActionCategory.DEPLOY,
provider: 'S3',
artifactBounds: deployArtifactBounds(),
inputs: [props.input],
});
this.props = props;
}
protected bound(_scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions):
codepipeline.ActionConfig {
// pipeline needs permissions to write to the S3 bucket
this.props.bucket.grantWrite(options.role);
if (this.props.accessControl !== undefined) {
// we need to modify the ACL settings of objects within the Bucket,
// so grant the Action's Role permissions to do that
this.props.bucket.grantPutAcl(options.role);
}
// the Action Role also needs to read from the Pipeline's bucket
options.bucket.grantRead(options.role);
this.props.encryptionKey?.grantEncrypt(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: acl ? toKebabCase(acl.toString()) : undefined,
CacheControl: this.props.cacheControl && this.props.cacheControl.map(ac => ac.value).join(', '),
KMSEncryptionKeyARN: this.props.encryptionKey?.keyArn,
},
};
}
}