sst 2.20.1 → 2.21.0
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/Function.d.ts +19 -1
- package/constructs/Job.d.ts +32 -7
- package/constructs/Job.js +148 -99
- package/constructs/util/permission.js +1 -1
- package/node/job/index.d.ts +4 -1
- package/node/job/index.js +17 -6
- package/package.json +1 -1
- package/runtime/handlers/container.js +158 -32
- package/runtime/handlers.d.ts +1 -1
- package/sst.mjs +167 -41
- package/support/{job-invoker → job-manager}/index.mjs +14281 -27
package/constructs/Function.d.ts
CHANGED
|
@@ -79,8 +79,9 @@ export interface FunctionProps extends Omit<FunctionOptions, "functionName" | "m
|
|
|
79
79
|
*/
|
|
80
80
|
python?: PythonProps;
|
|
81
81
|
/**
|
|
82
|
-
* Used to configure
|
|
82
|
+
* Used to configure container function properties
|
|
83
83
|
*/
|
|
84
|
+
container?: ContainerProps;
|
|
84
85
|
/**
|
|
85
86
|
* Hooks to run before and after function builds
|
|
86
87
|
*/
|
|
@@ -507,6 +508,23 @@ export interface JavaProps {
|
|
|
507
508
|
*/
|
|
508
509
|
experimentalUseProvidedRuntime?: "provided" | "provided.al2";
|
|
509
510
|
}
|
|
511
|
+
export interface ContainerProps {
|
|
512
|
+
/**
|
|
513
|
+
* Configure docker build options
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* ```js
|
|
517
|
+
* container: {
|
|
518
|
+
* docker: {
|
|
519
|
+
* cmd: ["executable", "param1", "param2"]
|
|
520
|
+
* }
|
|
521
|
+
* }
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
docker: {
|
|
525
|
+
cmd?: string[];
|
|
526
|
+
};
|
|
527
|
+
}
|
|
510
528
|
/**
|
|
511
529
|
* Used to configure additional files to copy into the function bundle
|
|
512
530
|
*
|
package/constructs/Job.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
+
import { Function as CdkFunction } from "aws-cdk-lib/aws-lambda";
|
|
2
3
|
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
3
4
|
import { SSTConstruct } from "./Construct.js";
|
|
4
|
-
import {
|
|
5
|
+
import { NodeJSProps, FunctionCopyFilesProps } from "./Function.js";
|
|
5
6
|
import { Duration } from "./util/duration.js";
|
|
6
7
|
import { Permissions } from "./util/permission.js";
|
|
7
8
|
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
@@ -9,7 +10,25 @@ import { ISecurityGroup, IVpc, SubnetSelection } from "aws-cdk-lib/aws-ec2";
|
|
|
9
10
|
export type JobMemorySize = "3 GB" | "7 GB" | "15 GB" | "145 GB";
|
|
10
11
|
export interface JobNodeJSProps extends NodeJSProps {
|
|
11
12
|
}
|
|
13
|
+
export interface JobContainerProps {
|
|
14
|
+
/**
|
|
15
|
+
* Configure docker build options
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```js
|
|
19
|
+
* container: {
|
|
20
|
+
* docker: {
|
|
21
|
+
* cmd: ["executable", "param1", "param2"]
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
docker: {
|
|
27
|
+
cmd: string[];
|
|
28
|
+
};
|
|
29
|
+
}
|
|
12
30
|
export interface JobProps {
|
|
31
|
+
runtime?: "nodejs" | "container";
|
|
13
32
|
/**
|
|
14
33
|
* Path to the entry point and handler function. Of the format:
|
|
15
34
|
* `/path/to/file.function`.
|
|
@@ -65,6 +84,10 @@ export interface JobProps {
|
|
|
65
84
|
* Used to configure nodejs function properties
|
|
66
85
|
*/
|
|
67
86
|
nodejs?: JobNodeJSProps;
|
|
87
|
+
/**
|
|
88
|
+
* Used to configure container properties
|
|
89
|
+
*/
|
|
90
|
+
container?: JobContainerProps;
|
|
68
91
|
/**
|
|
69
92
|
* Can be used to disable Live Lambda Development when using `sst start`. Useful for things like Custom Resources that need to execute during deployment.
|
|
70
93
|
*
|
|
@@ -204,10 +227,10 @@ export interface JobProps {
|
|
|
204
227
|
*/
|
|
205
228
|
export declare class Job extends Construct implements SSTConstruct {
|
|
206
229
|
readonly id: string;
|
|
207
|
-
private readonly localId;
|
|
208
230
|
private readonly props;
|
|
209
231
|
private readonly job;
|
|
210
|
-
readonly
|
|
232
|
+
private readonly liveDevJob?;
|
|
233
|
+
readonly _jobManager: CdkFunction;
|
|
211
234
|
constructor(scope: Construct, id: string, props: JobProps);
|
|
212
235
|
getConstructMetadata(): {
|
|
213
236
|
type: "Job";
|
|
@@ -246,15 +269,17 @@ export declare class Job extends Construct implements SSTConstruct {
|
|
|
246
269
|
* ```
|
|
247
270
|
*/
|
|
248
271
|
addEnvironment(name: string, value: string): void;
|
|
249
|
-
private
|
|
272
|
+
private createCodeBuildJob;
|
|
273
|
+
private createLiveDevJob;
|
|
250
274
|
private createLogRetention;
|
|
251
275
|
private buildCodeBuildProjectCode;
|
|
252
|
-
private
|
|
253
|
-
private createLocalInvoker;
|
|
254
|
-
private createCodeBuildInvoker;
|
|
276
|
+
private createJobManager;
|
|
255
277
|
private bindForCodeBuild;
|
|
256
278
|
private attachPermissionsForCodeBuild;
|
|
257
279
|
private addEnvironmentForCodeBuild;
|
|
280
|
+
private validateContainerProps;
|
|
258
281
|
private normalizeMemorySize;
|
|
259
282
|
private normalizeTimeout;
|
|
283
|
+
private convertJobRuntimeToFunctionRuntime;
|
|
284
|
+
private convertJobContainerToFunctionContainer;
|
|
260
285
|
}
|
package/constructs/Job.js
CHANGED
|
@@ -2,8 +2,9 @@ import url from "url";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs/promises";
|
|
4
4
|
import { Construct } from "constructs";
|
|
5
|
+
import { Duration as CdkDuration } from "aws-cdk-lib/core";
|
|
5
6
|
import { PolicyStatement, Effect } from "aws-cdk-lib/aws-iam";
|
|
6
|
-
import { AssetCode } from "aws-cdk-lib/aws-lambda";
|
|
7
|
+
import { AssetCode, Code, Runtime, Function as CdkFunction, } from "aws-cdk-lib/aws-lambda";
|
|
7
8
|
import { Project, LinuxBuildImage, BuildSpec, ComputeType, } from "aws-cdk-lib/aws-codebuild";
|
|
8
9
|
import { RetentionDays, LogRetention } from "aws-cdk-lib/aws-logs";
|
|
9
10
|
import { Stack } from "./Stack.js";
|
|
@@ -14,6 +15,7 @@ import { bindEnvironment, bindPermissions, getReferencedSecrets, } from "./util/
|
|
|
14
15
|
import { useDeferredTasks } from "./deferred_task.js";
|
|
15
16
|
import { useProject } from "../project.js";
|
|
16
17
|
import { useRuntimeHandlers } from "../runtime/handlers.js";
|
|
18
|
+
import { Platform } from "aws-cdk-lib/aws-ecr-assets";
|
|
17
19
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
18
20
|
/////////////////////
|
|
19
21
|
// Construct
|
|
@@ -34,43 +36,41 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
|
34
36
|
*/
|
|
35
37
|
export class Job extends Construct {
|
|
36
38
|
id;
|
|
37
|
-
localId;
|
|
38
39
|
props;
|
|
39
40
|
job;
|
|
40
|
-
|
|
41
|
+
liveDevJob;
|
|
42
|
+
_jobManager;
|
|
41
43
|
constructor(scope, id, props) {
|
|
42
44
|
super(scope, props.cdk?.id || id);
|
|
43
45
|
const app = this.node.root;
|
|
44
46
|
const stack = Stack.of(scope);
|
|
45
47
|
this.id = id;
|
|
46
48
|
this.props = props;
|
|
47
|
-
useFunctions().add(this.node.addr, {
|
|
48
|
-
...props,
|
|
49
|
-
runtime: "nodejs16.x",
|
|
50
|
-
});
|
|
51
|
-
this.localId = path.posix
|
|
52
|
-
.join(scope.node.path, id)
|
|
53
|
-
.replace(/\$/g, "-")
|
|
54
|
-
.replace(/\//g, "-")
|
|
55
|
-
.replace(/\./g, "-");
|
|
56
49
|
const isLiveDevEnabled = app.mode === "dev" && (this.props.enableLiveDev === false ? false : true);
|
|
57
|
-
|
|
58
|
-
this.
|
|
50
|
+
// TODO add test
|
|
51
|
+
this.validateContainerProps();
|
|
52
|
+
this.job = this.createCodeBuildJob();
|
|
59
53
|
if (!stack.isActive) {
|
|
60
|
-
this.
|
|
54
|
+
this._jobManager = this.createJobManager();
|
|
61
55
|
}
|
|
62
56
|
else if (isLiveDevEnabled) {
|
|
63
|
-
this.
|
|
57
|
+
this.liveDevJob = this.createLiveDevJob();
|
|
58
|
+
this._jobManager = this.createJobManager();
|
|
64
59
|
}
|
|
65
60
|
else {
|
|
66
|
-
this.
|
|
61
|
+
this._jobManager = this.createJobManager();
|
|
67
62
|
this.buildCodeBuildProjectCode();
|
|
68
63
|
}
|
|
64
|
+
this.createLogRetention();
|
|
69
65
|
this.attachPermissions(props.permissions || []);
|
|
70
66
|
this.bind(props.bind || []);
|
|
71
67
|
Object.entries(props.environment || {}).forEach(([key, value]) => {
|
|
72
68
|
this.addEnvironment(key, value);
|
|
73
69
|
});
|
|
70
|
+
useFunctions().add(this.node.addr, {
|
|
71
|
+
...props,
|
|
72
|
+
runtime: this.convertJobRuntimeToFunctionRuntime(),
|
|
73
|
+
});
|
|
74
74
|
}
|
|
75
75
|
getConstructMetadata() {
|
|
76
76
|
return {
|
|
@@ -87,11 +87,11 @@ export class Job extends Construct {
|
|
|
87
87
|
variables: {
|
|
88
88
|
functionName: {
|
|
89
89
|
type: "plain",
|
|
90
|
-
value: this.
|
|
90
|
+
value: this._jobManager.functionName,
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
93
|
permissions: {
|
|
94
|
-
"lambda:*": [this.
|
|
94
|
+
"lambda:*": [this._jobManager.functionArn],
|
|
95
95
|
},
|
|
96
96
|
};
|
|
97
97
|
}
|
|
@@ -104,7 +104,7 @@ export class Job extends Construct {
|
|
|
104
104
|
* ```
|
|
105
105
|
*/
|
|
106
106
|
bind(constructs) {
|
|
107
|
-
this.
|
|
107
|
+
this.liveDevJob?.bind(constructs);
|
|
108
108
|
this.bindForCodeBuild(constructs);
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
@@ -116,7 +116,7 @@ export class Job extends Construct {
|
|
|
116
116
|
* ```
|
|
117
117
|
*/
|
|
118
118
|
attachPermissions(permissions) {
|
|
119
|
-
this.
|
|
119
|
+
this.liveDevJob?.attachPermissions(permissions);
|
|
120
120
|
this.attachPermissionsForCodeBuild(permissions);
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
@@ -130,22 +130,15 @@ export class Job extends Construct {
|
|
|
130
130
|
* ```
|
|
131
131
|
*/
|
|
132
132
|
addEnvironment(name, value) {
|
|
133
|
-
this.
|
|
133
|
+
this.liveDevJob?.addEnvironment(name, value);
|
|
134
134
|
this.addEnvironmentForCodeBuild(name, value);
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
const { cdk, memorySize, timeout } = this.props;
|
|
136
|
+
createCodeBuildJob() {
|
|
137
|
+
const { cdk, runtime, handler, memorySize, timeout, container } = this.props;
|
|
138
138
|
const app = this.node.root;
|
|
139
139
|
return new Project(this, "JobProject", {
|
|
140
140
|
projectName: app.logicalPrefixedName(this.node.id),
|
|
141
141
|
environment: {
|
|
142
|
-
// CodeBuild offers different build images. The newer ones have much quicker
|
|
143
|
-
// boot time. The latest build image is STANDARD_6_0, which support Node.js 16.
|
|
144
|
-
// But while testing, I found STANDARD_6_0 took 100s to boot. So for the
|
|
145
|
-
// purpose of this demo, I use STANDARD_5_0. It takes 30s to boot.
|
|
146
|
-
//buildImage: codebuild.LinuxBuildImage.STANDARD_6_0,
|
|
147
|
-
//buildImage: codebuild.LinuxBuildImage.STANDARD_5_0,
|
|
148
|
-
buildImage: LinuxBuildImage.fromDockerRegistry("amazon/aws-lambda-nodejs:16"),
|
|
149
142
|
computeType: this.normalizeMemorySize(memorySize || "3 GB"),
|
|
150
143
|
},
|
|
151
144
|
environmentVariables: {
|
|
@@ -169,6 +162,24 @@ export class Job extends Construct {
|
|
|
169
162
|
subnetSelection: cdk?.vpcSubnets,
|
|
170
163
|
});
|
|
171
164
|
}
|
|
165
|
+
createLiveDevJob() {
|
|
166
|
+
// Note: make the invoker function the same ID as the Job
|
|
167
|
+
// construct so users can identify the invoker function
|
|
168
|
+
// in the Console.
|
|
169
|
+
const fn = new Function(this, this.node.id, {
|
|
170
|
+
...this.props,
|
|
171
|
+
runtime: this.convertJobRuntimeToFunctionRuntime(),
|
|
172
|
+
container: this.convertJobContainerToFunctionContainer(),
|
|
173
|
+
memorySize: 1024,
|
|
174
|
+
timeout: "10 seconds",
|
|
175
|
+
environment: {
|
|
176
|
+
...this.props.environment,
|
|
177
|
+
SST_DEBUG_JOB: "true",
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
fn._doNotAllowOthersToBind = true;
|
|
181
|
+
return fn;
|
|
182
|
+
}
|
|
172
183
|
createLogRetention() {
|
|
173
184
|
const { logRetention } = this.props;
|
|
174
185
|
if (!logRetention)
|
|
@@ -182,17 +193,44 @@ export class Job extends Construct {
|
|
|
182
193
|
});
|
|
183
194
|
}
|
|
184
195
|
buildCodeBuildProjectCode() {
|
|
185
|
-
const
|
|
196
|
+
const { handler, runtime, container } = this.props;
|
|
186
197
|
useDeferredTasks().add(async () => {
|
|
187
198
|
// Build function
|
|
188
199
|
const result = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
189
|
-
// create wrapper that calls the handler
|
|
190
200
|
if (result.type === "error") {
|
|
191
|
-
throw new Error([
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
201
|
+
throw new Error([`Failed to build job "${handler}"`, ...result.errors].join("\n"));
|
|
202
|
+
}
|
|
203
|
+
// No need to update code for container runtime
|
|
204
|
+
// Note: we could set the commands in `createCodeBuildJob` but
|
|
205
|
+
// in `sst dev`, we want to avoid changing the CodeBuild resources
|
|
206
|
+
// when `cmd` changes.
|
|
207
|
+
if (runtime === "container") {
|
|
208
|
+
const image = LinuxBuildImage.fromAsset(this, "ContainerImage", {
|
|
209
|
+
directory: handler,
|
|
210
|
+
platform: Platform.custom("linux/amd64"),
|
|
211
|
+
});
|
|
212
|
+
image.repository?.grantPull(this.job.role);
|
|
213
|
+
const project = this.job.node.defaultChild;
|
|
214
|
+
project.environment = {
|
|
215
|
+
...project.environment,
|
|
216
|
+
image: image.imageId,
|
|
217
|
+
imagePullCredentialsType: "SERVICE_ROLE",
|
|
218
|
+
};
|
|
219
|
+
project.source = {
|
|
220
|
+
type: "NO_SOURCE",
|
|
221
|
+
buildSpec: [
|
|
222
|
+
"version: 0.2",
|
|
223
|
+
"phases:",
|
|
224
|
+
" build:",
|
|
225
|
+
" commands:",
|
|
226
|
+
` - ${container.docker.cmd
|
|
227
|
+
.map((arg) => (arg.includes(" ") ? `"${arg}"` : arg))
|
|
228
|
+
.join(" ")}`,
|
|
229
|
+
].join("\n"),
|
|
230
|
+
};
|
|
231
|
+
return;
|
|
195
232
|
}
|
|
233
|
+
// Create wrapper that calls the handler
|
|
196
234
|
const parsed = path.parse(result.handler);
|
|
197
235
|
const importName = parsed.ext.substring(1);
|
|
198
236
|
const importPath = `./${path
|
|
@@ -219,76 +257,65 @@ export class Job extends Construct {
|
|
|
219
257
|
`console.log("")`,
|
|
220
258
|
`process.exit(0)`,
|
|
221
259
|
].join("\n"));
|
|
260
|
+
// Update job's commands
|
|
222
261
|
const code = AssetCode.fromAsset(result.out);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
createLocalInvoker() {
|
|
253
|
-
// Note: make the invoker function the same ID as the Job
|
|
254
|
-
// construct so users can identify the invoker function
|
|
255
|
-
// in the Console.
|
|
256
|
-
const fn = new Function(this, this.node.id, {
|
|
257
|
-
runtime: "nodejs16.x",
|
|
258
|
-
memorySize: 1024,
|
|
259
|
-
environment: {
|
|
260
|
-
...this.props.environment,
|
|
261
|
-
SST_DEBUG_TYPE: "job",
|
|
262
|
-
},
|
|
263
|
-
...this.props,
|
|
264
|
-
timeout: "15 minutes",
|
|
262
|
+
const codeConfig = code.bind(this);
|
|
263
|
+
const project = this.job.node.defaultChild;
|
|
264
|
+
const image = LinuxBuildImage.fromDockerRegistry("amazon/aws-lambda-nodejs:16");
|
|
265
|
+
project.environment = {
|
|
266
|
+
...project.environment,
|
|
267
|
+
image: image.imageId,
|
|
268
|
+
};
|
|
269
|
+
image.repository?.grantPull(this.job.role);
|
|
270
|
+
project.source = {
|
|
271
|
+
type: "S3",
|
|
272
|
+
location: `${codeConfig.s3Location?.bucketName}/${codeConfig.s3Location?.objectKey}`,
|
|
273
|
+
buildSpec: [
|
|
274
|
+
"version: 0.2",
|
|
275
|
+
"phases:",
|
|
276
|
+
" build:",
|
|
277
|
+
" commands:",
|
|
278
|
+
` - node handler-wrapper.mjs`,
|
|
279
|
+
].join("\n"),
|
|
280
|
+
};
|
|
281
|
+
this.attachPermissions([
|
|
282
|
+
new PolicyStatement({
|
|
283
|
+
actions: ["s3:*"],
|
|
284
|
+
effect: Effect.ALLOW,
|
|
285
|
+
resources: [
|
|
286
|
+
`arn:${Stack.of(this).partition}:s3:::${codeConfig.s3Location?.bucketName}/${codeConfig.s3Location?.objectKey}`,
|
|
287
|
+
],
|
|
288
|
+
}),
|
|
289
|
+
]);
|
|
265
290
|
});
|
|
266
|
-
fn._doNotAllowOthersToBind = true;
|
|
267
|
-
return fn;
|
|
268
291
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
292
|
+
createJobManager() {
|
|
293
|
+
return new CdkFunction(this, "Manager", {
|
|
294
|
+
code: Code.fromAsset(path.join(__dirname, "../support/job-manager/")),
|
|
295
|
+
handler: "index.handler",
|
|
296
|
+
runtime: Runtime.NODEJS_16_X,
|
|
297
|
+
timeout: CdkDuration.seconds(10),
|
|
274
298
|
memorySize: 1024,
|
|
275
299
|
environment: {
|
|
276
|
-
|
|
300
|
+
SST_JOB_PROVIDER: this.liveDevJob ? "lambda" : "codebuild",
|
|
301
|
+
SST_JOB_RUNNER: this.liveDevJob
|
|
302
|
+
? this.liveDevJob.functionArn
|
|
303
|
+
: this.job.projectName,
|
|
277
304
|
},
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
305
|
+
initialPolicy: [
|
|
306
|
+
this.liveDevJob
|
|
307
|
+
? new PolicyStatement({
|
|
308
|
+
effect: Effect.ALLOW,
|
|
309
|
+
actions: ["lambda:InvokeFunction"],
|
|
310
|
+
resources: [this.liveDevJob.functionArn],
|
|
311
|
+
})
|
|
312
|
+
: new PolicyStatement({
|
|
313
|
+
effect: Effect.ALLOW,
|
|
314
|
+
actions: ["codebuild:StartBuild", "codebuild:StopBuild"],
|
|
315
|
+
resources: [this.job.projectArn],
|
|
316
|
+
}),
|
|
284
317
|
],
|
|
285
|
-
nodejs: {
|
|
286
|
-
format: "esm",
|
|
287
|
-
},
|
|
288
|
-
enableLiveDev: false,
|
|
289
318
|
});
|
|
290
|
-
fn._doNotAllowOthersToBind = true;
|
|
291
|
-
return fn;
|
|
292
319
|
}
|
|
293
320
|
bindForCodeBuild(constructs) {
|
|
294
321
|
// Get referenced secrets
|
|
@@ -318,6 +345,14 @@ export class Job extends Construct {
|
|
|
318
345
|
const envVars = env.environmentVariables;
|
|
319
346
|
envVars.push({ name, value });
|
|
320
347
|
}
|
|
348
|
+
validateContainerProps() {
|
|
349
|
+
const { runtime, container } = this.props;
|
|
350
|
+
if (runtime === "container") {
|
|
351
|
+
if (!container) {
|
|
352
|
+
throw new Error(`No commands defined for the ${this.node.id} Job.`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
321
356
|
normalizeMemorySize(memorySize) {
|
|
322
357
|
if (memorySize === "3 GB") {
|
|
323
358
|
return ComputeType.SMALL;
|
|
@@ -340,4 +375,18 @@ export class Job extends Construct {
|
|
|
340
375
|
}
|
|
341
376
|
return value;
|
|
342
377
|
}
|
|
378
|
+
convertJobRuntimeToFunctionRuntime() {
|
|
379
|
+
const { runtime } = this.props;
|
|
380
|
+
return runtime === "container" ? "container" : "nodejs16.x";
|
|
381
|
+
}
|
|
382
|
+
convertJobContainerToFunctionContainer() {
|
|
383
|
+
const { runtime, container } = this.props;
|
|
384
|
+
if (runtime !== "container")
|
|
385
|
+
return;
|
|
386
|
+
return {
|
|
387
|
+
docker: {
|
|
388
|
+
cmd: container?.docker.cmd,
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
}
|
|
343
392
|
}
|
|
@@ -143,7 +143,7 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
143
143
|
statements.push(buildPolicyStatement("lambda:*", [permission.functionArn]));
|
|
144
144
|
}
|
|
145
145
|
else if (permission instanceof Job) {
|
|
146
|
-
statements.push(buildPolicyStatement("lambda:*", [permission.
|
|
146
|
+
statements.push(buildPolicyStatement("lambda:*", [permission._jobManager.functionArn]));
|
|
147
147
|
}
|
|
148
148
|
////////////////////////////////////
|
|
149
149
|
// Case: CDK constructs
|
package/node/job/index.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ export type JobType = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare const Job: JobType;
|
|
12
12
|
declare function JobControl<Name extends keyof JobResources>(name: Name, vars: Record<string, string>): {
|
|
13
|
-
run(props: JobRunProps<Name>): Promise<
|
|
13
|
+
run(props: JobRunProps<Name>): Promise<{
|
|
14
|
+
jobId: string;
|
|
15
|
+
}>;
|
|
16
|
+
cancel(jobId: string): Promise<void>;
|
|
14
17
|
};
|
|
15
18
|
/**
|
|
16
19
|
* Create a new job handler.
|
package/node/job/index.js
CHANGED
|
@@ -11,19 +11,30 @@ export const Job = /* @__PURE__ */ (() => {
|
|
|
11
11
|
return result;
|
|
12
12
|
})();
|
|
13
13
|
function JobControl(name, vars) {
|
|
14
|
+
const functionName = vars.functionName;
|
|
14
15
|
return {
|
|
15
16
|
async run(props) {
|
|
16
|
-
// Handle job permission not granted
|
|
17
|
-
const functionName = vars.functionName;
|
|
18
17
|
// Invoke the Lambda function
|
|
19
18
|
const ret = await lambda.send(new InvokeCommand({
|
|
20
19
|
FunctionName: functionName,
|
|
21
|
-
Payload: props?.payload
|
|
22
|
-
? undefined
|
|
23
|
-
: Buffer.from(JSON.stringify(props?.payload)),
|
|
20
|
+
Payload: Buffer.from(JSON.stringify({ action: "run", payload: props?.payload })),
|
|
24
21
|
}));
|
|
25
22
|
if (ret.FunctionError) {
|
|
26
|
-
throw new Error(`Failed to invoke the ${name}
|
|
23
|
+
throw new Error(`Failed to invoke the "${name}" job. Error: ${ret.FunctionError}`);
|
|
24
|
+
}
|
|
25
|
+
const resp = JSON.parse(Buffer.from(ret.Payload).toString());
|
|
26
|
+
return {
|
|
27
|
+
jobId: resp.jobId,
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
async cancel(jobId) {
|
|
31
|
+
// Invoke the Lambda function
|
|
32
|
+
const ret = await lambda.send(new InvokeCommand({
|
|
33
|
+
FunctionName: functionName,
|
|
34
|
+
Payload: Buffer.from(JSON.stringify({ action: "cancel", jobId })),
|
|
35
|
+
}));
|
|
36
|
+
if (ret.FunctionError) {
|
|
37
|
+
throw new Error(`Failed to cancel the "${name}" job id ${jobId}. Error: ${ret.FunctionError}`);
|
|
27
38
|
}
|
|
28
39
|
},
|
|
29
40
|
};
|