sst 2.18.4 → 2.19.1
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/cdk/asset-publishing.d.ts +74 -0
- package/cdk/asset-publishing.js +147 -0
- package/cdk/deployments.d.ts +1 -1
- package/cdk/deployments.js +1 -3
- package/cdk-assets/private/asset-handler.d.ts +29 -0
- package/cdk-assets/private/asset-handler.js +1 -0
- package/cdk-assets/private/docker.d.ts +94 -0
- package/cdk-assets/private/docker.js +237 -0
- package/cdk-assets/private/handlers/container-images.d.ts +22 -0
- package/cdk-assets/private/handlers/container-images.js +231 -0
- package/cdk-assets/private/handlers/index.d.ts +3 -0
- package/cdk-assets/private/handlers/index.js +18 -0
- package/cdk-assets/publishing.d.ts +113 -0
- package/cdk-assets/publishing.js +194 -0
- package/cli/commands/dev.js +25 -1
- package/constructs/Function.d.ts +4 -0
- package/constructs/Function.js +43 -11
- package/constructs/SsrSite.js +1 -4
- package/package.json +1 -1
- package/project.d.ts +1 -0
- package/runtime/handlers/container.d.ts +1 -0
- package/runtime/handlers/container.js +124 -0
- package/runtime/handlers.d.ts +4 -0
- package/runtime/handlers.js +1 -0
- package/runtime/workers.js +1 -0
- package/sst.mjs +1222 -319
- package/stacks/synth.js +7 -1
- package/support/bridge/Dockerfile +3 -0
package/constructs/Function.js
CHANGED
|
@@ -12,17 +12,20 @@ import * as functionUrlCors from "./util/functionUrlCors.js";
|
|
|
12
12
|
import url from "url";
|
|
13
13
|
import { useDeferredTasks } from "./deferred_task.js";
|
|
14
14
|
import { useProject } from "../project.js";
|
|
15
|
+
import { VisibleError } from "../error.js";
|
|
15
16
|
import { useRuntimeHandlers } from "../runtime/handlers.js";
|
|
16
17
|
import { createAppContext } from "./context.js";
|
|
17
18
|
import { useWarning } from "./util/warning.js";
|
|
18
|
-
import { Architecture, AssetCode, Code, Function as CDKFunction, FunctionUrlAuthType, LayerVersion, Runtime as CDKRuntime, Tracing, } from "aws-cdk-lib/aws-lambda";
|
|
19
|
+
import { Architecture, AssetCode, Code, Function as CDKFunction, FunctionUrlAuthType, Handler as CDKHandler, LayerVersion, Runtime as CDKRuntime, Tracing, } from "aws-cdk-lib/aws-lambda";
|
|
19
20
|
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
20
21
|
import { Token, Size as CDKSize, Duration as CDKDuration, } from "aws-cdk-lib/core";
|
|
21
22
|
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
22
23
|
import { StringParameter } from "aws-cdk-lib/aws-ssm";
|
|
24
|
+
import { Platform } from "aws-cdk-lib/aws-ecr-assets";
|
|
23
25
|
import { useBootstrap } from "../bootstrap.js";
|
|
24
26
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
25
27
|
const supportedRuntimes = {
|
|
28
|
+
container: CDKRuntime.FROM_IMAGE,
|
|
26
29
|
rust: CDKRuntime.PROVIDED_AL2,
|
|
27
30
|
nodejs: CDKRuntime.NODEJS,
|
|
28
31
|
"nodejs4.3": CDKRuntime.NODEJS_4_3,
|
|
@@ -96,7 +99,7 @@ export class Function extends CDKFunction {
|
|
|
96
99
|
return Architecture.ARM_64;
|
|
97
100
|
if (props.architecture === "x86_64")
|
|
98
101
|
return Architecture.X86_64;
|
|
99
|
-
return
|
|
102
|
+
return Architecture.X86_64;
|
|
100
103
|
})();
|
|
101
104
|
const memorySize = Function.normalizeMemorySize(props.memorySize);
|
|
102
105
|
const diskSize = Function.normalizeDiskSize(props.diskSize);
|
|
@@ -147,17 +150,30 @@ export class Function extends CDKFunction {
|
|
|
147
150
|
}
|
|
148
151
|
super(scope, id, {
|
|
149
152
|
...props,
|
|
153
|
+
...(props.runtime === "container"
|
|
154
|
+
? {
|
|
155
|
+
code: Code.fromAssetImage(path.resolve(__dirname, "../support/bridge"), {
|
|
156
|
+
...(architecture?.dockerPlatform
|
|
157
|
+
? { platform: Platform.custom(architecture.dockerPlatform) }
|
|
158
|
+
: {}),
|
|
159
|
+
}),
|
|
160
|
+
handler: CDKHandler.FROM_IMAGE,
|
|
161
|
+
runtime: CDKRuntime.FROM_IMAGE,
|
|
162
|
+
layers: undefined,
|
|
163
|
+
}
|
|
164
|
+
: {
|
|
165
|
+
runtime: CDKRuntime.NODEJS_16_X,
|
|
166
|
+
code: Code.fromAsset(path.resolve(__dirname, "../support/bridge")),
|
|
167
|
+
handler: "bridge.handler",
|
|
168
|
+
layers: [],
|
|
169
|
+
}),
|
|
150
170
|
architecture,
|
|
151
|
-
code: Code.fromAsset(path.resolve(__dirname, "../support/bridge")),
|
|
152
|
-
handler: "bridge.handler",
|
|
153
171
|
functionName,
|
|
154
|
-
runtime: CDKRuntime.NODEJS_16_X,
|
|
155
172
|
memorySize,
|
|
156
173
|
ephemeralStorageSize: diskSize,
|
|
157
174
|
timeout,
|
|
158
175
|
tracing,
|
|
159
176
|
environment: props.environment,
|
|
160
|
-
layers: [],
|
|
161
177
|
logRetention,
|
|
162
178
|
logRetentionRetryOptions: logRetention && { maxRetries: 100 },
|
|
163
179
|
retryAttempts: 0,
|
|
@@ -186,17 +202,30 @@ export class Function extends CDKFunction {
|
|
|
186
202
|
else {
|
|
187
203
|
super(scope, id, {
|
|
188
204
|
...props,
|
|
205
|
+
...(props.runtime === "container"
|
|
206
|
+
? {
|
|
207
|
+
code: Code.fromAssetImage(props.handler, {
|
|
208
|
+
...(architecture?.dockerPlatform
|
|
209
|
+
? { platform: Platform.custom(architecture.dockerPlatform) }
|
|
210
|
+
: {}),
|
|
211
|
+
}),
|
|
212
|
+
handler: CDKHandler.FROM_IMAGE,
|
|
213
|
+
runtime: CDKRuntime.FROM_IMAGE,
|
|
214
|
+
layers: undefined,
|
|
215
|
+
}
|
|
216
|
+
: {
|
|
217
|
+
code: Code.fromInline("export function placeholder() {}"),
|
|
218
|
+
handler: "index.placeholder",
|
|
219
|
+
runtime: CDKRuntime.NODEJS_16_X,
|
|
220
|
+
layers: Function.buildLayers(scope, id, props),
|
|
221
|
+
}),
|
|
189
222
|
architecture,
|
|
190
|
-
code: Code.fromInline("export function placeholder() {}"),
|
|
191
|
-
handler: "index.placeholder",
|
|
192
223
|
functionName,
|
|
193
|
-
runtime: CDKRuntime.NODEJS_16_X,
|
|
194
224
|
memorySize,
|
|
195
225
|
ephemeralStorageSize: diskSize,
|
|
196
226
|
timeout,
|
|
197
227
|
tracing,
|
|
198
228
|
environment: props.environment,
|
|
199
|
-
layers: Function.buildLayers(scope, id, props),
|
|
200
229
|
logRetention,
|
|
201
230
|
logRetentionRetryOptions: logRetention && { maxRetries: 100 },
|
|
202
231
|
});
|
|
@@ -204,11 +233,14 @@ export class Function extends CDKFunction {
|
|
|
204
233
|
// Build function
|
|
205
234
|
const result = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
206
235
|
if (result.type === "error") {
|
|
207
|
-
throw new
|
|
236
|
+
throw new VisibleError([
|
|
208
237
|
`Failed to build function "${props.handler}"`,
|
|
209
238
|
...result.errors,
|
|
210
239
|
].join("\n"));
|
|
211
240
|
}
|
|
241
|
+
// No need to update code if runtime is container
|
|
242
|
+
if (props.runtime === "container")
|
|
243
|
+
return;
|
|
212
244
|
// Update code
|
|
213
245
|
const cfnFunction = this.node.defaultChild;
|
|
214
246
|
const code = AssetCode.fromAsset(result.out);
|
package/constructs/SsrSite.js
CHANGED
|
@@ -877,9 +877,7 @@ function handler(event) {
|
|
|
877
877
|
generateBuildId() {
|
|
878
878
|
// We will generate a hash based on the contents of the "public" folder
|
|
879
879
|
// which will be used to indicate if we need to invalidate our CloudFront
|
|
880
|
-
// cache.
|
|
881
|
-
// filenames according to their content we can ignore the browser build
|
|
882
|
-
// files.
|
|
880
|
+
// cache.
|
|
883
881
|
// The below options are needed to support following symlinks when building zip files:
|
|
884
882
|
// - nodir: This will prevent symlinks themselves from being copied into the zip.
|
|
885
883
|
// - follow: This will follow symlinks and copy the files within.
|
|
@@ -887,7 +885,6 @@ function handler(event) {
|
|
|
887
885
|
dot: true,
|
|
888
886
|
nodir: true,
|
|
889
887
|
follow: true,
|
|
890
|
-
ignore: [`${this.buildConfig.clientBuildVersionedSubDir}/**`],
|
|
891
888
|
cwd: path.resolve(this.props.path, this.buildConfig.clientBuildOutputDir),
|
|
892
889
|
};
|
|
893
890
|
const files = glob.sync("**", globOptions);
|
package/package.json
CHANGED
package/project.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useContainerHandler: () => Promise<void>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { useRuntimeHandlers } from "../handlers.js";
|
|
2
|
+
import { useRuntimeWorkers } from "../workers.js";
|
|
3
|
+
import { Context } from "../../context/context.js";
|
|
4
|
+
import { VisibleError } from "../../error.js";
|
|
5
|
+
import { spawn } from "child_process";
|
|
6
|
+
import { useRuntimeServerConfig } from "../server.js";
|
|
7
|
+
import { isChild } from "../../util/fs.js";
|
|
8
|
+
import { execAsync } from "../../util/process.js";
|
|
9
|
+
export const useContainerHandler = Context.memo(async () => {
|
|
10
|
+
const workers = await useRuntimeWorkers();
|
|
11
|
+
const server = await useRuntimeServerConfig();
|
|
12
|
+
const handlers = useRuntimeHandlers();
|
|
13
|
+
const containers = new Map();
|
|
14
|
+
const sources = new Map();
|
|
15
|
+
handlers.register({
|
|
16
|
+
shouldBuild: (input) => {
|
|
17
|
+
const parent = sources.get(input.functionID);
|
|
18
|
+
if (!parent)
|
|
19
|
+
return false;
|
|
20
|
+
return isChild(parent, input.file);
|
|
21
|
+
},
|
|
22
|
+
canHandle: (input) => input.startsWith("container"),
|
|
23
|
+
startWorker: async (input) => {
|
|
24
|
+
const name = `sst-workerID-${input.workerID}-${Date.now()}`;
|
|
25
|
+
const proc = spawn("docker", [
|
|
26
|
+
"run",
|
|
27
|
+
"--rm",
|
|
28
|
+
"--network=host",
|
|
29
|
+
`--name=${name}`,
|
|
30
|
+
...Object.entries({
|
|
31
|
+
...input.environment,
|
|
32
|
+
IS_LOCAL: "true",
|
|
33
|
+
AWS_LAMBDA_RUNTIME_API: `host.docker.internal:${server.port}/${input.workerID}`,
|
|
34
|
+
})
|
|
35
|
+
.map(([key, value]) => ["-e", `${key}=${value}`])
|
|
36
|
+
.flat(),
|
|
37
|
+
`sst-dev:${input.functionID}`,
|
|
38
|
+
], {
|
|
39
|
+
env: {
|
|
40
|
+
...process.env,
|
|
41
|
+
},
|
|
42
|
+
cwd: input.out,
|
|
43
|
+
});
|
|
44
|
+
proc.on("exit", () => {
|
|
45
|
+
workers.exited(input.workerID);
|
|
46
|
+
});
|
|
47
|
+
proc.stdout.on("data", (data) => {
|
|
48
|
+
workers.stdout(input.workerID, data.toString());
|
|
49
|
+
});
|
|
50
|
+
proc.stderr.on("data", (data) => {
|
|
51
|
+
workers.stdout(input.workerID, data.toString());
|
|
52
|
+
});
|
|
53
|
+
containers.set(input.workerID, name);
|
|
54
|
+
},
|
|
55
|
+
stopWorker: async (workerID) => {
|
|
56
|
+
const name = containers.get(workerID);
|
|
57
|
+
if (name) {
|
|
58
|
+
try {
|
|
59
|
+
// note:
|
|
60
|
+
// - calling `docker kill` kills the docker process much faster than `docker stop`
|
|
61
|
+
// - process.kill() does not work on docker processes
|
|
62
|
+
await execAsync(`docker kill ${name}`, {
|
|
63
|
+
env: {
|
|
64
|
+
...process.env,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (ex) {
|
|
69
|
+
console.error(ex);
|
|
70
|
+
throw new VisibleError(`Could not stop docker container ${name}`);
|
|
71
|
+
}
|
|
72
|
+
containers.delete(workerID);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
build: async (input) => {
|
|
76
|
+
const project = input.props.handler;
|
|
77
|
+
sources.set(input.functionID, project);
|
|
78
|
+
if (input.mode === "start") {
|
|
79
|
+
try {
|
|
80
|
+
const result = await execAsync(`docker build -t sst-dev:${input.functionID} .`, {
|
|
81
|
+
cwd: project,
|
|
82
|
+
env: {
|
|
83
|
+
...process.env,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (ex) {
|
|
88
|
+
return {
|
|
89
|
+
type: "error",
|
|
90
|
+
errors: [String(ex)],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (input.mode === "deploy") {
|
|
95
|
+
try {
|
|
96
|
+
const platform = input.props.architecture === "arm_64"
|
|
97
|
+
? "linux/arm64"
|
|
98
|
+
: "linux/amd64";
|
|
99
|
+
await execAsync([
|
|
100
|
+
`docker build`,
|
|
101
|
+
`-t sst-build:${input.functionID}`,
|
|
102
|
+
`--platform ${platform}`,
|
|
103
|
+
`.`,
|
|
104
|
+
].join(" "), {
|
|
105
|
+
cwd: project,
|
|
106
|
+
env: {
|
|
107
|
+
...process.env,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (ex) {
|
|
112
|
+
return {
|
|
113
|
+
type: "error",
|
|
114
|
+
errors: [String(ex)],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
type: "success",
|
|
120
|
+
handler: "not required for container",
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
});
|
package/runtime/handlers.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { FunctionProps } from "../constructs/Function.js";
|
|
2
2
|
declare module "../bus.js" {
|
|
3
3
|
interface Events {
|
|
4
|
+
"function.build.started": {
|
|
5
|
+
functionID: string;
|
|
6
|
+
};
|
|
4
7
|
"function.build.success": {
|
|
5
8
|
functionID: string;
|
|
6
9
|
};
|
|
@@ -19,6 +22,7 @@ interface BuildInput {
|
|
|
19
22
|
interface StartWorkerInput {
|
|
20
23
|
url: string;
|
|
21
24
|
workerID: string;
|
|
25
|
+
functionID: string;
|
|
22
26
|
environment: Record<string, string>;
|
|
23
27
|
out: string;
|
|
24
28
|
handler: string;
|
package/runtime/handlers.js
CHANGED
|
@@ -34,6 +34,7 @@ export const useRuntimeHandlers = Context.memo(() => {
|
|
|
34
34
|
const out = path.join(project.paths.artifacts, functionID);
|
|
35
35
|
await fs.rm(out, { recursive: true, force: true });
|
|
36
36
|
await fs.mkdir(out, { recursive: true });
|
|
37
|
+
bus.publish("function.build.started", { functionID });
|
|
37
38
|
if (func.hooks?.beforeBuild)
|
|
38
39
|
await func.hooks.beforeBuild(func, out);
|
|
39
40
|
const built = await handler.build({
|
package/runtime/workers.js
CHANGED
|
@@ -43,6 +43,7 @@ export const useRuntimeWorkers = Context.memo(async () => {
|
|
|
43
43
|
await handler.startWorker({
|
|
44
44
|
...build,
|
|
45
45
|
workerID: evt.properties.workerID,
|
|
46
|
+
functionID: evt.properties.functionID,
|
|
46
47
|
environment: evt.properties.env,
|
|
47
48
|
url: `${server.url}/${evt.properties.workerID}/${server.API_VERSION}`,
|
|
48
49
|
runtime: props.runtime,
|