sst 2.0.0-rc.37 → 2.0.0-rc.39
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.js +3 -1
- package/cdk/cloudformation-deployments-wrapper.d.ts +3 -2
- package/cdk/cloudformation-deployments-wrapper.js +97 -10
- package/cdk/cloudformation-deployments.d.ts +1 -1
- package/cdk/deploy-stack.d.ts +15 -0
- package/cdk/deploy-stack.js +1 -1
- package/cli/commands/secrets/secrets.js +6 -3
- package/cli/program.js +1 -1
- package/iot.js +4 -0
- package/package.json +1 -1
- package/sst.mjs +269 -39
- package/stacks/deploy.d.ts +1 -1
- package/stacks/deploy.js +6 -8
- package/stacks/metadata.js +8 -7
package/bootstrap.js
CHANGED
|
@@ -68,7 +68,9 @@ export async function initBootstrap() {
|
|
|
68
68
|
}),
|
|
69
69
|
new PolicyStatement({
|
|
70
70
|
actions: ["iot:Publish"],
|
|
71
|
-
resources: [
|
|
71
|
+
resources: [
|
|
72
|
+
`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`,
|
|
73
|
+
],
|
|
72
74
|
}),
|
|
73
75
|
],
|
|
74
76
|
});
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { SdkProvider } from "aws-cdk/lib/api/aws-auth/sdk-provider.js";
|
|
2
|
+
import { DeployStackOptions as PublishStackAssetsOptions } from "./cloudformation-deployments.js";
|
|
3
|
+
export declare function publishDeployAssets(sdkProvider: SdkProvider, options: PublishStackAssetsOptions): Promise<any>;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { debug } from "aws-cdk/lib/logging.js";
|
|
2
|
+
import { CloudFormationStack, TemplateParameters, waitForStackDelete, } from "aws-cdk/lib/api/util/cloudformation.js";
|
|
1
3
|
import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
|
|
4
|
+
import { addMetadataAssetsToManifest } from "aws-cdk/lib/assets.js";
|
|
5
|
+
import { publishAssets } from "aws-cdk/lib/util/asset-publishing.js";
|
|
6
|
+
import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
|
|
7
|
+
import { CloudFormationDeployments, } from "./cloudformation-deployments.js";
|
|
8
|
+
import { makeBodyParameter } from "./deploy-stack.js";
|
|
2
9
|
import { Context } from "../context/context.js";
|
|
3
|
-
export async function
|
|
4
|
-
const toolkitInfo = await
|
|
10
|
+
export async function publishDeployAssets(sdkProvider, options) {
|
|
11
|
+
const { deployment, toolkitInfo, stackSdk, resolvedEnvironment, cloudFormationRoleArn, } = await useDeployment().get(sdkProvider, options);
|
|
5
12
|
await deployment.publishStackAssets(options.stack, toolkitInfo, {
|
|
6
13
|
buildAssets: options.buildAssets ?? true,
|
|
7
14
|
publishOptions: {
|
|
@@ -9,17 +16,97 @@ export async function publishAssets(deployment, options) {
|
|
|
9
16
|
parallel: options.assetParallelism,
|
|
10
17
|
},
|
|
11
18
|
});
|
|
19
|
+
return deployStack({
|
|
20
|
+
stack: options.stack,
|
|
21
|
+
noMonitor: true,
|
|
22
|
+
resolvedEnvironment,
|
|
23
|
+
deployName: options.deployName,
|
|
24
|
+
notificationArns: options.notificationArns,
|
|
25
|
+
quiet: options.quiet,
|
|
26
|
+
sdk: stackSdk,
|
|
27
|
+
sdkProvider,
|
|
28
|
+
roleArn: cloudFormationRoleArn,
|
|
29
|
+
reuseAssets: options.reuseAssets,
|
|
30
|
+
toolkitInfo,
|
|
31
|
+
tags: options.tags,
|
|
32
|
+
deploymentMethod: options.deploymentMethod,
|
|
33
|
+
force: options.force,
|
|
34
|
+
parameters: options.parameters,
|
|
35
|
+
usePreviousParameters: options.usePreviousParameters,
|
|
36
|
+
progress: options.progress,
|
|
37
|
+
ci: options.ci,
|
|
38
|
+
rollback: options.rollback,
|
|
39
|
+
hotswap: options.hotswap,
|
|
40
|
+
extraUserAgent: options.extraUserAgent,
|
|
41
|
+
resourcesToImport: options.resourcesToImport,
|
|
42
|
+
overrideTemplate: options.overrideTemplate,
|
|
43
|
+
assetParallelism: options.assetParallelism,
|
|
44
|
+
});
|
|
12
45
|
}
|
|
13
|
-
const
|
|
46
|
+
const useDeployment = Context.memo(() => {
|
|
14
47
|
const state = new Map();
|
|
15
48
|
return {
|
|
16
|
-
async
|
|
17
|
-
if (state.has(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
49
|
+
async get(sdkProvider, options) {
|
|
50
|
+
if (!state.has(sdkProvider)) {
|
|
51
|
+
const deployment = new CloudFormationDeployments({ sdkProvider });
|
|
52
|
+
const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
|
|
53
|
+
const toolkitInfo = await ToolkitInfo.lookup(resolvedEnvironment, stackSdk, options.toolkitStackName);
|
|
54
|
+
// Do a verification of the bootstrap stack version
|
|
55
|
+
await deployment.validateBootstrapStackVersion(options.stack.stackName, options.stack.requiresBootstrapStackVersion, options.stack.bootstrapStackVersionSsmParameter, toolkitInfo);
|
|
56
|
+
state.set(sdkProvider, {
|
|
57
|
+
deployment,
|
|
58
|
+
toolkitInfo,
|
|
59
|
+
stackSdk,
|
|
60
|
+
resolvedEnvironment,
|
|
61
|
+
cloudFormationRoleArn,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return state.get(sdkProvider);
|
|
23
65
|
}
|
|
24
66
|
};
|
|
25
67
|
});
|
|
68
|
+
async function deployStack(options) {
|
|
69
|
+
const stackArtifact = options.stack;
|
|
70
|
+
const stackEnv = options.resolvedEnvironment;
|
|
71
|
+
options.sdk.appendCustomUserAgent(options.extraUserAgent);
|
|
72
|
+
const cfn = options.sdk.cloudFormation();
|
|
73
|
+
const deployName = options.deployName || stackArtifact.stackName;
|
|
74
|
+
let cloudFormationStack = await CloudFormationStack.lookup(cfn, deployName);
|
|
75
|
+
if (cloudFormationStack.stackStatus.isCreationFailure) {
|
|
76
|
+
debug(`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`);
|
|
77
|
+
await cfn.deleteStack({ StackName: deployName }).promise();
|
|
78
|
+
const deletedStack = await waitForStackDelete(cfn, deployName);
|
|
79
|
+
if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
|
|
80
|
+
throw new Error(`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`);
|
|
81
|
+
}
|
|
82
|
+
// Update variable to mark that the stack does not exist anymore, but avoid
|
|
83
|
+
// doing an actual lookup in CloudFormation (which would be silly to do if
|
|
84
|
+
// we just deleted it).
|
|
85
|
+
cloudFormationStack = CloudFormationStack.doesNotExist(cfn, deployName);
|
|
86
|
+
}
|
|
87
|
+
// Detect "legacy" assets (which remain in the metadata) and publish them via
|
|
88
|
+
// an ad-hoc asset manifest, while passing their locations via template
|
|
89
|
+
// parameters.
|
|
90
|
+
const legacyAssets = new AssetManifestBuilder();
|
|
91
|
+
const assetParams = await addMetadataAssetsToManifest(stackArtifact, legacyAssets, options.toolkitInfo, options.reuseAssets);
|
|
92
|
+
const finalParameterValues = { ...options.parameters, ...assetParams };
|
|
93
|
+
const templateParams = TemplateParameters.fromTemplate(stackArtifact.template);
|
|
94
|
+
const stackParams = options.usePreviousParameters
|
|
95
|
+
? templateParams.updateExisting(finalParameterValues, cloudFormationStack.parameters)
|
|
96
|
+
: templateParams.supplyAll(finalParameterValues);
|
|
97
|
+
const bodyParameter = await makeBodyParameter(stackArtifact, options.resolvedEnvironment, legacyAssets, options.toolkitInfo, options.sdk, options.overrideTemplate);
|
|
98
|
+
await publishAssets(legacyAssets.toManifest(stackArtifact.assembly.directory), options.sdkProvider, stackEnv, {
|
|
99
|
+
parallel: options.assetParallelism,
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== 'REVIEW_IN_PROGRESS',
|
|
103
|
+
params: {
|
|
104
|
+
StackName: deployName,
|
|
105
|
+
TemplateBody: bodyParameter.TemplateBody,
|
|
106
|
+
TemplateURL: bodyParameter.TemplateURL,
|
|
107
|
+
Parameters: stackParams.apiParameters,
|
|
108
|
+
Capabilities: ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'],
|
|
109
|
+
Tags: options.tags,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -290,6 +290,6 @@ export declare class CloudFormationDeployments {
|
|
|
290
290
|
/**
|
|
291
291
|
* Validate that the bootstrap stack has the right version for this stack
|
|
292
292
|
*/
|
|
293
|
-
|
|
293
|
+
validateBootstrapStackVersion(stackName: string, requiresBootstrapStackVersion: number | undefined, bootstrapStackVersionSsmParameter: string | undefined, toolkitInfo: ToolkitInfo): Promise<void>;
|
|
294
294
|
}
|
|
295
295
|
export {};
|
package/cdk/deploy-stack.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as cxapi from "@aws-cdk/cx-api";
|
|
2
2
|
import { Tag } from "aws-cdk/lib/cdk-toolkit.js";
|
|
3
|
+
import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
|
|
3
4
|
import { ISDK, SdkProvider } from "aws-cdk/lib/api/aws-auth/index.js";
|
|
4
5
|
import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
|
|
5
6
|
import { ResourcesToImport } from "aws-cdk/lib/api/util/cloudformation.js";
|
|
@@ -185,6 +186,20 @@ export interface ChangeSetDeploymentMethod {
|
|
|
185
186
|
readonly changeSetName?: string;
|
|
186
187
|
}
|
|
187
188
|
export declare function deployStack(options: DeployStackOptions): Promise<DeployStackResult | undefined>;
|
|
189
|
+
/**
|
|
190
|
+
* Prepares the body parameter for +CreateChangeSet+.
|
|
191
|
+
*
|
|
192
|
+
* If the template is small enough to be inlined into the API call, just return
|
|
193
|
+
* it immediately.
|
|
194
|
+
*
|
|
195
|
+
* Otherwise, add it to the asset manifest to get uploaded to the staging
|
|
196
|
+
* bucket and return its coordinates. If there is no staging bucket, an error
|
|
197
|
+
* is thrown.
|
|
198
|
+
*
|
|
199
|
+
* @param stack the synthesized stack that provides the CloudFormation template
|
|
200
|
+
* @param toolkitInfo information about the toolkit stack
|
|
201
|
+
*/
|
|
202
|
+
export declare function makeBodyParameter(stack: cxapi.CloudFormationStackArtifact, resolvedEnvironment: cxapi.Environment, assetManifest: AssetManifestBuilder, toolkitInfo: ToolkitInfo, sdk: ISDK, overrideTemplate?: any): Promise<TemplateBodyParameter>;
|
|
188
203
|
/**
|
|
189
204
|
* Prepare a body parameter for CFN, performing the upload
|
|
190
205
|
*
|
package/cdk/deploy-stack.js
CHANGED
|
@@ -340,7 +340,7 @@ class FullCloudFormationDeployment {
|
|
|
340
340
|
* @param stack the synthesized stack that provides the CloudFormation template
|
|
341
341
|
* @param toolkitInfo information about the toolkit stack
|
|
342
342
|
*/
|
|
343
|
-
async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
|
|
343
|
+
export async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
|
|
344
344
|
// If the template has already been uploaded to S3, just use it from there.
|
|
345
345
|
if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) {
|
|
346
346
|
return {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { get } from "./get.js";
|
|
2
|
+
import { list } from "./list.js";
|
|
3
|
+
import { remove } from "./remove.js";
|
|
1
4
|
import { set } from "./set.js";
|
|
2
5
|
export function secrets(program) {
|
|
3
6
|
program.command("secrets", "Manage the secrets in your app", (yargs) => {
|
|
4
7
|
yargs.demandCommand(1);
|
|
5
8
|
set(yargs);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
get(yargs);
|
|
10
|
+
list(yargs);
|
|
11
|
+
remove(yargs);
|
|
9
12
|
return yargs;
|
|
10
13
|
});
|
|
11
14
|
}
|
package/cli/program.js
CHANGED
|
@@ -22,7 +22,7 @@ export const program = yargs(hideBin(process.argv))
|
|
|
22
22
|
type: "string",
|
|
23
23
|
describe: "ARN of the IAM role to use when invoking AWS",
|
|
24
24
|
})
|
|
25
|
-
.group(["stage", "profile", "region", "help"], "Global:")
|
|
25
|
+
.group(["stage", "profile", "region", "help", "verbose", "role"], "Global:")
|
|
26
26
|
.middleware(async (argv) => {
|
|
27
27
|
if (argv.verbose) {
|
|
28
28
|
process.env.SST_VERBOSE = "1";
|
package/iot.js
CHANGED
|
@@ -37,6 +37,10 @@ export const useIOT = Context.memo(async () => {
|
|
|
37
37
|
});
|
|
38
38
|
device.on("message", (_topic, buffer) => {
|
|
39
39
|
const fragment = JSON.parse(buffer.toString());
|
|
40
|
+
if (!fragment.id) {
|
|
41
|
+
bus.publish(fragment.type, fragment.properties);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
40
44
|
let pending = fragments.get(fragment.id);
|
|
41
45
|
if (!pending) {
|
|
42
46
|
pending = new Map();
|
package/package.json
CHANGED
package/sst.mjs
CHANGED
|
@@ -2120,11 +2120,26 @@ var init_cloudformation_deployments = __esm({
|
|
|
2120
2120
|
// src/cdk/cloudformation-deployments-wrapper.ts
|
|
2121
2121
|
var cloudformation_deployments_wrapper_exports = {};
|
|
2122
2122
|
__export(cloudformation_deployments_wrapper_exports, {
|
|
2123
|
-
|
|
2123
|
+
publishDeployAssets: () => publishDeployAssets
|
|
2124
2124
|
});
|
|
2125
|
+
import { debug as debug3 } from "aws-cdk/lib/logging.js";
|
|
2126
|
+
import {
|
|
2127
|
+
CloudFormationStack as CloudFormationStack3,
|
|
2128
|
+
TemplateParameters as TemplateParameters2,
|
|
2129
|
+
waitForStackDelete as waitForStackDelete2
|
|
2130
|
+
} from "aws-cdk/lib/api/util/cloudformation.js";
|
|
2125
2131
|
import { ToolkitInfo as ToolkitInfo2 } from "aws-cdk/lib/api/toolkit-info.js";
|
|
2126
|
-
|
|
2127
|
-
|
|
2132
|
+
import { addMetadataAssetsToManifest as addMetadataAssetsToManifest2 } from "aws-cdk/lib/assets.js";
|
|
2133
|
+
import { publishAssets as publishAssets3 } from "aws-cdk/lib/util/asset-publishing.js";
|
|
2134
|
+
import { AssetManifestBuilder as AssetManifestBuilder2 } from "aws-cdk/lib/util/asset-manifest-builder.js";
|
|
2135
|
+
async function publishDeployAssets(sdkProvider, options) {
|
|
2136
|
+
const {
|
|
2137
|
+
deployment,
|
|
2138
|
+
toolkitInfo,
|
|
2139
|
+
stackSdk,
|
|
2140
|
+
resolvedEnvironment,
|
|
2141
|
+
cloudFormationRoleArn
|
|
2142
|
+
} = await useDeployment().get(sdkProvider, options);
|
|
2128
2143
|
await deployment.publishStackAssets(options.stack, toolkitInfo, {
|
|
2129
2144
|
buildAssets: options.buildAssets ?? true,
|
|
2130
2145
|
publishOptions: {
|
|
@@ -2132,26 +2147,130 @@ async function publishAssets3(deployment, options) {
|
|
|
2132
2147
|
parallel: options.assetParallelism
|
|
2133
2148
|
}
|
|
2134
2149
|
});
|
|
2150
|
+
return deployStack2({
|
|
2151
|
+
stack: options.stack,
|
|
2152
|
+
noMonitor: true,
|
|
2153
|
+
resolvedEnvironment,
|
|
2154
|
+
deployName: options.deployName,
|
|
2155
|
+
notificationArns: options.notificationArns,
|
|
2156
|
+
quiet: options.quiet,
|
|
2157
|
+
sdk: stackSdk,
|
|
2158
|
+
sdkProvider,
|
|
2159
|
+
roleArn: cloudFormationRoleArn,
|
|
2160
|
+
reuseAssets: options.reuseAssets,
|
|
2161
|
+
toolkitInfo,
|
|
2162
|
+
tags: options.tags,
|
|
2163
|
+
deploymentMethod: options.deploymentMethod,
|
|
2164
|
+
force: options.force,
|
|
2165
|
+
parameters: options.parameters,
|
|
2166
|
+
usePreviousParameters: options.usePreviousParameters,
|
|
2167
|
+
progress: options.progress,
|
|
2168
|
+
ci: options.ci,
|
|
2169
|
+
rollback: options.rollback,
|
|
2170
|
+
hotswap: options.hotswap,
|
|
2171
|
+
extraUserAgent: options.extraUserAgent,
|
|
2172
|
+
resourcesToImport: options.resourcesToImport,
|
|
2173
|
+
overrideTemplate: options.overrideTemplate,
|
|
2174
|
+
assetParallelism: options.assetParallelism
|
|
2175
|
+
});
|
|
2135
2176
|
}
|
|
2136
|
-
|
|
2177
|
+
async function deployStack2(options) {
|
|
2178
|
+
const stackArtifact = options.stack;
|
|
2179
|
+
const stackEnv = options.resolvedEnvironment;
|
|
2180
|
+
options.sdk.appendCustomUserAgent(options.extraUserAgent);
|
|
2181
|
+
const cfn = options.sdk.cloudFormation();
|
|
2182
|
+
const deployName = options.deployName || stackArtifact.stackName;
|
|
2183
|
+
let cloudFormationStack = await CloudFormationStack3.lookup(cfn, deployName);
|
|
2184
|
+
if (cloudFormationStack.stackStatus.isCreationFailure) {
|
|
2185
|
+
debug3(
|
|
2186
|
+
`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`
|
|
2187
|
+
);
|
|
2188
|
+
await cfn.deleteStack({ StackName: deployName }).promise();
|
|
2189
|
+
const deletedStack = await waitForStackDelete2(cfn, deployName);
|
|
2190
|
+
if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
|
|
2191
|
+
throw new Error(
|
|
2192
|
+
`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`
|
|
2193
|
+
);
|
|
2194
|
+
}
|
|
2195
|
+
cloudFormationStack = CloudFormationStack3.doesNotExist(cfn, deployName);
|
|
2196
|
+
}
|
|
2197
|
+
const legacyAssets = new AssetManifestBuilder2();
|
|
2198
|
+
const assetParams = await addMetadataAssetsToManifest2(
|
|
2199
|
+
stackArtifact,
|
|
2200
|
+
legacyAssets,
|
|
2201
|
+
options.toolkitInfo,
|
|
2202
|
+
options.reuseAssets
|
|
2203
|
+
);
|
|
2204
|
+
const finalParameterValues = { ...options.parameters, ...assetParams };
|
|
2205
|
+
const templateParams = TemplateParameters2.fromTemplate(
|
|
2206
|
+
stackArtifact.template
|
|
2207
|
+
);
|
|
2208
|
+
const stackParams = options.usePreviousParameters ? templateParams.updateExisting(
|
|
2209
|
+
finalParameterValues,
|
|
2210
|
+
cloudFormationStack.parameters
|
|
2211
|
+
) : templateParams.supplyAll(finalParameterValues);
|
|
2212
|
+
const bodyParameter = await makeBodyParameter(
|
|
2213
|
+
stackArtifact,
|
|
2214
|
+
options.resolvedEnvironment,
|
|
2215
|
+
legacyAssets,
|
|
2216
|
+
options.toolkitInfo,
|
|
2217
|
+
options.sdk,
|
|
2218
|
+
options.overrideTemplate
|
|
2219
|
+
);
|
|
2220
|
+
await publishAssets3(
|
|
2221
|
+
legacyAssets.toManifest(stackArtifact.assembly.directory),
|
|
2222
|
+
options.sdkProvider,
|
|
2223
|
+
stackEnv,
|
|
2224
|
+
{
|
|
2225
|
+
parallel: options.assetParallelism
|
|
2226
|
+
}
|
|
2227
|
+
);
|
|
2228
|
+
return {
|
|
2229
|
+
isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== "REVIEW_IN_PROGRESS",
|
|
2230
|
+
params: {
|
|
2231
|
+
StackName: deployName,
|
|
2232
|
+
TemplateBody: bodyParameter.TemplateBody,
|
|
2233
|
+
TemplateURL: bodyParameter.TemplateURL,
|
|
2234
|
+
Parameters: stackParams.apiParameters,
|
|
2235
|
+
Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"],
|
|
2236
|
+
Tags: options.tags
|
|
2237
|
+
}
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
var useDeployment;
|
|
2137
2241
|
var init_cloudformation_deployments_wrapper = __esm({
|
|
2138
2242
|
"src/cdk/cloudformation-deployments-wrapper.ts"() {
|
|
2139
2243
|
"use strict";
|
|
2244
|
+
init_cloudformation_deployments();
|
|
2245
|
+
init_deploy_stack();
|
|
2140
2246
|
init_context();
|
|
2141
|
-
|
|
2247
|
+
useDeployment = Context.memo(() => {
|
|
2142
2248
|
const state2 = /* @__PURE__ */ new Map();
|
|
2143
2249
|
return {
|
|
2144
|
-
async
|
|
2145
|
-
if (state2.has(
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2250
|
+
async get(sdkProvider, options) {
|
|
2251
|
+
if (!state2.has(sdkProvider)) {
|
|
2252
|
+
const deployment = new CloudFormationDeployments({ sdkProvider });
|
|
2253
|
+
const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
|
|
2254
|
+
const toolkitInfo = await ToolkitInfo2.lookup(
|
|
2255
|
+
resolvedEnvironment,
|
|
2256
|
+
stackSdk,
|
|
2257
|
+
options.toolkitStackName
|
|
2258
|
+
);
|
|
2259
|
+
await deployment.validateBootstrapStackVersion(
|
|
2260
|
+
options.stack.stackName,
|
|
2261
|
+
options.stack.requiresBootstrapStackVersion,
|
|
2262
|
+
options.stack.bootstrapStackVersionSsmParameter,
|
|
2263
|
+
toolkitInfo
|
|
2264
|
+
);
|
|
2265
|
+
state2.set(sdkProvider, {
|
|
2266
|
+
deployment,
|
|
2267
|
+
toolkitInfo,
|
|
2268
|
+
stackSdk,
|
|
2269
|
+
resolvedEnvironment,
|
|
2270
|
+
cloudFormationRoleArn
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
return state2.get(sdkProvider);
|
|
2155
2274
|
}
|
|
2156
2275
|
};
|
|
2157
2276
|
});
|
|
@@ -2162,23 +2281,22 @@ var init_cloudformation_deployments_wrapper = __esm({
|
|
|
2162
2281
|
async function publishAssets4(stacks) {
|
|
2163
2282
|
Logger.debug("Publishing assets");
|
|
2164
2283
|
const provider = await useAWSProvider();
|
|
2165
|
-
const {
|
|
2166
|
-
const
|
|
2167
|
-
const deployment = new CloudFormationDeployments2({
|
|
2168
|
-
sdkProvider: provider
|
|
2169
|
-
});
|
|
2284
|
+
const { publishDeployAssets: publishDeployAssets2 } = await Promise.resolve().then(() => (init_cloudformation_deployments_wrapper(), cloudformation_deployments_wrapper_exports));
|
|
2285
|
+
const results = {};
|
|
2170
2286
|
for (const stack of stacks) {
|
|
2171
|
-
await
|
|
2172
|
-
|
|
2287
|
+
const result = await publishDeployAssets2(
|
|
2288
|
+
provider,
|
|
2173
2289
|
{
|
|
2174
2290
|
stack,
|
|
2175
|
-
quiet:
|
|
2291
|
+
quiet: false,
|
|
2176
2292
|
deploymentMethod: {
|
|
2177
2293
|
method: "direct"
|
|
2178
2294
|
}
|
|
2179
2295
|
}
|
|
2180
2296
|
);
|
|
2297
|
+
results[stack.stackName] = result;
|
|
2181
2298
|
}
|
|
2299
|
+
return results;
|
|
2182
2300
|
}
|
|
2183
2301
|
async function deployMany(stacks) {
|
|
2184
2302
|
Logger.debug(
|
|
@@ -2352,7 +2470,7 @@ async function metadata() {
|
|
|
2352
2470
|
credentials
|
|
2353
2471
|
});
|
|
2354
2472
|
const key = `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/`;
|
|
2355
|
-
const
|
|
2473
|
+
const list2 = await s3.send(
|
|
2356
2474
|
new ListObjectsV2Command({
|
|
2357
2475
|
Prefix: key,
|
|
2358
2476
|
Bucket: bootstrap.bucket
|
|
@@ -2360,7 +2478,7 @@ async function metadata() {
|
|
|
2360
2478
|
);
|
|
2361
2479
|
const result = Object.fromEntries(
|
|
2362
2480
|
await Promise.all(
|
|
2363
|
-
|
|
2481
|
+
list2.Contents?.map(async (obj) => {
|
|
2364
2482
|
const stackID = obj.Key?.split("/").pop();
|
|
2365
2483
|
const result2 = await s3.send(
|
|
2366
2484
|
new GetObjectCommand({
|
|
@@ -2372,7 +2490,7 @@ async function metadata() {
|
|
|
2372
2490
|
}) || []
|
|
2373
2491
|
)
|
|
2374
2492
|
);
|
|
2375
|
-
Logger.debug("Fetched metadata from",
|
|
2493
|
+
Logger.debug("Fetched metadata from", list2.KeyCount, "stacks");
|
|
2376
2494
|
return result;
|
|
2377
2495
|
}
|
|
2378
2496
|
async function metadataForStack(stackID) {
|
|
@@ -2409,22 +2527,23 @@ var init_metadata = __esm({
|
|
|
2409
2527
|
init_cache();
|
|
2410
2528
|
init_context();
|
|
2411
2529
|
init_bus();
|
|
2412
|
-
init_stacks();
|
|
2413
2530
|
init_logger();
|
|
2414
2531
|
init_project();
|
|
2415
2532
|
MetadataContext = Context.create(async () => {
|
|
2416
2533
|
const bus = useBus();
|
|
2417
2534
|
const cache = await useCache();
|
|
2418
2535
|
const data2 = await metadata();
|
|
2419
|
-
bus.subscribe("
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2536
|
+
bus.subscribe("stacks.metadata.updated", async () => {
|
|
2537
|
+
const data3 = await metadata();
|
|
2538
|
+
await cache.write(`metadata.json`, JSON.stringify(data3));
|
|
2539
|
+
bus.publish("stacks.metadata", data3);
|
|
2540
|
+
MetadataContext.provide(Promise.resolve(data3));
|
|
2541
|
+
});
|
|
2542
|
+
bus.subscribe("stacks.metadata.deleted", async () => {
|
|
2543
|
+
const data3 = await metadata();
|
|
2544
|
+
await cache.write(`metadata.json`, JSON.stringify(data3));
|
|
2545
|
+
bus.publish("stacks.metadata", data3);
|
|
2546
|
+
MetadataContext.provide(Promise.resolve(data3));
|
|
2428
2547
|
});
|
|
2429
2548
|
return data2;
|
|
2430
2549
|
});
|
|
@@ -3851,7 +3970,9 @@ async function initBootstrap() {
|
|
|
3851
3970
|
}),
|
|
3852
3971
|
new PolicyStatement({
|
|
3853
3972
|
actions: ["iot:Publish"],
|
|
3854
|
-
resources: [
|
|
3973
|
+
resources: [
|
|
3974
|
+
`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
|
|
3975
|
+
]
|
|
3855
3976
|
})
|
|
3856
3977
|
]
|
|
3857
3978
|
});
|
|
@@ -4484,6 +4605,10 @@ var init_iot = __esm({
|
|
|
4484
4605
|
});
|
|
4485
4606
|
device.on("message", (_topic, buffer) => {
|
|
4486
4607
|
const fragment = JSON.parse(buffer.toString());
|
|
4608
|
+
if (!fragment.id) {
|
|
4609
|
+
bus.publish(fragment.type, fragment.properties);
|
|
4610
|
+
return;
|
|
4611
|
+
}
|
|
4487
4612
|
let pending = fragments.get(fragment.id);
|
|
4488
4613
|
if (!pending) {
|
|
4489
4614
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -5706,7 +5831,7 @@ var program = yargs(hideBin(process.argv)).scriptName("sst").option("stage", {
|
|
|
5706
5831
|
}).option("role", {
|
|
5707
5832
|
type: "string",
|
|
5708
5833
|
describe: "ARN of the IAM role to use when invoking AWS"
|
|
5709
|
-
}).group(["stage", "profile", "region", "help"], "Global:").middleware(async (argv) => {
|
|
5834
|
+
}).group(["stage", "profile", "region", "help", "verbose", "role"], "Global:").middleware(async (argv) => {
|
|
5710
5835
|
if (argv.verbose) {
|
|
5711
5836
|
process.env.SST_VERBOSE = "1";
|
|
5712
5837
|
}
|
|
@@ -6181,6 +6306,108 @@ var consoleCommand = async (program2) => program2.command(
|
|
|
6181
6306
|
}
|
|
6182
6307
|
);
|
|
6183
6308
|
|
|
6309
|
+
// src/cli/commands/secrets/get.ts
|
|
6310
|
+
var get = (program2) => program2.command(
|
|
6311
|
+
"get <name>",
|
|
6312
|
+
"Get the value of a secret",
|
|
6313
|
+
(yargs2) => yargs2.positional("name", {
|
|
6314
|
+
type: "string",
|
|
6315
|
+
describe: "Name of the secret",
|
|
6316
|
+
demandOption: true
|
|
6317
|
+
}).option("fallback", {
|
|
6318
|
+
type: "boolean",
|
|
6319
|
+
describe: "Get the fallback value"
|
|
6320
|
+
}),
|
|
6321
|
+
async (args) => {
|
|
6322
|
+
const { red: red3 } = await import("colorette");
|
|
6323
|
+
const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6324
|
+
const { bold: bold2 } = await import("colorette");
|
|
6325
|
+
try {
|
|
6326
|
+
const result = await Config2.getSecret({
|
|
6327
|
+
key: args.name,
|
|
6328
|
+
fallback: args.fallback === true
|
|
6329
|
+
});
|
|
6330
|
+
console.log(bold2(result));
|
|
6331
|
+
} catch {
|
|
6332
|
+
console.log(red3(`${bold2(args.name)} is not set`));
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
);
|
|
6336
|
+
|
|
6337
|
+
// src/cli/commands/secrets/list.ts
|
|
6338
|
+
var list = (program2) => program2.command(
|
|
6339
|
+
"list [format]",
|
|
6340
|
+
"Fetch all the secrets",
|
|
6341
|
+
(yargs2) => yargs2.positional("format", {
|
|
6342
|
+
type: "string",
|
|
6343
|
+
choices: ["table", "env"]
|
|
6344
|
+
}),
|
|
6345
|
+
async (args) => {
|
|
6346
|
+
const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6347
|
+
const { gray } = await import("colorette");
|
|
6348
|
+
const secrets2 = await Config2.secrets();
|
|
6349
|
+
switch (args.format || "table") {
|
|
6350
|
+
case "env":
|
|
6351
|
+
for (const [key, value] of Object.entries(secrets2)) {
|
|
6352
|
+
console.log(`${key}=${value.value || value.fallback}`);
|
|
6353
|
+
}
|
|
6354
|
+
break;
|
|
6355
|
+
case "table":
|
|
6356
|
+
const keys2 = Object.keys(secrets2);
|
|
6357
|
+
const keyLen = Math.max(
|
|
6358
|
+
"Secrets".length,
|
|
6359
|
+
...keys2.map((key) => key.length)
|
|
6360
|
+
);
|
|
6361
|
+
const valueLen = Math.max(
|
|
6362
|
+
"Values".length,
|
|
6363
|
+
...keys2.map(
|
|
6364
|
+
(key) => secrets2[key].value ? secrets2[key].value.length : `${secrets2[key].fallback} (fallback)`.length
|
|
6365
|
+
)
|
|
6366
|
+
);
|
|
6367
|
+
console.log(
|
|
6368
|
+
"\u250C".padEnd(keyLen + 3, "\u2500") + "\u252C" + "".padEnd(valueLen + 2, "\u2500") + "\u2510"
|
|
6369
|
+
);
|
|
6370
|
+
console.log(
|
|
6371
|
+
`\u2502 ${"Secrets".padEnd(keyLen)} \u2502 ${"Values".padEnd(valueLen)} \u2502`
|
|
6372
|
+
);
|
|
6373
|
+
console.log(
|
|
6374
|
+
"\u251C".padEnd(keyLen + 3, "\u2500") + "\u253C" + "".padEnd(valueLen + 2, "\u2500") + "\u2524"
|
|
6375
|
+
);
|
|
6376
|
+
keys2.sort().forEach((key) => {
|
|
6377
|
+
const value = secrets2[key].value ? secrets2[key].value : `${secrets2[key].fallback} ${gray("(fallback)")}`;
|
|
6378
|
+
console.log(
|
|
6379
|
+
`\u2502 ${key.padEnd(keyLen)} \u2502 ${value.padEnd(valueLen)} \u2502`
|
|
6380
|
+
);
|
|
6381
|
+
});
|
|
6382
|
+
console.log(
|
|
6383
|
+
"\u2514".padEnd(keyLen + 3, "\u2500") + "\u2534" + "".padEnd(valueLen + 2, "\u2500") + "\u2518"
|
|
6384
|
+
);
|
|
6385
|
+
break;
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
);
|
|
6389
|
+
|
|
6390
|
+
// src/cli/commands/secrets/remove.ts
|
|
6391
|
+
var remove3 = (program2) => program2.command(
|
|
6392
|
+
"remove <name>",
|
|
6393
|
+
"Remove a secret",
|
|
6394
|
+
(yargs2) => yargs2.positional("name", {
|
|
6395
|
+
describe: "Name of the secret",
|
|
6396
|
+
type: "string",
|
|
6397
|
+
demandOption: true
|
|
6398
|
+
}).option("fallback", {
|
|
6399
|
+
type: "boolean",
|
|
6400
|
+
describe: "Remove the fallback value"
|
|
6401
|
+
}),
|
|
6402
|
+
async (args) => {
|
|
6403
|
+
const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6404
|
+
await Config2.removeSecret({
|
|
6405
|
+
key: args.name,
|
|
6406
|
+
fallback: args.fallback === true
|
|
6407
|
+
});
|
|
6408
|
+
}
|
|
6409
|
+
);
|
|
6410
|
+
|
|
6184
6411
|
// src/cli/commands/secrets/set.ts
|
|
6185
6412
|
var set = (program2) => program2.command(
|
|
6186
6413
|
"set <name> <value>",
|
|
@@ -6223,6 +6450,9 @@ function secrets(program2) {
|
|
|
6223
6450
|
program2.command("secrets", "Manage the secrets in your app", (yargs2) => {
|
|
6224
6451
|
yargs2.demandCommand(1);
|
|
6225
6452
|
set(yargs2);
|
|
6453
|
+
get(yargs2);
|
|
6454
|
+
list(yargs2);
|
|
6455
|
+
remove3(yargs2);
|
|
6226
6456
|
return yargs2;
|
|
6227
6457
|
});
|
|
6228
6458
|
}
|
package/stacks/deploy.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CloudFormationStackArtifact } from "aws-cdk-lib/cx-api";
|
|
2
2
|
import { StackDeploymentResult } from "./monitor.js";
|
|
3
|
-
export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<
|
|
3
|
+
export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<Record<string, any>>;
|
|
4
4
|
export declare function deployMany(stacks: CloudFormationStackArtifact[]): Promise<Record<string, {
|
|
5
5
|
status: string;
|
|
6
6
|
outputs: Record<string, string>;
|
package/stacks/deploy.js
CHANGED
|
@@ -3,23 +3,21 @@ import { useAWSProvider } from "../credentials.js";
|
|
|
3
3
|
import { Logger } from "../logger.js";
|
|
4
4
|
import { isFailed, monitor } from "./monitor.js";
|
|
5
5
|
export async function publishAssets(stacks) {
|
|
6
|
-
// TODO: use memo in cloudformation-deployments.ts
|
|
7
6
|
Logger.debug("Publishing assets");
|
|
8
7
|
const provider = await useAWSProvider();
|
|
9
|
-
const {
|
|
10
|
-
const
|
|
11
|
-
const deployment = new CloudFormationDeployments({
|
|
12
|
-
sdkProvider: provider,
|
|
13
|
-
});
|
|
8
|
+
const { publishDeployAssets } = await import("../cdk/cloudformation-deployments-wrapper.js");
|
|
9
|
+
const results = {};
|
|
14
10
|
for (const stack of stacks) {
|
|
15
|
-
await
|
|
11
|
+
const result = await publishDeployAssets(provider, {
|
|
16
12
|
stack: stack,
|
|
17
|
-
quiet:
|
|
13
|
+
quiet: false,
|
|
18
14
|
deploymentMethod: {
|
|
19
15
|
method: "direct",
|
|
20
16
|
},
|
|
21
17
|
});
|
|
18
|
+
results[stack.stackName] = result;
|
|
22
19
|
}
|
|
20
|
+
return results;
|
|
23
21
|
}
|
|
24
22
|
export async function deployMany(stacks) {
|
|
25
23
|
Logger.debug("Deploying stacks", stacks.map((s) => s.stackName));
|
package/stacks/metadata.js
CHANGED
|
@@ -5,7 +5,6 @@ import { json } from "stream/consumers";
|
|
|
5
5
|
import { useCache } from "../cache.js";
|
|
6
6
|
import { Context } from "../context/context.js";
|
|
7
7
|
import { useBus } from "../bus.js";
|
|
8
|
-
import { Stacks } from "./index.js";
|
|
9
8
|
import { Logger } from "../logger.js";
|
|
10
9
|
import { useProject } from "../project.js";
|
|
11
10
|
export async function metadata() {
|
|
@@ -67,12 +66,14 @@ const MetadataContext = Context.create(async () => {
|
|
|
67
66
|
const bus = useBus();
|
|
68
67
|
const cache = await useCache();
|
|
69
68
|
const data = await metadata();
|
|
70
|
-
bus.subscribe("
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
bus.subscribe("stacks.metadata.updated", async () => {
|
|
70
|
+
const data = await metadata();
|
|
71
|
+
await cache.write(`metadata.json`, JSON.stringify(data));
|
|
72
|
+
bus.publish("stacks.metadata", data);
|
|
73
|
+
MetadataContext.provide(Promise.resolve(data));
|
|
74
|
+
});
|
|
75
|
+
bus.subscribe("stacks.metadata.deleted", async () => {
|
|
76
|
+
const data = await metadata();
|
|
76
77
|
await cache.write(`metadata.json`, JSON.stringify(data));
|
|
77
78
|
bus.publish("stacks.metadata", data);
|
|
78
79
|
MetadataContext.provide(Promise.resolve(data));
|