sst 2.0.0-rc.25 → 2.0.0-rc.28
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/bootstrap.d.ts +2 -4
- package/bootstrap.js +98 -41
- package/cli/commands/deploy.js +13 -8
- package/cli/commands/dev.js +13 -8
- package/cli/commands/remove.d.ts +2 -0
- package/cli/commands/remove.js +21 -4
- package/cli/ui/deploy.js +9 -4
- package/constructs/App.js +9 -1
- package/constructs/Stack.d.ts +1 -3
- package/constructs/Stack.js +7 -28
- package/package.json +1 -1
- package/sst.mjs +287 -199
- package/stacks/monitor.js +2 -1
- package/support/bootstrap-metadata-function/index.mjs +30820 -0
- package/support/custom-resources/index.mjs +69 -33512
package/bootstrap.d.ts
CHANGED
package/bootstrap.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import url from "url";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { DescribeStacksCommand, CloudFormationClient, } from "@aws-sdk/client-cloudformation";
|
|
4
|
+
import { Tags, Stack, RemovalPolicy, App, CfnOutput } from "aws-cdk-lib";
|
|
5
|
+
import { Function, Runtime, Code } from "aws-cdk-lib/aws-lambda";
|
|
6
|
+
import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
7
|
+
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
8
|
+
import { Queue } from "aws-cdk-lib/aws-sqs";
|
|
9
|
+
import { Rule } from "aws-cdk-lib/aws-events";
|
|
10
|
+
import { SqsQueue } from "aws-cdk-lib/aws-events-targets";
|
|
3
11
|
import { BlockPublicAccess, Bucket, BucketEncryption, } from "aws-cdk-lib/aws-s3";
|
|
4
|
-
import { ParameterTier, StringParameter } from "aws-cdk-lib/aws-ssm";
|
|
5
12
|
import { useProject } from "./project.js";
|
|
6
13
|
import { createSpinner } from "./cli/spinner.js";
|
|
7
14
|
import { Context } from "./context/context.js";
|
|
@@ -9,71 +16,121 @@ import { useAWSClient } from "./credentials.js";
|
|
|
9
16
|
import { VisibleError } from "./error.js";
|
|
10
17
|
import { Logger } from "./logger.js";
|
|
11
18
|
import { Stacks } from "./stacks/index.js";
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
19
|
+
const STACK_NAME = "SSTBootstrap";
|
|
20
|
+
const OUTPUT_VERSION = "Version";
|
|
21
|
+
const OUTPUT_BUCKET = "BucketName";
|
|
22
|
+
const LATEST_VERSION = "4";
|
|
23
|
+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
16
24
|
export const useBootstrap = Context.memo(async () => {
|
|
17
25
|
Logger.debug("Initializing bootstrap context");
|
|
18
|
-
|
|
19
|
-
if (!
|
|
20
|
-
!ret.bucket ||
|
|
21
|
-
!ret.stack ||
|
|
22
|
-
ret.version !== LATEST_VERSION) {
|
|
26
|
+
let status = await loadBootstrapStatus();
|
|
27
|
+
if (!status || status.version !== LATEST_VERSION) {
|
|
23
28
|
const project = useProject();
|
|
24
29
|
const spinner = createSpinner("Deploying bootstrap stack, this only needs to happen once").start();
|
|
30
|
+
// Create bootstrap stack
|
|
25
31
|
const app = new App();
|
|
26
|
-
const stack = new Stack(app,
|
|
32
|
+
const stack = new Stack(app, STACK_NAME, {
|
|
27
33
|
env: {
|
|
28
34
|
region: project.config.region,
|
|
29
35
|
},
|
|
30
36
|
});
|
|
37
|
+
// Add tags to stack
|
|
31
38
|
const tags = {};
|
|
32
39
|
for (const [key, value] of Object.entries(tags)) {
|
|
33
40
|
Tags.of(app).add(key, value);
|
|
34
41
|
}
|
|
42
|
+
// Create S3 bucket to store stacks metadata
|
|
35
43
|
const bucket = new Bucket(stack, project.config.region, {
|
|
36
44
|
encryption: BucketEncryption.S3_MANAGED,
|
|
37
45
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
38
46
|
autoDeleteObjects: true,
|
|
39
47
|
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
|
|
40
48
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
// Create Function and subscribe to CloudFormation events
|
|
50
|
+
const fn = new Function(stack, "MetadataHandler", {
|
|
51
|
+
code: Code.fromAsset(path.resolve(__dirname, "support/bootstrap-metadata-function")),
|
|
52
|
+
handler: "index.handler",
|
|
53
|
+
runtime: Runtime.NODEJS_16_X,
|
|
54
|
+
initialPolicy: [
|
|
55
|
+
new PolicyStatement({
|
|
56
|
+
actions: ["cloudformation:DescribeStacks"],
|
|
57
|
+
resources: ["*"],
|
|
58
|
+
}),
|
|
59
|
+
new PolicyStatement({
|
|
60
|
+
actions: ["s3:PutObject", "s3:DeleteObject"],
|
|
61
|
+
resources: [bucket.bucketArn + "/*"],
|
|
62
|
+
}),
|
|
63
|
+
],
|
|
45
64
|
});
|
|
46
|
-
new
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
const queue = new Queue(stack, "MetadataQueue");
|
|
66
|
+
fn.addEventSource(new SqsEventSource(queue));
|
|
67
|
+
const rule = new Rule(stack, "MetadataRule", {
|
|
68
|
+
eventPattern: {
|
|
69
|
+
source: ["aws.cloudformation"],
|
|
70
|
+
detailType: ["CloudFormation Stack Status Change"],
|
|
71
|
+
detail: {
|
|
72
|
+
"status-details": {
|
|
73
|
+
status: [
|
|
74
|
+
"CREATE_COMPLETE",
|
|
75
|
+
"UPDATE_COMPLETE",
|
|
76
|
+
"UPDATE_ROLLBACK_COMPLETE",
|
|
77
|
+
"ROLLBACK_COMPLETE",
|
|
78
|
+
"DELETE_COMPLETE",
|
|
79
|
+
],
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
55
83
|
});
|
|
84
|
+
rule.addTarget(new SqsQueue(queue, {
|
|
85
|
+
retryAttempts: 10,
|
|
86
|
+
}));
|
|
87
|
+
// Create stack outputs to store bootstrap stack info
|
|
88
|
+
new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
|
|
89
|
+
new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
|
|
90
|
+
// Deploy bootstrap stack
|
|
56
91
|
const asm = app.synth();
|
|
57
92
|
const result = await Stacks.deploy(asm.stacks[0]);
|
|
58
93
|
if (Stacks.isFailed(result.status)) {
|
|
59
94
|
throw new VisibleError(`Failed to deploy bootstrap stack:\n${JSON.stringify(result.errors, null, 4)}`);
|
|
60
95
|
}
|
|
61
96
|
spinner.succeed();
|
|
62
|
-
|
|
97
|
+
// Fetch bootstrap status
|
|
98
|
+
status = await loadBootstrapStatus();
|
|
99
|
+
if (!status) {
|
|
100
|
+
throw new VisibleError("Failed to deploy bootstrap stack");
|
|
101
|
+
}
|
|
63
102
|
}
|
|
64
|
-
Logger.debug("Loaded bootstrap info: ", JSON.stringify(
|
|
65
|
-
return
|
|
103
|
+
Logger.debug("Loaded bootstrap info: ", JSON.stringify(status));
|
|
104
|
+
return status;
|
|
66
105
|
});
|
|
67
|
-
async function
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
async function loadBootstrapStatus() {
|
|
107
|
+
// Get bootstrap CloudFormation stack
|
|
108
|
+
const cf = useAWSClient(CloudFormationClient);
|
|
109
|
+
let result;
|
|
110
|
+
try {
|
|
111
|
+
result = await cf.send(new DescribeStacksCommand({
|
|
112
|
+
StackName: STACK_NAME,
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
if (e.Code === "ValidationError"
|
|
117
|
+
&& e.message === `Stack with id ${STACK_NAME} does not exist`) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
throw e;
|
|
121
|
+
}
|
|
122
|
+
// Parse stack outputs
|
|
123
|
+
let version, bucket;
|
|
124
|
+
(result.Stacks[0].Outputs || []).forEach((o) => {
|
|
125
|
+
if (o.OutputKey === OUTPUT_VERSION) {
|
|
126
|
+
version = o.OutputValue;
|
|
127
|
+
}
|
|
128
|
+
else if (o.OutputKey === OUTPUT_BUCKET) {
|
|
129
|
+
bucket = o.OutputValue;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
if (!version || !bucket) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
return { version, bucket };
|
|
79
136
|
}
|
package/cli/commands/deploy.js
CHANGED
|
@@ -37,15 +37,20 @@ export const deploy = (program) => program.command("deploy [filter]", "Work on y
|
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
console.log(`Deploying ${bold(target.length + " stacks")} for stage ${blue(project.config.stage)}...`);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const cleanup = (() => {
|
|
41
|
+
if (args.fullscreen) {
|
|
42
|
+
process.stdout.write("\x1b[?1049h");
|
|
43
|
+
const component = render(React.createElement(DeploymentUI, { stacks: assembly.stacks.map((s) => s.stackName) }));
|
|
44
|
+
return () => {
|
|
45
|
+
component.unmount();
|
|
46
|
+
process.stdout.write("\x1b[?1049l");
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const spinner = createSpinner("Deploying stacks");
|
|
50
|
+
return () => spinner.succeed();
|
|
51
|
+
})();
|
|
45
52
|
const results = await Stacks.deployMany(target);
|
|
46
|
-
|
|
47
|
-
component.unmount();
|
|
48
|
-
process.stdout.write("\x1b[?1049l");
|
|
53
|
+
cleanup();
|
|
49
54
|
printDeploymentResults(results);
|
|
50
55
|
if (Object.values(results).some((stack) => Stacks.isFailed(stack.status)))
|
|
51
56
|
process.exit(1);
|
package/cli/commands/dev.js
CHANGED
|
@@ -108,15 +108,20 @@ export const dev = (program) => program.command(["start", "dev"], "Work on your
|
|
|
108
108
|
const assembly = pending;
|
|
109
109
|
const nextChecksum = await checksum(assembly.directory);
|
|
110
110
|
pending = undefined;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
const cleanup = (() => {
|
|
112
|
+
if (args.fullscreen) {
|
|
113
|
+
process.stdout.write("\x1b[?1049h");
|
|
114
|
+
const component = render(React.createElement(DeploymentUI, { stacks: assembly.stacks.map((s) => s.stackName) }));
|
|
115
|
+
return () => {
|
|
116
|
+
component.unmount();
|
|
117
|
+
process.stdout.write("\x1b[?1049l");
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const spinner = createSpinner("Deploying stacks");
|
|
121
|
+
return () => spinner.succeed();
|
|
122
|
+
})();
|
|
116
123
|
const results = await Stacks.deployMany(assembly.stacks);
|
|
117
|
-
|
|
118
|
-
component.unmount();
|
|
119
|
-
process.stdout.write("\x1b[?1049l");
|
|
124
|
+
cleanup();
|
|
120
125
|
lastDeployed = nextChecksum;
|
|
121
126
|
printDeploymentResults(results);
|
|
122
127
|
const keys = await SiteEnv.keys();
|
package/cli/commands/remove.d.ts
CHANGED
package/cli/commands/remove.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { createSpinner } from "../spinner.js";
|
|
1
2
|
import { printDeploymentResults } from "../ui/deploy.js";
|
|
2
3
|
export const remove = (program) => program.command("remove [filter]", "Remove all stacks for this app", (yargs) => yargs
|
|
3
4
|
.option("from", { type: "string" })
|
|
5
|
+
.option("fullscreen", {
|
|
6
|
+
type: "boolean",
|
|
7
|
+
describe: "Disable full screen UI",
|
|
8
|
+
default: true,
|
|
9
|
+
})
|
|
4
10
|
.positional("filter", { type: "string" }), async (args) => {
|
|
5
11
|
const React = await import("react");
|
|
6
12
|
const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
|
|
@@ -28,11 +34,22 @@ export const remove = (program) => program.command("remove [filter]", "Remove al
|
|
|
28
34
|
process.exit(1);
|
|
29
35
|
}
|
|
30
36
|
console.log(`Removing ${bold(target.length + " stacks")} for stage ${blue(project.config.stage)}...`);
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const cleanup = (() => {
|
|
38
|
+
if (args.fullscreen) {
|
|
39
|
+
process.stdout.write("\x1b[?1049h");
|
|
40
|
+
const component = render(React.createElement(DeploymentUI, { stacks: assembly.stacks.map((s) => s.stackName) }));
|
|
41
|
+
return () => {
|
|
42
|
+
component.unmount();
|
|
43
|
+
process.stdout.write("\x1b[?1049l");
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const spinner = createSpinner("Removing stacks");
|
|
47
|
+
return () => spinner.succeed();
|
|
48
|
+
})();
|
|
33
49
|
const results = await Stacks.removeMany(target);
|
|
34
|
-
|
|
35
|
-
process.stdout.write("\x1b[?1049l");
|
|
50
|
+
cleanup();
|
|
36
51
|
printDeploymentResults(results);
|
|
52
|
+
if (Object.values(results).some((stack) => Stacks.isFailed(stack.status)))
|
|
53
|
+
process.exit(1);
|
|
37
54
|
process.exit(0);
|
|
38
55
|
});
|
package/cli/ui/deploy.js
CHANGED
|
@@ -76,7 +76,10 @@ export const DeploymentUI = (props) => {
|
|
|
76
76
|
React.createElement(Text, null,
|
|
77
77
|
"Deploying ",
|
|
78
78
|
React.createElement(Text, { color: "bold" }, props.stacks.length),
|
|
79
|
-
"
|
|
79
|
+
" stack",
|
|
80
|
+
props.stacks.length > 1 && "s",
|
|
81
|
+
" for stage",
|
|
82
|
+
" ",
|
|
80
83
|
React.createElement(Text, { color: "blue" }, useProject().config.stage)),
|
|
81
84
|
Object.entries(stacks).map(([stackID, status]) => {
|
|
82
85
|
return (React.createElement(React.Fragment, { key: stackID },
|
|
@@ -106,9 +109,9 @@ export const DeploymentUI = (props) => {
|
|
|
106
109
|
};
|
|
107
110
|
export function printDeploymentResults(results) {
|
|
108
111
|
console.log();
|
|
109
|
-
console.log(
|
|
110
|
-
console.log(`|
|
|
111
|
-
console.log(
|
|
112
|
+
console.log(`-----------`);
|
|
113
|
+
console.log(`| Summary |`);
|
|
114
|
+
console.log(`-----------`);
|
|
112
115
|
for (const [stack, result] of Object.entries(results)) {
|
|
113
116
|
const icon = (() => {
|
|
114
117
|
if (Stacks.isSuccess(result.status))
|
|
@@ -122,6 +125,8 @@ export function printDeploymentResults(results) {
|
|
|
122
125
|
return false;
|
|
123
126
|
if (key.includes("SstSiteEnv"))
|
|
124
127
|
return false;
|
|
128
|
+
if (key === "SstMetadata")
|
|
129
|
+
return false;
|
|
125
130
|
return true;
|
|
126
131
|
});
|
|
127
132
|
if (outputs.length > 0) {
|
package/constructs/App.js
CHANGED
|
@@ -304,7 +304,15 @@ export class App extends cdk.App {
|
|
|
304
304
|
for (const child of this.node.children) {
|
|
305
305
|
if (child instanceof Stack) {
|
|
306
306
|
const stackName = child.node.id;
|
|
307
|
-
child.
|
|
307
|
+
child.addOutputs({
|
|
308
|
+
SstMetadata: JSON.stringify({
|
|
309
|
+
app: this.name,
|
|
310
|
+
stage: this.stage,
|
|
311
|
+
version: useProject().version,
|
|
312
|
+
bootstrapBucket: this.bootstrap.bucket,
|
|
313
|
+
metadata: byStack[stackName] || [],
|
|
314
|
+
}),
|
|
315
|
+
});
|
|
308
316
|
}
|
|
309
317
|
}
|
|
310
318
|
}
|
package/constructs/Stack.d.ts
CHANGED
|
@@ -32,7 +32,6 @@ export declare class Stack extends cdk.Stack {
|
|
|
32
32
|
* @internal
|
|
33
33
|
*/
|
|
34
34
|
readonly customResourceHandler: lambda.Function;
|
|
35
|
-
private readonly metadata;
|
|
36
35
|
constructor(scope: Construct, id: string, props?: StackProps);
|
|
37
36
|
/**
|
|
38
37
|
* The default function props to be applied to all the Lambda functions in the stack.
|
|
@@ -129,9 +128,8 @@ export declare class Stack extends cdk.Stack {
|
|
|
129
128
|
* ```
|
|
130
129
|
*/
|
|
131
130
|
addOutputs(outputs: Record<string, string | cdk.CfnOutputProps>): void;
|
|
132
|
-
setStackMetadata(metadata: any): void;
|
|
133
131
|
private createCustomResourceHandler;
|
|
134
|
-
private
|
|
132
|
+
private createSecretsMigrationResource;
|
|
135
133
|
private static checkForPropsIsConstruct;
|
|
136
134
|
private static checkForEnvInProps;
|
|
137
135
|
}
|
package/constructs/Stack.js
CHANGED
|
@@ -5,10 +5,8 @@ import * as iam from "aws-cdk-lib/aws-iam";
|
|
|
5
5
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
6
6
|
import { Function as Fn } from "./Function.js";
|
|
7
7
|
import { isConstruct } from "./Construct.js";
|
|
8
|
-
import { createRequire } from "module";
|
|
9
8
|
import { useApp } from "./context.js";
|
|
10
9
|
import { useProject } from "../project.js";
|
|
11
|
-
const require = createRequire(import.meta.url);
|
|
12
10
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
13
11
|
/**
|
|
14
12
|
* The Stack construct extends cdk.Stack. It automatically prefixes the stack names with the stage and app name to ensure that they can be deployed to multiple regions in the same AWS account. It also ensure that the stack uses the same AWS profile and region as the app. They're defined using functions that return resources that can be imported by other stacks.
|
|
@@ -36,7 +34,6 @@ export class Stack extends cdk.Stack {
|
|
|
36
34
|
* @internal
|
|
37
35
|
*/
|
|
38
36
|
customResourceHandler;
|
|
39
|
-
metadata;
|
|
40
37
|
constructor(scope, id, props) {
|
|
41
38
|
const root = scope.node.root;
|
|
42
39
|
const stackId = root.logicalPrefixedName(id);
|
|
@@ -51,15 +48,10 @@ export class Stack extends cdk.Stack {
|
|
|
51
48
|
});
|
|
52
49
|
this.stage = root.stage;
|
|
53
50
|
this.defaultFunctionProps = root.defaultFunctionProps.map((dfp) => typeof dfp === "function" ? dfp(this) : dfp);
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
// We do this two step process because we call the "Template.fromStack"
|
|
57
|
-
// method in the tests. And the call triggers an app synethsis. And we
|
|
58
|
-
// end up synthesize an app multiple times. If we created the Metadata
|
|
59
|
-
// resource on app synth, the tests would fail because the resource
|
|
60
|
-
// would already exist.
|
|
51
|
+
// Create a custom resource handler per stack. This handler will
|
|
52
|
+
// be used by all the custom resources in the stack.
|
|
61
53
|
this.customResourceHandler = this.createCustomResourceHandler();
|
|
62
|
-
this.
|
|
54
|
+
this.createSecretsMigrationResource();
|
|
63
55
|
}
|
|
64
56
|
/**
|
|
65
57
|
* The default function props to be applied to all the Lambda functions in the stack.
|
|
@@ -200,9 +192,6 @@ export class Stack extends cdk.Stack {
|
|
|
200
192
|
}
|
|
201
193
|
});
|
|
202
194
|
}
|
|
203
|
-
setStackMetadata(metadata) {
|
|
204
|
-
this.metadata.node.defaultChild.addPropertyOverride("Metadata", metadata);
|
|
205
|
-
}
|
|
206
195
|
createCustomResourceHandler() {
|
|
207
196
|
return new lambda.Function(this, "CustomResourceHandler", {
|
|
208
197
|
code: lambda.Code.fromAsset(path.join(__dirname, "../support/custom-resources/"), {
|
|
@@ -214,14 +203,9 @@ export class Stack extends cdk.Stack {
|
|
|
214
203
|
memorySize: 1024,
|
|
215
204
|
});
|
|
216
205
|
}
|
|
217
|
-
|
|
206
|
+
createSecretsMigrationResource() {
|
|
218
207
|
const app = useApp();
|
|
219
|
-
//
|
|
220
|
-
this.customResourceHandler.addToRolePolicy(new iam.PolicyStatement({
|
|
221
|
-
actions: ["s3:PutObject", "s3:DeleteObject"],
|
|
222
|
-
resources: [`arn:aws:s3:::${app.bootstrap.bucket}/*`],
|
|
223
|
-
}));
|
|
224
|
-
// Temporary: Add permissions to migrate SSM paths for secrets (piggybacking on the stack metadata custom resource handler)
|
|
208
|
+
// Add permissions to migrate SSM paths for secrets
|
|
225
209
|
this.customResourceHandler.addToRolePolicy(new iam.PolicyStatement({
|
|
226
210
|
actions: ["ssm:GetParametersByPath", "ssm:PutParameter"],
|
|
227
211
|
resources: [
|
|
@@ -229,18 +213,13 @@ export class Stack extends cdk.Stack {
|
|
|
229
213
|
`arn:aws:ssm:${app.region}:${app.account}:parameter/sst/${app.name}/.fallback/*`,
|
|
230
214
|
],
|
|
231
215
|
}));
|
|
232
|
-
|
|
216
|
+
new cdk.CustomResource(this, "SecretsMigration", {
|
|
233
217
|
serviceToken: this.customResourceHandler.functionArn,
|
|
234
|
-
resourceType: "Custom::
|
|
218
|
+
resourceType: "Custom::SecretsMigration",
|
|
235
219
|
properties: {
|
|
236
220
|
App: app.name,
|
|
237
221
|
Stage: this.stage,
|
|
238
|
-
Stack: this.stackName,
|
|
239
222
|
SSTVersion: useProject().version,
|
|
240
|
-
BootstrapBucketName: app.bootstrap.bucket,
|
|
241
|
-
ForceUpdate: process.env.SST_FORCE_UPDATE_METADATA
|
|
242
|
-
? Date.now().toString()
|
|
243
|
-
: undefined,
|
|
244
223
|
},
|
|
245
224
|
});
|
|
246
225
|
}
|