sst 2.0.17 → 2.0.19
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/cli/commands/secrets/set.js +3 -1
- package/constructs/Function.d.ts +1 -0
- package/constructs/Function.js +1 -0
- package/constructs/WebSocketApi.d.ts +1 -0
- package/constructs/WebSocketApi.js +38 -0
- package/package.json +3 -1
- package/runtime/handlers/rust.d.ts +1 -0
- package/runtime/handlers/rust.js +96 -0
- package/runtime/server.js +9 -2
- package/sst.mjs +218 -96
- package/stacks/app-metadata.js +4 -6
- package/stacks/metadata.js +8 -11
- package/stacks/synth.js +2 -0
- package/support/custom-resources/index.mjs +50301 -0
|
@@ -25,5 +25,7 @@ export const set = (program) => program.command("set <name> <value>", "Set the v
|
|
|
25
25
|
setting.succeed();
|
|
26
26
|
const restarting = createSpinner(` Restarting all functions using ${blue(args.name)}...`).start();
|
|
27
27
|
const count = await Config.restart(args.name);
|
|
28
|
-
restarting.succeed(
|
|
28
|
+
restarting.succeed(count === 1
|
|
29
|
+
? ` Restarted ${count} function`
|
|
30
|
+
: ` Restarted ${count} functions`);
|
|
29
31
|
});
|
package/constructs/Function.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Duration } from "./util/duration.js";
|
|
|
10
10
|
import { Permissions } from "./util/permission.js";
|
|
11
11
|
import * as functionUrlCors from "./util/functionUrlCors.js";
|
|
12
12
|
declare const supportedRuntimes: {
|
|
13
|
+
rust: cdk.aws_lambda.Runtime;
|
|
13
14
|
nodejs: cdk.aws_lambda.Runtime;
|
|
14
15
|
"nodejs4.3": cdk.aws_lambda.Runtime;
|
|
15
16
|
"nodejs6.10": cdk.aws_lambda.Runtime;
|
package/constructs/Function.js
CHANGED
|
@@ -21,6 +21,7 @@ import { useRuntimeHandlers } from "../runtime/handlers.js";
|
|
|
21
21
|
import { createAppContext } from "./context.js";
|
|
22
22
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
23
23
|
const supportedRuntimes = {
|
|
24
|
+
rust: lambda.Runtime.PROVIDED_AL2,
|
|
24
25
|
nodejs: lambda.Runtime.NODEJS,
|
|
25
26
|
"nodejs4.3": lambda.Runtime.NODEJS_4_3,
|
|
26
27
|
"nodejs6.10": lambda.Runtime.NODEJS_6_10,
|
|
@@ -354,6 +354,7 @@ export declare class WebSocketApi extends Construct implements SSTConstruct {
|
|
|
354
354
|
};
|
|
355
355
|
private createWebSocketApi;
|
|
356
356
|
private createWebSocketStage;
|
|
357
|
+
private createCloudWatchRole;
|
|
357
358
|
private addAuthorizer;
|
|
358
359
|
private addRoute;
|
|
359
360
|
private buildRouteAuth;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
+
import { CustomResource } from "aws-cdk-lib";
|
|
2
3
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
3
4
|
import * as apig from "@aws-cdk/aws-apigatewayv2-alpha";
|
|
4
5
|
import * as apigAuthorizers from "@aws-cdk/aws-apigatewayv2-authorizers-alpha";
|
|
5
6
|
import * as apigIntegrations from "@aws-cdk/aws-apigatewayv2-integrations-alpha";
|
|
7
|
+
import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
6
8
|
import { Stack } from "./Stack.js";
|
|
7
9
|
import { getFunctionRef, isCDKConstruct } from "./Construct.js";
|
|
8
10
|
import { Function as Fn, } from "./Function.js";
|
|
@@ -258,7 +260,10 @@ export class WebSocketApi extends Construct {
|
|
|
258
260
|
};
|
|
259
261
|
this._customDomainUrl = `wss://${customDomainData.url}`;
|
|
260
262
|
}
|
|
263
|
+
// Create CloudWatch Role
|
|
264
|
+
const customResource = this.createCloudWatchRole();
|
|
261
265
|
// Create stage
|
|
266
|
+
// note: create the CloudWatch role before creating the Api
|
|
262
267
|
this.cdk.webSocketStage = new apig.WebSocketStage(this, "Stage", {
|
|
263
268
|
webSocketApi: this.cdk.webSocketApi,
|
|
264
269
|
stageName: this.node.root.stage,
|
|
@@ -266,10 +271,43 @@ export class WebSocketApi extends Construct {
|
|
|
266
271
|
domainMapping,
|
|
267
272
|
...webSocketStageProps,
|
|
268
273
|
});
|
|
274
|
+
this.cdk.webSocketStage.node.addDependency(customResource);
|
|
269
275
|
// Configure Access Log
|
|
270
276
|
this.cdk.accessLogGroup = apigV2AccessLog.buildAccessLogData(this, accessLog, this.cdk.webSocketStage, true);
|
|
271
277
|
}
|
|
272
278
|
}
|
|
279
|
+
createCloudWatchRole() {
|
|
280
|
+
const stack = Stack.of(this);
|
|
281
|
+
const roleName = "apigateway-cloudwatch-logs-role";
|
|
282
|
+
const roleArn = `arn:${stack.partition}:iam::${stack.account}:role/${roleName}`;
|
|
283
|
+
const policy = new Policy(this, "APIGatewayCloudWatchRolePolicy", {
|
|
284
|
+
statements: [
|
|
285
|
+
new PolicyStatement({
|
|
286
|
+
effect: Effect.ALLOW,
|
|
287
|
+
actions: ["apigateway:GET", "apigateway:PATCH"],
|
|
288
|
+
resources: [
|
|
289
|
+
`arn:${stack.partition}:apigateway:${stack.region}::/account`,
|
|
290
|
+
],
|
|
291
|
+
}),
|
|
292
|
+
new PolicyStatement({
|
|
293
|
+
effect: Effect.ALLOW,
|
|
294
|
+
actions: ["iam:CreateRole", "iam:PassRole", "iam:AttachRolePolicy"],
|
|
295
|
+
resources: [roleArn],
|
|
296
|
+
}),
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
stack.customResourceHandler.role?.attachInlinePolicy(policy);
|
|
300
|
+
const resource = new CustomResource(this, "APIGatewayCloudWatchRole", {
|
|
301
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
302
|
+
resourceType: "Custom::APIGatewayCloudWatchRole",
|
|
303
|
+
properties: {
|
|
304
|
+
roleName,
|
|
305
|
+
roleArn,
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
resource.node.addDependency(policy);
|
|
309
|
+
return resource;
|
|
310
|
+
}
|
|
273
311
|
addAuthorizer() {
|
|
274
312
|
const { authorizer } = this.props;
|
|
275
313
|
if (!authorizer || authorizer === "none") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sst",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.19",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sst": "cli/sst.js"
|
|
6
6
|
},
|
|
@@ -29,8 +29,10 @@
|
|
|
29
29
|
"@aws-cdk/cloudformation-diff": "2.62.2",
|
|
30
30
|
"@aws-cdk/cx-api": "2.62.2",
|
|
31
31
|
"@aws-cdk/region-info": "2.62.2",
|
|
32
|
+
"@aws-sdk/client-api-gateway": "3.208.0",
|
|
32
33
|
"@aws-sdk/client-cloudformation": "3.208.0",
|
|
33
34
|
"@aws-sdk/client-cloudfront": "3.208.0",
|
|
35
|
+
"@aws-sdk/client-iam": "3.208.0",
|
|
34
36
|
"@aws-sdk/client-iot": "3.208.0",
|
|
35
37
|
"@aws-sdk/client-iot-data-plane": "3.208.0",
|
|
36
38
|
"@aws-sdk/client-lambda": "3.208.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useRustHandler: () => Promise<void>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import { useRuntimeHandlers } from "../handlers.js";
|
|
4
|
+
import { useRuntimeWorkers } from "../workers.js";
|
|
5
|
+
import { Context } from "../../context/context.js";
|
|
6
|
+
import { VisibleError } from "../../error.js";
|
|
7
|
+
import { exec, spawn } from "child_process";
|
|
8
|
+
import { promisify } from "util";
|
|
9
|
+
import { useRuntimeServerConfig } from "../server.js";
|
|
10
|
+
import { findAbove, isChild } from "../../util/fs.js";
|
|
11
|
+
const execAsync = promisify(exec);
|
|
12
|
+
export const useRustHandler = Context.memo(async () => {
|
|
13
|
+
const workers = await useRuntimeWorkers();
|
|
14
|
+
const server = await useRuntimeServerConfig();
|
|
15
|
+
const handlers = useRuntimeHandlers();
|
|
16
|
+
const processes = new Map();
|
|
17
|
+
const sources = new Map();
|
|
18
|
+
const handlerName = process.platform === "win32" ? `handler.exe` : `handler`;
|
|
19
|
+
handlers.register({
|
|
20
|
+
shouldBuild: (input) => {
|
|
21
|
+
if (!input.file.endsWith(".rs"))
|
|
22
|
+
return false;
|
|
23
|
+
const parent = sources.get(input.functionID);
|
|
24
|
+
if (!parent)
|
|
25
|
+
return false;
|
|
26
|
+
const result = isChild(parent, input.file);
|
|
27
|
+
return result;
|
|
28
|
+
},
|
|
29
|
+
canHandle: (input) => input.startsWith("rust"),
|
|
30
|
+
startWorker: async (input) => {
|
|
31
|
+
const proc = spawn(path.join(input.out, handlerName), {
|
|
32
|
+
env: {
|
|
33
|
+
...process.env,
|
|
34
|
+
...input.environment,
|
|
35
|
+
IS_LOCAL: "true",
|
|
36
|
+
RUST_BACKTRACE: "1",
|
|
37
|
+
AWS_LAMBDA_RUNTIME_API: `http://localhost:${server.port}/${input.workerID}`,
|
|
38
|
+
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: "1024",
|
|
39
|
+
},
|
|
40
|
+
cwd: input.out,
|
|
41
|
+
});
|
|
42
|
+
proc.on("exit", () => workers.exited(input.workerID));
|
|
43
|
+
proc.stdout.on("data", (data) => {
|
|
44
|
+
workers.stdout(input.workerID, data.toString());
|
|
45
|
+
});
|
|
46
|
+
proc.stderr.on("data", (data) => {
|
|
47
|
+
workers.stdout(input.workerID, data.toString());
|
|
48
|
+
});
|
|
49
|
+
processes.set(input.workerID, proc);
|
|
50
|
+
},
|
|
51
|
+
stopWorker: async (workerID) => {
|
|
52
|
+
const proc = processes.get(workerID);
|
|
53
|
+
if (proc) {
|
|
54
|
+
proc.kill();
|
|
55
|
+
processes.delete(workerID);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
build: async (input) => {
|
|
59
|
+
const parsed = path.parse(input.props.handler);
|
|
60
|
+
const project = await findAbove(parsed.dir, "Cargo.toml");
|
|
61
|
+
sources.set(input.functionID, project);
|
|
62
|
+
if (input.mode === "start") {
|
|
63
|
+
try {
|
|
64
|
+
await execAsync(`cargo build --bin ${parsed.name}`, {
|
|
65
|
+
cwd: project,
|
|
66
|
+
env: {
|
|
67
|
+
...process.env,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
await fs.cp(path.join(project, `target/debug`, parsed.name), path.join(input.out, "handler"));
|
|
71
|
+
}
|
|
72
|
+
catch (ex) {
|
|
73
|
+
throw new VisibleError("Failed to build");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (input.mode === "deploy") {
|
|
77
|
+
try {
|
|
78
|
+
await execAsync(`cargo lambda build --release --bin ${parsed.name}`, {
|
|
79
|
+
cwd: project,
|
|
80
|
+
env: {
|
|
81
|
+
...process.env,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
await fs.cp(path.join(project, `target/lambda/`, parsed.name, "bootstrap"), path.join(input.out, "bootstrap"));
|
|
85
|
+
}
|
|
86
|
+
catch (ex) {
|
|
87
|
+
throw new VisibleError("Failed to build");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
type: "success",
|
|
92
|
+
handler: "handler",
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
});
|
package/runtime/server.js
CHANGED
|
@@ -74,15 +74,22 @@ export const useRuntimeServer = Context.memo(async () => {
|
|
|
74
74
|
"Lambda-Runtime-Deadline-Ms": payload.deadline,
|
|
75
75
|
"Lambda-Runtime-Invoked-Function-Arn": payload.context.invokedFunctionArn,
|
|
76
76
|
"Lambda-Runtime-Client-Context": JSON.stringify(payload.context.clientContext || {}),
|
|
77
|
-
|
|
77
|
+
...(payload.context.identity
|
|
78
|
+
? {
|
|
79
|
+
"Lambda-Runtime-Cognito-Identity": JSON.stringify(payload.context.identity),
|
|
80
|
+
}
|
|
81
|
+
: {}),
|
|
78
82
|
});
|
|
79
83
|
res.json(payload.event);
|
|
80
84
|
});
|
|
81
85
|
app.post(`/:workerID/${cfg.API_VERSION}/runtime/invocation/:awsRequestId/response`, express.json({
|
|
82
86
|
strict: false,
|
|
83
|
-
type
|
|
87
|
+
type() {
|
|
88
|
+
return true;
|
|
89
|
+
},
|
|
84
90
|
limit: "10mb",
|
|
85
91
|
}), (req, res) => {
|
|
92
|
+
console.log(JSON.stringify(req.body, null, 4));
|
|
86
93
|
Logger.debug("Worker", req.params.workerID, "got response", req.body);
|
|
87
94
|
const worker = workers.fromID(req.params.workerID);
|
|
88
95
|
bus.publish("function.success", {
|