sst 2.0.12 → 2.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constructs/Job.d.ts +0 -1
- package/constructs/Job.js +53 -68
- package/constructs/SsrSite.js +17 -24
- package/constructs/Stack.js +5 -2
- package/constructs/StaticSite.js +22 -29
- package/constructs/deprecated/NextjsSite.js +25 -31
- package/package.json +2 -1
- package/sst.mjs +5 -0
- package/stacks/deploy.js +5 -0
- package/support/custom-resources/index.mjs +25448 -0
- package/support/job-invoker/index.mjs +26317 -26
- package/support/base-site-custom-resource/cf-invalidate.py +0 -130
package/constructs/Job.d.ts
CHANGED
|
@@ -140,7 +140,6 @@ export declare class Job extends Construct implements SSTConstruct {
|
|
|
140
140
|
private readonly localId;
|
|
141
141
|
private readonly props;
|
|
142
142
|
private readonly job;
|
|
143
|
-
private readonly isLiveDevEnabled;
|
|
144
143
|
readonly _jobInvoker: Function;
|
|
145
144
|
constructor(scope: Construct, id: string, props: JobProps);
|
|
146
145
|
getConstructMetadata(): {
|
package/constructs/Job.js
CHANGED
|
@@ -3,9 +3,9 @@ import url from "url";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import fs from "fs/promises";
|
|
5
5
|
import { Construct } from "constructs";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
6
|
+
import { PolicyStatement, Effect } from "aws-cdk-lib/aws-iam";
|
|
7
|
+
import { AssetCode } from "aws-cdk-lib/aws-lambda";
|
|
8
|
+
import { Project, LinuxBuildImage, BuildSpec, ComputeType, } from "aws-cdk-lib/aws-codebuild";
|
|
9
9
|
import { Stack } from "./Stack.js";
|
|
10
10
|
import { Function, useFunctions } from "./Function.js";
|
|
11
11
|
import { toCdkDuration } from "./util/duration.js";
|
|
@@ -37,7 +37,6 @@ export class Job extends Construct {
|
|
|
37
37
|
localId;
|
|
38
38
|
props;
|
|
39
39
|
job;
|
|
40
|
-
isLiveDevEnabled;
|
|
41
40
|
_jobInvoker;
|
|
42
41
|
constructor(scope, id, props) {
|
|
43
42
|
super(scope, props.cdk?.id || id);
|
|
@@ -53,9 +52,9 @@ export class Job extends Construct {
|
|
|
53
52
|
.replace(/\$/g, "-")
|
|
54
53
|
.replace(/\//g, "-")
|
|
55
54
|
.replace(/\./g, "-");
|
|
56
|
-
|
|
55
|
+
const isLiveDevEnabled = app.local && (this.props.enableLiveDev === false ? false : true);
|
|
57
56
|
this.job = this.createCodeBuildProject();
|
|
58
|
-
if (
|
|
57
|
+
if (isLiveDevEnabled) {
|
|
59
58
|
this._jobInvoker = this.createLocalInvoker();
|
|
60
59
|
}
|
|
61
60
|
else {
|
|
@@ -129,7 +128,7 @@ export class Job extends Construct {
|
|
|
129
128
|
}
|
|
130
129
|
createCodeBuildProject() {
|
|
131
130
|
const app = this.node.root;
|
|
132
|
-
return new
|
|
131
|
+
return new Project(this, "JobProject", {
|
|
133
132
|
vpc: this.props.cdk?.vpc,
|
|
134
133
|
projectName: app.logicalPrefixedName(this.node.id),
|
|
135
134
|
environment: {
|
|
@@ -139,7 +138,7 @@ export class Job extends Construct {
|
|
|
139
138
|
// purpose of this demo, I use STANDARD_5_0. It takes 30s to boot.
|
|
140
139
|
//buildImage: codebuild.LinuxBuildImage.STANDARD_6_0,
|
|
141
140
|
//buildImage: codebuild.LinuxBuildImage.STANDARD_5_0,
|
|
142
|
-
buildImage:
|
|
141
|
+
buildImage: LinuxBuildImage.fromDockerRegistry("amazon/aws-lambda-nodejs:16"),
|
|
143
142
|
computeType: this.normalizeMemorySize(this.props.memorySize || "3 GB"),
|
|
144
143
|
},
|
|
145
144
|
environmentVariables: {
|
|
@@ -148,7 +147,7 @@ export class Job extends Construct {
|
|
|
148
147
|
SST_SSM_PREFIX: { value: useProject().config.ssmPrefix },
|
|
149
148
|
},
|
|
150
149
|
timeout: this.normalizeTimeout(this.props.timeout || "8 hours"),
|
|
151
|
-
buildSpec:
|
|
150
|
+
buildSpec: BuildSpec.fromObject({
|
|
152
151
|
version: "0.2",
|
|
153
152
|
phases: {
|
|
154
153
|
build: {
|
|
@@ -163,54 +162,40 @@ export class Job extends Construct {
|
|
|
163
162
|
buildCodeBuildProjectCode() {
|
|
164
163
|
const app = this.node.root;
|
|
165
164
|
// Handle remove (ie. sst remove)
|
|
166
|
-
if (app.mode
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
`console.log("----------------------")`,
|
|
201
|
-
`console.log("")`,
|
|
202
|
-
`console.log("Result:", result);`,
|
|
203
|
-
`console.log("")`,
|
|
204
|
-
`console.log("//////////////////////")`,
|
|
205
|
-
`console.log("// End of the job //")`,
|
|
206
|
-
`console.log("//////////////////////")`,
|
|
207
|
-
`console.log("")`,
|
|
208
|
-
].join("\n"));
|
|
209
|
-
const code = lambda.AssetCode.fromAsset(bundle.out);
|
|
210
|
-
this.updateCodeBuildProjectCode(code, "handler-wrapper.js");
|
|
211
|
-
// This should always be true b/c runtime is always Node.js
|
|
212
|
-
});
|
|
213
|
-
}
|
|
165
|
+
if (app.mode === "remove")
|
|
166
|
+
return;
|
|
167
|
+
useDeferredTasks().add(async () => {
|
|
168
|
+
// Build function
|
|
169
|
+
const bundle = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
170
|
+
// create wrapper that calls the handler
|
|
171
|
+
if (bundle.type === "error")
|
|
172
|
+
throw new Error(`Failed to build job "${this.props.handler}"`);
|
|
173
|
+
const parsed = path.parse(bundle.handler);
|
|
174
|
+
const importName = parsed.ext.substring(1);
|
|
175
|
+
const importPath = `./${path.join(parsed.dir, parsed.name)}.mjs`;
|
|
176
|
+
await fs.writeFile(path.join(bundle.out, "handler-wrapper.mjs"), [
|
|
177
|
+
`console.log("")`,
|
|
178
|
+
`console.log("//////////////////////")`,
|
|
179
|
+
`console.log("// Start of the job //")`,
|
|
180
|
+
`console.log("//////////////////////")`,
|
|
181
|
+
`console.log("")`,
|
|
182
|
+
`import { ${importName} } from "${importPath}";`,
|
|
183
|
+
`const event = JSON.parse(process.env.SST_PAYLOAD);`,
|
|
184
|
+
`const result = await ${importName}(event);`,
|
|
185
|
+
`console.log("")`,
|
|
186
|
+
`console.log("----------------------")`,
|
|
187
|
+
`console.log("")`,
|
|
188
|
+
`console.log("Result:", result);`,
|
|
189
|
+
`console.log("")`,
|
|
190
|
+
`console.log("//////////////////////")`,
|
|
191
|
+
`console.log("// End of the job //")`,
|
|
192
|
+
`console.log("//////////////////////")`,
|
|
193
|
+
`console.log("")`,
|
|
194
|
+
].join("\n"));
|
|
195
|
+
const code = AssetCode.fromAsset(bundle.out);
|
|
196
|
+
this.updateCodeBuildProjectCode(code, "handler-wrapper.mjs");
|
|
197
|
+
// This should always be true b/c runtime is always Node.js
|
|
198
|
+
});
|
|
214
199
|
}
|
|
215
200
|
updateCodeBuildProjectCode(code, script) {
|
|
216
201
|
// Update job's commands
|
|
@@ -228,9 +213,9 @@ export class Job extends Construct {
|
|
|
228
213
|
].join("\n"),
|
|
229
214
|
};
|
|
230
215
|
this.attachPermissions([
|
|
231
|
-
new
|
|
216
|
+
new PolicyStatement({
|
|
232
217
|
actions: ["s3:*"],
|
|
233
|
-
effect:
|
|
218
|
+
effect: Effect.ALLOW,
|
|
234
219
|
resources: [
|
|
235
220
|
`arn:${Stack.of(this).partition}:s3:::${codeConfig.s3Location?.bucketName}/${codeConfig.s3Location?.objectKey}`,
|
|
236
221
|
],
|
|
@@ -259,15 +244,15 @@ export class Job extends Construct {
|
|
|
259
244
|
createCodeBuildInvoker() {
|
|
260
245
|
const fn = new Function(this, this.node.id, {
|
|
261
246
|
handler: path.join(__dirname, "../support/job-invoker/index.main"),
|
|
262
|
-
runtime: "
|
|
247
|
+
runtime: "nodejs18.x",
|
|
263
248
|
timeout: 10,
|
|
264
249
|
memorySize: 1024,
|
|
265
250
|
environment: {
|
|
266
251
|
PROJECT_NAME: this.job.projectName,
|
|
267
252
|
},
|
|
268
253
|
permissions: [
|
|
269
|
-
new
|
|
270
|
-
effect:
|
|
254
|
+
new PolicyStatement({
|
|
255
|
+
effect: Effect.ALLOW,
|
|
271
256
|
actions: ["codebuild:StartBuild"],
|
|
272
257
|
resources: [this.job.projectArn],
|
|
273
258
|
}),
|
|
@@ -289,9 +274,9 @@ export class Job extends Construct {
|
|
|
289
274
|
// Bind permissions
|
|
290
275
|
const permissions = bindPermissions(c);
|
|
291
276
|
Object.entries(permissions).forEach(([action, resources]) => this.attachPermissionsForCodeBuild([
|
|
292
|
-
new
|
|
277
|
+
new PolicyStatement({
|
|
293
278
|
actions: [action],
|
|
294
|
-
effect:
|
|
279
|
+
effect: Effect.ALLOW,
|
|
295
280
|
resources,
|
|
296
281
|
}),
|
|
297
282
|
]));
|
|
@@ -308,16 +293,16 @@ export class Job extends Construct {
|
|
|
308
293
|
}
|
|
309
294
|
normalizeMemorySize(memorySize) {
|
|
310
295
|
if (memorySize === "3 GB") {
|
|
311
|
-
return
|
|
296
|
+
return ComputeType.SMALL;
|
|
312
297
|
}
|
|
313
298
|
else if (memorySize === "7 GB") {
|
|
314
|
-
return
|
|
299
|
+
return ComputeType.MEDIUM;
|
|
315
300
|
}
|
|
316
301
|
else if (memorySize === "15 GB") {
|
|
317
|
-
return
|
|
302
|
+
return ComputeType.LARGE;
|
|
318
303
|
}
|
|
319
304
|
else if (memorySize === "145 GB") {
|
|
320
|
-
return
|
|
305
|
+
return ComputeType.X2_LARGE;
|
|
321
306
|
}
|
|
322
307
|
throw new Error(`Invalid memory size value for the ${this.node.id} Job.`);
|
|
323
308
|
}
|
package/constructs/SsrSite.js
CHANGED
|
@@ -100,7 +100,7 @@ export class SsrSite extends Construct {
|
|
|
100
100
|
: this.createCloudFrontDistributionForRegional();
|
|
101
101
|
this.distribution.node.addDependency(s3deployCR);
|
|
102
102
|
// Invalidate CloudFront
|
|
103
|
-
const invalidationCR = this.createCloudFrontInvalidation(
|
|
103
|
+
const invalidationCR = this.createCloudFrontInvalidation();
|
|
104
104
|
invalidationCR.node.addDependency(this.distribution);
|
|
105
105
|
// Connect Custom Domain to CloudFront Distribution
|
|
106
106
|
this.createRoute53Records();
|
|
@@ -551,36 +551,29 @@ export class SsrSite extends Construct {
|
|
|
551
551
|
comment: "SST server response cache policy",
|
|
552
552
|
});
|
|
553
553
|
}
|
|
554
|
-
createCloudFrontInvalidation(
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
554
|
+
createCloudFrontInvalidation() {
|
|
555
|
+
const stack = Stack.of(this);
|
|
556
|
+
const resource = new CustomResource(this, "CloudFrontInvalidator", {
|
|
557
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
558
|
+
resourceType: "Custom::CloudFrontInvalidator",
|
|
559
|
+
properties: {
|
|
560
|
+
buildId: this.generateBuildId(),
|
|
561
|
+
distributionId: this.distribution.distributionId,
|
|
562
|
+
paths: ["/*"],
|
|
563
|
+
waitForInvalidation: this.props.waitForInvalidation,
|
|
564
|
+
},
|
|
563
565
|
});
|
|
564
|
-
|
|
565
|
-
invalidator.addToRolePolicy(new PolicyStatement({
|
|
566
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
|
|
566
567
|
effect: Effect.ALLOW,
|
|
567
568
|
actions: [
|
|
568
569
|
"cloudfront:GetInvalidation",
|
|
569
570
|
"cloudfront:CreateInvalidation",
|
|
570
571
|
],
|
|
571
|
-
resources: [
|
|
572
|
+
resources: [
|
|
573
|
+
`arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.distribution.distributionId}`,
|
|
574
|
+
],
|
|
572
575
|
}));
|
|
573
|
-
return
|
|
574
|
-
serviceToken: invalidator.functionArn,
|
|
575
|
-
resourceType: "Custom::SSTCloudFrontInvalidation",
|
|
576
|
-
properties: {
|
|
577
|
-
BuildId: this.generateBuildId(),
|
|
578
|
-
DistributionId: this.distribution.distributionId,
|
|
579
|
-
// TODO: Ignore the browser build path as it may speed up invalidation
|
|
580
|
-
DistributionPaths: ["/*"],
|
|
581
|
-
WaitForInvalidation: this.props.waitForInvalidation,
|
|
582
|
-
},
|
|
583
|
-
});
|
|
576
|
+
return resource;
|
|
584
577
|
}
|
|
585
578
|
/////////////////////
|
|
586
579
|
// Custom Domain
|
package/constructs/Stack.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fs from "fs";
|
|
1
2
|
import url from "url";
|
|
2
3
|
import * as path from "path";
|
|
3
4
|
import * as cdk from "aws-cdk-lib";
|
|
@@ -172,9 +173,11 @@ export class Stack extends cdk.Stack {
|
|
|
172
173
|
});
|
|
173
174
|
}
|
|
174
175
|
createCustomResourceHandler() {
|
|
176
|
+
const dir = path.join(__dirname, "../support/custom-resources/");
|
|
175
177
|
return new lambda.Function(this, "CustomResourceHandler", {
|
|
176
|
-
code: lambda.Code.fromAsset(
|
|
177
|
-
assetHash: this.stackName + "-custom-resources-20230130",
|
|
178
|
+
code: lambda.Code.fromAsset(dir, {
|
|
179
|
+
//assetHash: this.stackName + "-custom-resources-20230130",
|
|
180
|
+
assetHash: this.stackName + fs.readFileSync(dir + "/index.mjs").toString(),
|
|
178
181
|
}),
|
|
179
182
|
handler: "index.handler",
|
|
180
183
|
runtime: lambda.Runtime.NODEJS_16_X,
|
package/constructs/StaticSite.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Construct } from "constructs";
|
|
|
7
7
|
import { Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
|
|
8
8
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
9
9
|
import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
|
|
10
|
-
import
|
|
10
|
+
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
11
11
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
12
12
|
import * as route53 from "aws-cdk-lib/aws-route53";
|
|
13
13
|
import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
|
|
@@ -91,7 +91,7 @@ export class StaticSite extends Construct {
|
|
|
91
91
|
this.distribution = this.createCfDistribution();
|
|
92
92
|
this.distribution.node.addDependency(s3deployCR);
|
|
93
93
|
// Invalidate CloudFront
|
|
94
|
-
const invalidationCR = this.createCloudFrontInvalidation(
|
|
94
|
+
const invalidationCR = this.createCloudFrontInvalidation(assets);
|
|
95
95
|
invalidationCR.node.addDependency(this.distribution);
|
|
96
96
|
// Connect Custom Domain to CloudFront Distribution
|
|
97
97
|
this.createRoute53Records();
|
|
@@ -420,41 +420,34 @@ interface ImportMeta {
|
|
|
420
420
|
},
|
|
421
421
|
});
|
|
422
422
|
}
|
|
423
|
-
createCloudFrontInvalidation(
|
|
424
|
-
|
|
425
|
-
const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
|
|
426
|
-
code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
|
|
427
|
-
layers: [cliLayer],
|
|
428
|
-
runtime: lambda.Runtime.PYTHON_3_7,
|
|
429
|
-
handler: "cf-invalidate.handler",
|
|
430
|
-
timeout: Duration.minutes(15),
|
|
431
|
-
memorySize: 1024,
|
|
432
|
-
});
|
|
433
|
-
// Grant permissions to invalidate CF Distribution
|
|
434
|
-
invalidator.addToRolePolicy(new iam.PolicyStatement({
|
|
435
|
-
effect: iam.Effect.ALLOW,
|
|
436
|
-
actions: [
|
|
437
|
-
"cloudfront:GetInvalidation",
|
|
438
|
-
"cloudfront:CreateInvalidation",
|
|
439
|
-
],
|
|
440
|
-
resources: ["*"],
|
|
441
|
-
}));
|
|
423
|
+
createCloudFrontInvalidation(assets) {
|
|
424
|
+
const stack = Stack.of(this);
|
|
442
425
|
// Need the AssetHash field so the CR gets updated on each deploy
|
|
443
426
|
const assetsHash = crypto
|
|
444
427
|
.createHash("md5")
|
|
445
428
|
.update(assets.map(({ assetHash }) => assetHash).join(""))
|
|
446
429
|
.digest("hex");
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
resourceType: "Custom::SSTCloudFrontInvalidation",
|
|
430
|
+
const resource = new CustomResource(this, "CloudFrontInvalidator", {
|
|
431
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
432
|
+
resourceType: "Custom::CloudFrontInvalidator",
|
|
451
433
|
properties: {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
434
|
+
assetsHash,
|
|
435
|
+
distributionId: this.distribution.distributionId,
|
|
436
|
+
paths: ["/*"],
|
|
437
|
+
waitForInvalidation: this.props.waitForInvalidation,
|
|
456
438
|
},
|
|
457
439
|
});
|
|
440
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
|
|
441
|
+
effect: Effect.ALLOW,
|
|
442
|
+
actions: [
|
|
443
|
+
"cloudfront:GetInvalidation",
|
|
444
|
+
"cloudfront:CreateInvalidation",
|
|
445
|
+
],
|
|
446
|
+
resources: [
|
|
447
|
+
`arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.distribution.distributionId}`,
|
|
448
|
+
],
|
|
449
|
+
}));
|
|
450
|
+
return resource;
|
|
458
451
|
}
|
|
459
452
|
/////////////////////
|
|
460
453
|
// Custom Domain
|
|
@@ -6,7 +6,7 @@ import { execSync } from "child_process";
|
|
|
6
6
|
import { Construct } from "constructs";
|
|
7
7
|
import { Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
|
|
8
8
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
9
|
-
import
|
|
9
|
+
import { Role, Effect, PolicyStatement, CompositePrincipal, ServicePrincipal, ManagedPolicy, } from "aws-cdk-lib/aws-iam";
|
|
10
10
|
import * as sqs from "aws-cdk-lib/aws-sqs";
|
|
11
11
|
import * as logs from "aws-cdk-lib/aws-logs";
|
|
12
12
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
@@ -388,10 +388,10 @@ export class NextjsSite extends Construct {
|
|
|
388
388
|
createEdgeFunctionRole() {
|
|
389
389
|
const { defaults } = this.props;
|
|
390
390
|
// Create function role
|
|
391
|
-
const role = new
|
|
392
|
-
assumedBy: new
|
|
391
|
+
const role = new Role(this, `EdgeLambdaRole`, {
|
|
392
|
+
assumedBy: new CompositePrincipal(new ServicePrincipal("lambda.amazonaws.com"), new ServicePrincipal("edgelambda.amazonaws.com")),
|
|
393
393
|
managedPolicies: [
|
|
394
|
-
|
|
394
|
+
ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
|
|
395
395
|
],
|
|
396
396
|
});
|
|
397
397
|
// Attach permission
|
|
@@ -470,8 +470,8 @@ export class NextjsSite extends Construct {
|
|
|
470
470
|
});
|
|
471
471
|
}
|
|
472
472
|
// Allow provider to perform search/replace on the asset
|
|
473
|
-
provider.role?.addToPrincipalPolicy(new
|
|
474
|
-
effect:
|
|
473
|
+
provider.role?.addToPrincipalPolicy(new PolicyStatement({
|
|
474
|
+
effect: Effect.ALLOW,
|
|
475
475
|
actions: ["s3:*"],
|
|
476
476
|
resources: [
|
|
477
477
|
`arn:${Stack.of(this).partition}:s3:::${asset.s3BucketName}/${asset.s3ObjectKey}`,
|
|
@@ -813,24 +813,7 @@ export class NextjsSite extends Construct {
|
|
|
813
813
|
return new cloudfront.OriginRequestPolicy(this, "ImageOriginRequest", NextjsSite.imageOriginRequestPolicyProps);
|
|
814
814
|
}
|
|
815
815
|
createCloudFrontInvalidation() {
|
|
816
|
-
|
|
817
|
-
const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
|
|
818
|
-
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/base-site-custom-resource")),
|
|
819
|
-
layers: [this.awsCliLayer],
|
|
820
|
-
runtime: lambda.Runtime.PYTHON_3_7,
|
|
821
|
-
handler: "cf-invalidate.handler",
|
|
822
|
-
timeout: Duration.minutes(15),
|
|
823
|
-
memorySize: 1024,
|
|
824
|
-
});
|
|
825
|
-
// Grant permissions to invalidate CF Distribution
|
|
826
|
-
invalidator.addToRolePolicy(new iam.PolicyStatement({
|
|
827
|
-
effect: iam.Effect.ALLOW,
|
|
828
|
-
actions: [
|
|
829
|
-
"cloudfront:GetInvalidation",
|
|
830
|
-
"cloudfront:CreateInvalidation",
|
|
831
|
-
],
|
|
832
|
-
resources: ["*"],
|
|
833
|
-
}));
|
|
816
|
+
const stack = Stack.of(this);
|
|
834
817
|
// need the BuildId field so this CR gets updated on each deploy
|
|
835
818
|
let buildId;
|
|
836
819
|
if (this.isPlaceholder) {
|
|
@@ -846,16 +829,27 @@ export class NextjsSite extends Construct {
|
|
|
846
829
|
: this.props.waitForInvalidation === false
|
|
847
830
|
? false
|
|
848
831
|
: true;
|
|
849
|
-
|
|
850
|
-
serviceToken:
|
|
851
|
-
resourceType: "Custom::
|
|
832
|
+
const resource = new CustomResource(this, "CloudFrontInvalidator", {
|
|
833
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
834
|
+
resourceType: "Custom::CloudFrontInvalidator",
|
|
852
835
|
properties: {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
836
|
+
buildId,
|
|
837
|
+
distributionId: this.cdk.distribution.distributionId,
|
|
838
|
+
paths: ["/*"],
|
|
839
|
+
waitForInvalidation,
|
|
857
840
|
},
|
|
858
841
|
});
|
|
842
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
|
|
843
|
+
effect: Effect.ALLOW,
|
|
844
|
+
actions: [
|
|
845
|
+
"cloudfront:GetInvalidation",
|
|
846
|
+
"cloudfront:CreateInvalidation",
|
|
847
|
+
],
|
|
848
|
+
resources: [
|
|
849
|
+
`arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.cdk.distribution.distributionId}`,
|
|
850
|
+
],
|
|
851
|
+
}));
|
|
852
|
+
return resource;
|
|
859
853
|
}
|
|
860
854
|
/////////////////////
|
|
861
855
|
// Custom Domain
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sst",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.14",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sst": "cli/sst.js"
|
|
6
6
|
},
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@aws-cdk/cx-api": "2.62.2",
|
|
31
31
|
"@aws-cdk/region-info": "2.62.2",
|
|
32
32
|
"@aws-sdk/client-cloudformation": "3.208.0",
|
|
33
|
+
"@aws-sdk/client-cloudfront": "3.208.0",
|
|
33
34
|
"@aws-sdk/client-iot": "3.208.0",
|
|
34
35
|
"@aws-sdk/client-iot-data-plane": "3.208.0",
|
|
35
36
|
"@aws-sdk/client-lambda": "3.208.0",
|
package/sst.mjs
CHANGED
|
@@ -4228,11 +4228,16 @@ async function deploy(stack) {
|
|
|
4228
4228
|
const deployment = new CloudFormationDeployments2({
|
|
4229
4229
|
sdkProvider: provider
|
|
4230
4230
|
});
|
|
4231
|
+
const stackTags = Object.entries(stack.tags ?? {}).map(([Key, Value]) => ({
|
|
4232
|
+
Key,
|
|
4233
|
+
Value
|
|
4234
|
+
}));
|
|
4231
4235
|
try {
|
|
4232
4236
|
await addInUseExports(stack);
|
|
4233
4237
|
const result = await deployment.deployStack({
|
|
4234
4238
|
stack,
|
|
4235
4239
|
quiet: true,
|
|
4240
|
+
tags: stackTags,
|
|
4236
4241
|
deploymentMethod: {
|
|
4237
4242
|
method: "direct"
|
|
4238
4243
|
}
|
package/stacks/deploy.js
CHANGED
|
@@ -74,11 +74,16 @@ export async function deploy(stack) {
|
|
|
74
74
|
const deployment = new CloudFormationDeployments({
|
|
75
75
|
sdkProvider: provider,
|
|
76
76
|
});
|
|
77
|
+
const stackTags = Object.entries(stack.tags ?? {}).map(([Key, Value]) => ({
|
|
78
|
+
Key,
|
|
79
|
+
Value,
|
|
80
|
+
}));
|
|
77
81
|
try {
|
|
78
82
|
await addInUseExports(stack);
|
|
79
83
|
const result = await deployment.deployStack({
|
|
80
84
|
stack: stack,
|
|
81
85
|
quiet: true,
|
|
86
|
+
tags: stackTags,
|
|
82
87
|
deploymentMethod: {
|
|
83
88
|
method: "direct",
|
|
84
89
|
},
|