serverless-offline 13.3.2 → 13.3.3
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/README.md +17 -17
- package/package.json +14 -13
- package/src/ServerlessOffline.js +42 -42
- package/src/config/colors.js +9 -9
- package/src/config/commandOptions.js +61 -61
- package/src/config/constants.js +5 -5
- package/src/config/defaultOptions.js +6 -6
- package/src/config/index.js +4 -4
- package/src/config/supportedRuntimes.js +18 -18
- package/src/errors/index.js +1 -1
- package/src/events/alb/Alb.js +2 -2
- package/src/events/alb/AlbEventDefinition.js +2 -2
- package/src/events/alb/HttpServer.js +54 -54
- package/src/events/alb/index.js +1 -1
- package/src/events/alb/lambda-events/LambdaAlbRequestEvent.js +2 -2
- package/src/events/alb/lambda-events/index.js +1 -1
- package/src/events/authCanExecuteResource.js +3 -3
- package/src/events/authFunctionNameExtractor.js +9 -9
- package/src/events/authMatchPolicyResource.js +8 -8
- package/src/events/authValidateContext.js +11 -11
- package/src/events/http/Endpoint.js +26 -26
- package/src/events/http/Http.js +2 -2
- package/src/events/http/HttpEventDefinition.js +2 -2
- package/src/events/http/HttpServer.js +156 -156
- package/src/events/http/OfflineEndpoint.js +7 -7
- package/src/events/http/authJWTSettingsExtractor.js +2 -2
- package/src/events/http/createAuthScheme.js +29 -27
- package/src/events/http/createJWTAuthScheme.js +12 -12
- package/src/events/http/index.js +1 -1
- package/src/events/http/javaHelpers.js +2 -2
- package/src/events/http/lambda-events/LambdaIntegrationEvent.js +5 -5
- package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +47 -47
- package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +27 -27
- package/src/events/http/lambda-events/VelocityContext.js +28 -32
- package/src/events/http/lambda-events/index.js +4 -4
- package/src/events/http/lambda-events/renderVelocityTemplateObject.js +13 -13
- package/src/events/http/parseResources.js +6 -6
- package/src/events/http/payloadSchemaValidator.js +2 -2
- package/src/events/schedule/Schedule.js +21 -21
- package/src/events/schedule/ScheduleEvent.js +7 -7
- package/src/events/schedule/ScheduleEventDefinition.js +1 -1
- package/src/events/schedule/index.js +1 -1
- package/src/events/websocket/HttpServer.js +9 -9
- package/src/events/websocket/WebSocket.js +4 -4
- package/src/events/websocket/WebSocketClients.js +29 -29
- package/src/events/websocket/WebSocketEventDefinition.js +1 -1
- package/src/events/websocket/WebSocketServer.js +9 -9
- package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +3 -3
- package/src/events/websocket/http-routes/_catchAll/index.js +1 -1
- package/src/events/websocket/http-routes/connections/ConnectionsController.js +1 -1
- package/src/events/websocket/http-routes/connections/connectionsRoutes.js +6 -6
- package/src/events/websocket/http-routes/connections/index.js +1 -1
- package/src/events/websocket/http-routes/index.js +2 -2
- package/src/events/websocket/index.js +1 -1
- package/src/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +5 -5
- package/src/events/websocket/lambda-events/WebSocketConnectEvent.js +7 -6
- package/src/events/websocket/lambda-events/WebSocketDisconnectEvent.js +5 -5
- package/src/events/websocket/lambda-events/WebSocketEvent.js +2 -2
- package/src/events/websocket/lambda-events/WebSocketRequestContext.js +12 -11
- package/src/events/websocket/lambda-events/index.js +4 -4
- package/src/index.js +1 -1
- package/src/lambda/HttpServer.js +11 -11
- package/src/lambda/Lambda.js +2 -2
- package/src/lambda/LambdaContext.js +1 -1
- package/src/lambda/LambdaFunction.js +34 -34
- package/src/lambda/LambdaFunctionPool.js +3 -3
- package/src/lambda/handler-runner/HandlerRunner.js +12 -12
- package/src/lambda/handler-runner/docker-runner/DockerContainer.js +59 -59
- package/src/lambda/handler-runner/docker-runner/DockerImage.js +6 -6
- package/src/lambda/handler-runner/docker-runner/DockerRunner.js +2 -2
- package/src/lambda/handler-runner/docker-runner/index.js +1 -1
- package/src/lambda/handler-runner/go-runner/GoRunner.js +34 -34
- package/src/lambda/handler-runner/go-runner/index.js +1 -1
- package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +7 -7
- package/src/lambda/handler-runner/in-process-runner/aws-lambda-ric/UserFunction.js +52 -52
- package/src/lambda/handler-runner/in-process-runner/index.js +1 -1
- package/src/lambda/handler-runner/index.js +1 -1
- package/src/lambda/handler-runner/java-runner/JavaRunner.js +13 -13
- package/src/lambda/handler-runner/java-runner/index.js +1 -1
- package/src/lambda/handler-runner/python-runner/PythonRunner.js +21 -21
- package/src/lambda/handler-runner/python-runner/index.js +1 -1
- package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +11 -11
- package/src/lambda/handler-runner/ruby-runner/index.js +1 -1
- package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +6 -6
- package/src/lambda/handler-runner/worker-thread-runner/index.js +1 -1
- package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +4 -4
- package/src/lambda/index.js +1 -1
- package/src/lambda/routes/index.js +2 -2
- package/src/lambda/routes/invocations/InvocationsController.js +11 -11
- package/src/lambda/routes/invocations/index.js +1 -1
- package/src/lambda/routes/invocations/invocationsRoute.js +15 -15
- package/src/lambda/routes/invoke-async/index.js +1 -1
- package/src/lambda/routes/invoke-async/invokeAsyncRoute.js +6 -6
- package/src/utils/checkDockerDaemon.js +8 -8
- package/src/utils/checkGoVersion.js +3 -3
- package/src/utils/createApiKey.js +2 -2
- package/src/utils/detectExecutable.js +2 -2
- package/src/utils/formatToClfTime.js +2 -2
- package/src/utils/generateHapiPath.js +8 -8
- package/src/utils/getApiKeysValues.js +2 -2
- package/src/utils/getHttpApiCorsConfig.js +11 -11
- package/src/utils/getRawQueryParams.js +2 -2
- package/src/utils/index.js +25 -26
- package/src/utils/jsonPath.js +1 -1
- package/src/utils/logRoutes.js +13 -13
- package/src/utils/parseHeaders.js +1 -1
- package/src/utils/parseMultiValueHeaders.js +1 -1
- package/src/utils/parseMultiValueQueryStringParameters.js +1 -1
- package/src/utils/parseQueryStringParameters.js +1 -1
- package/src/utils/parseQueryStringParametersForPayloadV2.js +1 -1
- package/src/utils/splitHandlerPathAndName.js +3 -3
- package/src/utils/createUniqueId.js +0 -5
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
1
|
+
import crypto from "node:crypto"
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises"
|
|
3
|
+
import { dirname, join, resolve } from "node:path"
|
|
4
|
+
import process from "node:process"
|
|
5
|
+
import { performance } from "node:perf_hooks"
|
|
6
|
+
import { setTimeout } from "node:timers/promises"
|
|
7
|
+
import { log } from "@serverless/utils/log.js"
|
|
8
|
+
import { emptyDir, ensureDir, remove } from "fs-extra"
|
|
9
|
+
import jszip from "jszip"
|
|
10
|
+
import HandlerRunner from "./handler-runner/index.js"
|
|
11
|
+
import LambdaContext from "./LambdaContext.js"
|
|
11
12
|
import {
|
|
12
13
|
DEFAULT_LAMBDA_MEMORY_SIZE,
|
|
13
14
|
DEFAULT_LAMBDA_RUNTIME,
|
|
14
15
|
DEFAULT_LAMBDA_TIMEOUT,
|
|
15
16
|
supportedRuntimes,
|
|
16
|
-
} from
|
|
17
|
-
import { LambdaTimeoutError } from
|
|
18
|
-
import { createUniqueId } from '../utils/index.js'
|
|
17
|
+
} from "../config/index.js"
|
|
18
|
+
import { LambdaTimeoutError } from "../errors/index.js"
|
|
19
19
|
|
|
20
20
|
const { ceil } = Math
|
|
21
21
|
const { entries, fromEntries } = Object
|
|
@@ -57,7 +57,7 @@ export default class LambdaFunction {
|
|
|
57
57
|
|
|
58
58
|
#runtime = null
|
|
59
59
|
|
|
60
|
-
#status =
|
|
60
|
+
#status = "IDLE" // can be 'BUSY' or 'IDLE'
|
|
61
61
|
|
|
62
62
|
#timeout = null
|
|
63
63
|
|
|
@@ -71,7 +71,7 @@ export default class LambdaFunction {
|
|
|
71
71
|
// TEMP options.location, for compatibility with serverless-webpack:
|
|
72
72
|
// https://github.com/dherault/serverless-offline/issues/787
|
|
73
73
|
// TODO FIXME look into better way to work with serverless-webpack
|
|
74
|
-
const servicepath = resolve(servicePath, options.location ??
|
|
74
|
+
const servicepath = resolve(servicePath, options.location ?? "")
|
|
75
75
|
|
|
76
76
|
const { handler, name, package: functionPackage = {} } = functionDefinition
|
|
77
77
|
|
|
@@ -104,12 +104,12 @@ export default class LambdaFunction {
|
|
|
104
104
|
? process.env
|
|
105
105
|
: // we always copy all AWS_xxxx environment variables over from local env
|
|
106
106
|
fromEntries(
|
|
107
|
-
entries(process.env).filter(([key]) => key.startsWith(
|
|
107
|
+
entries(process.env).filter(([key]) => key.startsWith("AWS_")),
|
|
108
108
|
)),
|
|
109
109
|
...this.#getAwsEnvVars(),
|
|
110
110
|
...provider.environment,
|
|
111
111
|
...functionDefinition.environment,
|
|
112
|
-
IS_OFFLINE:
|
|
112
|
+
IS_OFFLINE: "true",
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
this.#artifact = functionDefinition.package?.artifact
|
|
@@ -122,16 +122,16 @@ export default class LambdaFunction {
|
|
|
122
122
|
// lambda directory contains code and layers
|
|
123
123
|
this.#lambdaDir = join(
|
|
124
124
|
servicepath,
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
".serverless-offline",
|
|
126
|
+
"services",
|
|
127
127
|
service.service,
|
|
128
128
|
functionKey,
|
|
129
|
-
|
|
129
|
+
crypto.randomUUID(),
|
|
130
130
|
)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
this.#codeDir = this.#lambdaDir
|
|
134
|
-
? resolve(this.#lambdaDir,
|
|
134
|
+
? resolve(this.#lambdaDir, "code")
|
|
135
135
|
: servicepath
|
|
136
136
|
|
|
137
137
|
// TEMP
|
|
@@ -189,18 +189,18 @@ export default class LambdaFunction {
|
|
|
189
189
|
AWS_DEFAULT_REGION: this.#region,
|
|
190
190
|
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: this.#memorySize,
|
|
191
191
|
AWS_LAMBDA_FUNCTION_NAME: this.#functionName,
|
|
192
|
-
AWS_LAMBDA_FUNCTION_VERSION:
|
|
192
|
+
AWS_LAMBDA_FUNCTION_VERSION: "$LATEST",
|
|
193
193
|
// https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/lib/naming.js#L123
|
|
194
194
|
AWS_LAMBDA_LOG_GROUP_NAME: `/aws/lambda/${this.#functionName}`,
|
|
195
195
|
AWS_LAMBDA_LOG_STREAM_NAME:
|
|
196
|
-
|
|
196
|
+
"2016/12/02/[$LATEST]f77ff5e4026c45bda9a9ebcec6bc9cad",
|
|
197
197
|
AWS_REGION: this.#region,
|
|
198
|
-
LAMBDA_RUNTIME_DIR:
|
|
199
|
-
LAMBDA_TASK_ROOT:
|
|
200
|
-
LANG:
|
|
198
|
+
LAMBDA_RUNTIME_DIR: "/var/runtime",
|
|
199
|
+
LAMBDA_TASK_ROOT: "/var/task",
|
|
200
|
+
LANG: "en_US.UTF-8",
|
|
201
201
|
LD_LIBRARY_PATH:
|
|
202
|
-
|
|
203
|
-
NODE_PATH:
|
|
202
|
+
"/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib",
|
|
203
|
+
NODE_PATH: "/var/runtime:/var/task:/var/runtime/node_modules",
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
@@ -244,8 +244,8 @@ export default class LambdaFunction {
|
|
|
244
244
|
|
|
245
245
|
await Promise.all(
|
|
246
246
|
entries(zip.files).map(async ([filename, jsZipObj]) => {
|
|
247
|
-
const fileData = await jsZipObj.async(
|
|
248
|
-
if (filename.endsWith(
|
|
247
|
+
const fileData = await jsZipObj.async("nodebuffer")
|
|
248
|
+
if (filename.endsWith("/")) {
|
|
249
249
|
return undefined
|
|
250
250
|
}
|
|
251
251
|
await ensureDir(join(this.#codeDir, dirname(filename)))
|
|
@@ -276,17 +276,17 @@ export default class LambdaFunction {
|
|
|
276
276
|
async #timeoutAndTerminate() {
|
|
277
277
|
await setTimeout(this.#timeout)
|
|
278
278
|
|
|
279
|
-
throw new LambdaTimeoutError(
|
|
279
|
+
throw new LambdaTimeoutError("[504] - Lambda timeout.")
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
async runHandler() {
|
|
283
|
-
this.#status =
|
|
283
|
+
this.#status = "BUSY"
|
|
284
284
|
|
|
285
285
|
if (!this.#initialized) {
|
|
286
286
|
await this.#initialize()
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
const requestId =
|
|
289
|
+
const requestId = crypto.randomUUID()
|
|
290
290
|
|
|
291
291
|
this.#lambdaContext.setRequestId(requestId)
|
|
292
292
|
this.#lambdaContext.setClientContext(this.#clientContext)
|
|
@@ -322,7 +322,7 @@ export default class LambdaFunction {
|
|
|
322
322
|
|
|
323
323
|
throw err
|
|
324
324
|
} finally {
|
|
325
|
-
this.#status =
|
|
325
|
+
this.#status = "IDLE"
|
|
326
326
|
|
|
327
327
|
this.#startIdleTimer()
|
|
328
328
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import LambdaFunction from
|
|
1
|
+
import LambdaFunction from "./LambdaFunction.js"
|
|
2
2
|
|
|
3
3
|
export default class LambdaFunctionPool {
|
|
4
4
|
#options = null
|
|
@@ -34,7 +34,7 @@ export default class LambdaFunctionPool {
|
|
|
34
34
|
const { idleTimeInMillis, status } = lambdaFunction
|
|
35
35
|
|
|
36
36
|
if (
|
|
37
|
-
status ===
|
|
37
|
+
status === "IDLE" &&
|
|
38
38
|
idleTimeInMillis >= functionCleanupIdleTimeInMillis
|
|
39
39
|
) {
|
|
40
40
|
cleanupWait.push(lambdaFunction.cleanup())
|
|
@@ -96,7 +96,7 @@ export default class LambdaFunctionPool {
|
|
|
96
96
|
if (!this.#options.reloadHandler) {
|
|
97
97
|
// find any IDLE
|
|
98
98
|
lambdaFunction = Array.from(lambdaFunctions).find(
|
|
99
|
-
({ status }) => status ===
|
|
99
|
+
({ status }) => status === "IDLE",
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
if (lambdaFunction != null) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { log } from
|
|
1
|
+
import { log } from "@serverless/utils/log.js"
|
|
2
2
|
import {
|
|
3
3
|
supportedGo,
|
|
4
4
|
supportedJava,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
supportedPython,
|
|
7
7
|
supportedRuby,
|
|
8
8
|
unsupportedDockerRuntimes,
|
|
9
|
-
} from
|
|
9
|
+
} from "../../config/index.js"
|
|
10
10
|
|
|
11
11
|
export default class HandlerRunner {
|
|
12
12
|
#env = null
|
|
@@ -34,7 +34,7 @@ export default class HandlerRunner {
|
|
|
34
34
|
log.warning(
|
|
35
35
|
`"${runtime}" runtime is not supported with docker. See https://github.com/lambci/docker-lambda`,
|
|
36
36
|
)
|
|
37
|
-
throw new Error(
|
|
37
|
+
throw new Error("Unsupported runtime")
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const dockerOptions = {
|
|
@@ -45,7 +45,7 @@ export default class HandlerRunner {
|
|
|
45
45
|
readOnly: this.#options.dockerReadOnly,
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const { default: DockerRunner } = await import(
|
|
48
|
+
const { default: DockerRunner } = await import("./docker-runner/index.js")
|
|
49
49
|
|
|
50
50
|
return new DockerRunner(this.#funOptions, this.#env, dockerOptions)
|
|
51
51
|
}
|
|
@@ -53,50 +53,50 @@ export default class HandlerRunner {
|
|
|
53
53
|
if (supportedNodejs.has(runtime)) {
|
|
54
54
|
if (useInProcess) {
|
|
55
55
|
const { default: InProcessRunner } = await import(
|
|
56
|
-
|
|
56
|
+
"./in-process-runner/index.js"
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
return new InProcessRunner(this.#funOptions, this.#env)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
const { default: WorkerThreadRunner } = await import(
|
|
63
|
-
|
|
63
|
+
"./worker-thread-runner/index.js"
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
return new WorkerThreadRunner(this.#funOptions, this.#env)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (supportedGo.has(runtime)) {
|
|
70
|
-
const { default: GoRunner } = await import(
|
|
70
|
+
const { default: GoRunner } = await import("./go-runner/index.js")
|
|
71
71
|
|
|
72
72
|
return new GoRunner(this.#funOptions, this.#env)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
if (supportedPython.has(runtime)) {
|
|
76
|
-
const { default: PythonRunner } = await import(
|
|
76
|
+
const { default: PythonRunner } = await import("./python-runner/index.js")
|
|
77
77
|
|
|
78
78
|
return new PythonRunner(this.#funOptions, this.#env)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
if (supportedRuby.has(runtime)) {
|
|
82
|
-
const { default: RubyRunner } = await import(
|
|
82
|
+
const { default: RubyRunner } = await import("./ruby-runner/index.js")
|
|
83
83
|
|
|
84
84
|
return new RubyRunner(this.#funOptions, this.#env)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
if (supportedJava.has(runtime)) {
|
|
88
|
-
const { default: JavaRunner } = await import(
|
|
88
|
+
const { default: JavaRunner } = await import("./java-runner/index.js")
|
|
89
89
|
|
|
90
90
|
return new JavaRunner(this.#funOptions, this.#env)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// TODO FIXME
|
|
94
|
-
throw new Error(
|
|
94
|
+
throw new Error("Unsupported runtime")
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// TEMP TODO FIXME
|
|
98
98
|
isDockerRunner() {
|
|
99
|
-
return this.#runner && this.#runner.constructor.name ===
|
|
99
|
+
return this.#runner && this.#runner.constructor.name === "DockerRunner"
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// () => Promise<void>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { createHash } from
|
|
2
|
-
import { createWriteStream } from
|
|
3
|
-
import { readFile, unlink, writeFile } from
|
|
4
|
-
import { platform } from
|
|
5
|
-
import { dirname, join, sep } from
|
|
6
|
-
import { LambdaClient, GetLayerVersionCommand } from
|
|
7
|
-
import { log, progress } from
|
|
8
|
-
import { execa } from
|
|
9
|
-
import { ensureDir, pathExists } from
|
|
10
|
-
import isWsl from
|
|
11
|
-
import jszip from
|
|
12
|
-
import pRetry from
|
|
13
|
-
import DockerImage from
|
|
1
|
+
import { createHash } from "node:crypto"
|
|
2
|
+
import { createWriteStream } from "node:fs"
|
|
3
|
+
import { readFile, unlink, writeFile } from "node:fs/promises"
|
|
4
|
+
import { platform } from "node:os"
|
|
5
|
+
import { dirname, join, sep } from "node:path"
|
|
6
|
+
import { LambdaClient, GetLayerVersionCommand } from "@aws-sdk/client-lambda"
|
|
7
|
+
import { log, progress } from "@serverless/utils/log.js"
|
|
8
|
+
import { execa } from "execa"
|
|
9
|
+
import { ensureDir, pathExists } from "fs-extra"
|
|
10
|
+
import isWsl from "is-wsl"
|
|
11
|
+
import jszip from "jszip"
|
|
12
|
+
import pRetry from "p-retry"
|
|
13
|
+
import DockerImage from "./DockerImage.js"
|
|
14
14
|
|
|
15
15
|
const { stringify } = JSON
|
|
16
16
|
const { floor, log: mathLog } = Math
|
|
@@ -73,33 +73,33 @@ export default class DockerContainer {
|
|
|
73
73
|
async start(codeDir) {
|
|
74
74
|
await this.#image.pull()
|
|
75
75
|
|
|
76
|
-
log.debug(
|
|
76
|
+
log.debug("Run Docker container...")
|
|
77
77
|
|
|
78
|
-
let permissions =
|
|
78
|
+
let permissions = "ro"
|
|
79
79
|
|
|
80
80
|
if (!this.#dockerOptions.readOnly) {
|
|
81
|
-
permissions =
|
|
81
|
+
permissions = "rw"
|
|
82
82
|
}
|
|
83
83
|
// https://github.com/serverless/serverless/blob/v1.57.0/lib/plugins/aws/invokeLocal/index.js#L291-L293
|
|
84
84
|
const dockerArgs = [
|
|
85
|
-
|
|
85
|
+
"-v",
|
|
86
86
|
`${codeDir}:/var/task:${permissions},delegated`,
|
|
87
|
-
|
|
87
|
+
"-p",
|
|
88
88
|
9001,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
"-e",
|
|
90
|
+
"DOCKER_LAMBDA_STAY_OPEN=1", // API mode
|
|
91
|
+
"-e",
|
|
92
|
+
"DOCKER_LAMBDA_WATCH=1", // Watch mode
|
|
93
93
|
]
|
|
94
94
|
|
|
95
95
|
if (this.#layers.length > 0) {
|
|
96
96
|
log.verbose(`Found layers, checking provider type`)
|
|
97
97
|
|
|
98
|
-
if (this.#provider.name.toLowerCase() ===
|
|
98
|
+
if (this.#provider.name.toLowerCase() === "aws") {
|
|
99
99
|
let layerDir = this.#dockerOptions.layersDir
|
|
100
100
|
|
|
101
101
|
if (!layerDir) {
|
|
102
|
-
layerDir = join(this.#servicePath,
|
|
102
|
+
layerDir = join(this.#servicePath, ".serverless-offline", "layers")
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
layerDir = join(layerDir, this.#getLayersSha256())
|
|
@@ -113,7 +113,7 @@ export default class DockerContainer {
|
|
|
113
113
|
|
|
114
114
|
// Only initialise if we have layers, we're using AWS, and they don't already exist
|
|
115
115
|
this.#lambdaClient = new LambdaClient({
|
|
116
|
-
apiVersion:
|
|
116
|
+
apiVersion: "2015-03-31",
|
|
117
117
|
region: this.#provider.region,
|
|
118
118
|
})
|
|
119
119
|
|
|
@@ -135,7 +135,7 @@ export default class DockerContainer {
|
|
|
135
135
|
this.#dockerOptions.hostServicePath,
|
|
136
136
|
)
|
|
137
137
|
}
|
|
138
|
-
dockerArgs.push(
|
|
138
|
+
dockerArgs.push("-v", `${layerDir}:/opt:ro,delegated`)
|
|
139
139
|
} else {
|
|
140
140
|
log.warning(
|
|
141
141
|
`Provider ${this.#provider.name} is Unsupported. Layers are only supported on aws.`,
|
|
@@ -144,52 +144,52 @@ export default class DockerContainer {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
entries(this.#env).forEach(([key, value]) => {
|
|
147
|
-
dockerArgs.push(
|
|
147
|
+
dockerArgs.push("-e", `${key}=${value}`)
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
if (platform() ===
|
|
150
|
+
if (platform() === "linux" && !isWsl) {
|
|
151
151
|
// Add `host.docker.internal` DNS name to access host from inside the container
|
|
152
152
|
// https://github.com/docker/for-linux/issues/264
|
|
153
153
|
const gatewayIp = await this.#getBridgeGatewayIp()
|
|
154
154
|
if (gatewayIp) {
|
|
155
|
-
dockerArgs.push(
|
|
155
|
+
dockerArgs.push("--add-host", `host.docker.internal:${gatewayIp}`)
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
if (this.#dockerOptions.network) {
|
|
160
|
-
dockerArgs.push(
|
|
160
|
+
dockerArgs.push("--network", this.#dockerOptions.network)
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
const { stdout: containerId } = await execa(
|
|
164
|
-
|
|
163
|
+
const { stdout: containerId } = await execa("docker", [
|
|
164
|
+
"create",
|
|
165
165
|
...dockerArgs,
|
|
166
166
|
this.#imageNameTag,
|
|
167
167
|
this.#handler,
|
|
168
168
|
])
|
|
169
169
|
|
|
170
|
-
const dockerStart = execa(
|
|
170
|
+
const dockerStart = execa("docker", ["start", "-a", containerId], {
|
|
171
171
|
all: true,
|
|
172
172
|
})
|
|
173
173
|
|
|
174
174
|
await new Promise((resolve, reject) => {
|
|
175
|
-
dockerStart.all.on(
|
|
175
|
+
dockerStart.all.on("data", (data) => {
|
|
176
176
|
const str = String(data)
|
|
177
177
|
log.error(str)
|
|
178
178
|
|
|
179
|
-
if (str.includes(
|
|
179
|
+
if (str.includes("Lambda API listening on port")) {
|
|
180
180
|
resolve()
|
|
181
181
|
}
|
|
182
182
|
})
|
|
183
183
|
|
|
184
|
-
dockerStart.on(
|
|
184
|
+
dockerStart.on("error", (err) => {
|
|
185
185
|
reject(err)
|
|
186
186
|
})
|
|
187
187
|
})
|
|
188
188
|
|
|
189
189
|
// parse `docker port` output and get the container port
|
|
190
190
|
let containerPort
|
|
191
|
-
const { stdout: dockerPortOutput } = await execa(
|
|
192
|
-
|
|
191
|
+
const { stdout: dockerPortOutput } = await execa("docker", [
|
|
192
|
+
"port",
|
|
193
193
|
containerId,
|
|
194
194
|
])
|
|
195
195
|
// NOTE: `docker port` may output multiple lines.
|
|
@@ -199,7 +199,7 @@ export default class DockerContainer {
|
|
|
199
199
|
// 9001/tcp -> :::49153
|
|
200
200
|
//
|
|
201
201
|
// Parse each line until it finds the mapped port.
|
|
202
|
-
for (const line of dockerPortOutput.split(
|
|
202
|
+
for (const line of dockerPortOutput.split("\n")) {
|
|
203
203
|
const result = line.match(/^9001\/tcp -> (.*):(\d+)$/)
|
|
204
204
|
if (result && result.length > 2) {
|
|
205
205
|
;[, , containerPort] = result
|
|
@@ -207,7 +207,7 @@ export default class DockerContainer {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
if (!containerPort) {
|
|
210
|
-
throw new Error(
|
|
210
|
+
throw new Error("Failed to get container port")
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
this.#containerId = containerId
|
|
@@ -224,7 +224,7 @@ export default class DockerContainer {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
async #downloadLayer(layerArn, layerDir) {
|
|
227
|
-
const [, layerName] = layerArn.split(
|
|
227
|
+
const [, layerName] = layerArn.split(":layer:")
|
|
228
228
|
const layerZipFile = `${layerDir}/${layerName}.zip`
|
|
229
229
|
const layerProgress = progress.get(`layer-${layerName}`)
|
|
230
230
|
|
|
@@ -249,7 +249,7 @@ export default class DockerContainer {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
if (
|
|
252
|
-
hasOwn(layer,
|
|
252
|
+
hasOwn(layer, "CompatibleRuntimes") &&
|
|
253
253
|
!layer.CompatibleRuntimes.includes(this.#runtime)
|
|
254
254
|
) {
|
|
255
255
|
log.warning(
|
|
@@ -289,10 +289,10 @@ export default class DockerContainer {
|
|
|
289
289
|
|
|
290
290
|
await new Promise((resolve, reject) => {
|
|
291
291
|
res.body.pipe(fileStream)
|
|
292
|
-
res.body.on(
|
|
292
|
+
res.body.on("error", (err) => {
|
|
293
293
|
reject(err)
|
|
294
294
|
})
|
|
295
|
-
fileStream.on(
|
|
295
|
+
fileStream.on("finish", () => {
|
|
296
296
|
resolve()
|
|
297
297
|
})
|
|
298
298
|
})
|
|
@@ -307,7 +307,7 @@ export default class DockerContainer {
|
|
|
307
307
|
|
|
308
308
|
await Promise.all(
|
|
309
309
|
entries(zip.files).map(async ([filename, jsZipObj]) => {
|
|
310
|
-
const fileData = await jsZipObj.async(
|
|
310
|
+
const fileData = await jsZipObj.async("nodebuffer")
|
|
311
311
|
if (filename.endsWith(sep)) {
|
|
312
312
|
return undefined
|
|
313
313
|
}
|
|
@@ -329,19 +329,19 @@ export default class DockerContainer {
|
|
|
329
329
|
async #getBridgeGatewayIp() {
|
|
330
330
|
let gateway
|
|
331
331
|
try {
|
|
332
|
-
;({ stdout: gateway } = await execa(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
332
|
+
;({ stdout: gateway } = await execa("docker", [
|
|
333
|
+
"network",
|
|
334
|
+
"inspect",
|
|
335
|
+
"bridge",
|
|
336
|
+
"--format",
|
|
337
|
+
"{{(index .IPAM.Config 0).Gateway}}",
|
|
338
338
|
]))
|
|
339
339
|
} catch (err) {
|
|
340
340
|
log.error(err.stderr)
|
|
341
341
|
|
|
342
342
|
throw err
|
|
343
343
|
}
|
|
344
|
-
return gateway.split(
|
|
344
|
+
return gateway.split("/")[0]
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
async #ping() {
|
|
@@ -360,8 +360,8 @@ export default class DockerContainer {
|
|
|
360
360
|
|
|
361
361
|
const res = await fetch(url, {
|
|
362
362
|
body: stringify(event),
|
|
363
|
-
headers: {
|
|
364
|
-
method:
|
|
363
|
+
headers: { "Content-Type": "application/json" },
|
|
364
|
+
method: "post",
|
|
365
365
|
})
|
|
366
366
|
|
|
367
367
|
if (!res.ok) {
|
|
@@ -374,8 +374,8 @@ export default class DockerContainer {
|
|
|
374
374
|
async stop() {
|
|
375
375
|
if (this.#containerId) {
|
|
376
376
|
try {
|
|
377
|
-
await execa(
|
|
378
|
-
await execa(
|
|
377
|
+
await execa("docker", ["stop", this.#containerId])
|
|
378
|
+
await execa("docker", ["rm", this.#containerId])
|
|
379
379
|
} catch (err) {
|
|
380
380
|
log.error(err.stderr)
|
|
381
381
|
|
|
@@ -385,11 +385,11 @@ export default class DockerContainer {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
#formatBytes(bytes, decimals = 2) {
|
|
388
|
-
if (bytes === 0) return
|
|
388
|
+
if (bytes === 0) return "0 Bytes"
|
|
389
389
|
|
|
390
390
|
const k = 1024
|
|
391
391
|
const dm = decimals < 0 ? 0 : decimals
|
|
392
|
-
const sizes = [
|
|
392
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
|
393
393
|
|
|
394
394
|
const i = floor(mathLog(bytes) / mathLog(k))
|
|
395
395
|
|
|
@@ -397,7 +397,7 @@ export default class DockerContainer {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
#getLayersSha256() {
|
|
400
|
-
return createHash(
|
|
400
|
+
return createHash("sha256").update(stringify(this.#layers)).digest("hex")
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
get isRunning() {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { log } from
|
|
2
|
-
import { execa } from
|
|
1
|
+
import { log } from "@serverless/utils/log.js"
|
|
2
|
+
import { execa } from "execa"
|
|
3
3
|
// TODO FIXME eslint plugin import bug, or not supporting package.json "expprts" field?
|
|
4
4
|
// eslint-disable-next-line import/no-unresolved
|
|
5
|
-
import promiseMemoize from
|
|
5
|
+
import promiseMemoize from "p-memoize"
|
|
6
6
|
|
|
7
7
|
export default class DockerImage {
|
|
8
8
|
#imageNameTag = null
|
|
@@ -17,9 +17,9 @@ export default class DockerImage {
|
|
|
17
17
|
log.debug(`Downloading base Docker image... (${imageNameTag})`)
|
|
18
18
|
|
|
19
19
|
try {
|
|
20
|
-
await execa(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
await execa("docker", [
|
|
21
|
+
"pull",
|
|
22
|
+
"--disable-content-trust=false",
|
|
23
23
|
imageNameTag,
|
|
24
24
|
])
|
|
25
25
|
} catch (err) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import DockerContainer from
|
|
2
|
-
import { checkDockerDaemon } from
|
|
1
|
+
import DockerContainer from "./DockerContainer.js"
|
|
2
|
+
import { checkDockerDaemon } from "../../../utils/index.js"
|
|
3
3
|
|
|
4
4
|
export default class DockerRunner {
|
|
5
5
|
#codeDir = null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from
|
|
1
|
+
export { default } from "./DockerRunner.js"
|