@adobe/aio-lib-sandbox 0.1.0-alpha.8 → 0.1.0-alpha.9
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/package.json +1 -1
- package/src/Sandbox.js +16 -4
- package/src/constants.js +4 -1
- package/src/errors.js +5 -1
- package/src/index.js +8 -2
- package/src/utils.js +2 -2
- package/src/ws.js +12 -0
- package/test/Sandbox.test.js +30 -2
package/package.json
CHANGED
package/src/Sandbox.js
CHANGED
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
normalizeSize,
|
|
24
24
|
apiRequest
|
|
25
25
|
} = require('./utils')
|
|
26
|
-
const { SANDBOX_SIZES } = require('./constants')
|
|
26
|
+
const { SANDBOX_SIZES, PROTOCOL_VERSION, API_PREFIX } = require('./constants')
|
|
27
27
|
const { SandboxSocket } = require('./ws')
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -44,6 +44,7 @@ class Sandbox {
|
|
|
44
44
|
this.region = options.region
|
|
45
45
|
this.idleTimeout = options.idleTimeout
|
|
46
46
|
this.maxLifetime = options.maxLifetime
|
|
47
|
+
this.protocolVersion = options.protocolVersion || PROTOCOL_VERSION
|
|
47
48
|
|
|
48
49
|
this.namespace = options.namespace
|
|
49
50
|
this.apiHost = options.apiHost
|
|
@@ -98,7 +99,7 @@ class Sandbox {
|
|
|
98
99
|
if (options.policy !== undefined) body.policy = options.policy
|
|
99
100
|
if (options.ports !== undefined) body.ports = options.ports
|
|
100
101
|
|
|
101
|
-
const url = `${creds.apiHost}/
|
|
102
|
+
const url = `${creds.apiHost}${API_PREFIX}/namespaces/${creds.namespace}/sandboxes`
|
|
102
103
|
const payload = await apiRequest('POST', url, creds.apiKey, body)
|
|
103
104
|
|
|
104
105
|
const sandboxId = payload.sandboxId
|
|
@@ -112,6 +113,7 @@ class Sandbox {
|
|
|
112
113
|
region: payload.region,
|
|
113
114
|
idleTimeout: payload.idleTimeout,
|
|
114
115
|
maxLifetime: payload.maxLifetime,
|
|
116
|
+
protocolVersion: payload.protocolVersion || PROTOCOL_VERSION,
|
|
115
117
|
previewUrls: parsePreviewUrls(payload.previewUrls),
|
|
116
118
|
managementEndpoint: payload.managementEndpoint || null,
|
|
117
119
|
namespace: creds.namespace,
|
|
@@ -146,7 +148,7 @@ class Sandbox {
|
|
|
146
148
|
console.warn('[aio-lib-sandbox] alpha — APIs may change without notice')
|
|
147
149
|
const creds = resolveCredentials(options)
|
|
148
150
|
const base = options.managementEndpoint || creds.apiHost
|
|
149
|
-
const url = `${base}/
|
|
151
|
+
const url = `${base}${API_PREFIX}/namespaces/${creds.namespace}/sandboxes/${sandboxId}`
|
|
150
152
|
const payload = await apiRequest('GET', url, creds.apiKey)
|
|
151
153
|
|
|
152
154
|
return new Sandbox({
|
|
@@ -157,6 +159,7 @@ class Sandbox {
|
|
|
157
159
|
region: payload.region,
|
|
158
160
|
idleTimeout: payload.idleTimeout,
|
|
159
161
|
maxLifetime: payload.maxLifetime,
|
|
162
|
+
protocolVersion: payload.protocolVersion || PROTOCOL_VERSION,
|
|
160
163
|
managementEndpoint: payload.managementEndpoint || options.managementEndpoint || null,
|
|
161
164
|
previewUrls: parsePreviewUrls(payload.previewUrls),
|
|
162
165
|
namespace: creds.namespace,
|
|
@@ -175,6 +178,15 @@ class Sandbox {
|
|
|
175
178
|
return SANDBOX_SIZES
|
|
176
179
|
}
|
|
177
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Sandbox wire protocol major bundled with this SDK.
|
|
183
|
+
*
|
|
184
|
+
* @type {string}
|
|
185
|
+
*/
|
|
186
|
+
static get protocolVersion () {
|
|
187
|
+
return PROTOCOL_VERSION
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
/**
|
|
179
191
|
* Exposes `resolveCredentials` as a static helper (useful for testing).
|
|
180
192
|
*
|
|
@@ -507,7 +519,7 @@ class Sandbox {
|
|
|
507
519
|
*/
|
|
508
520
|
async destroy () {
|
|
509
521
|
const base = this.managementEndpoint || this.apiHost
|
|
510
|
-
const url = `${base}/
|
|
522
|
+
const url = `${base}${API_PREFIX}/namespaces/${this.namespace}/sandboxes/${this.id}`
|
|
511
523
|
this.ws?.beginIntentionalClose()
|
|
512
524
|
|
|
513
525
|
let payload
|
package/src/constants.js
CHANGED
|
@@ -16,4 +16,7 @@ const SANDBOX_SIZES = Object.freeze({
|
|
|
16
16
|
XLARGE: { cpu: '8000m', memory: '32Gi', gpu: 1 }
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const PROTOCOL_VERSION = '1'
|
|
20
|
+
const API_PREFIX = `/api/v${PROTOCOL_VERSION}`
|
|
21
|
+
|
|
22
|
+
module.exports = { SANDBOX_SIZES, PROTOCOL_VERSION, API_PREFIX }
|
package/src/errors.js
CHANGED
|
@@ -28,6 +28,8 @@ class SandboxWebSocketError extends SandboxSDKError {}
|
|
|
28
28
|
class SandboxCommandNotFoundError extends SandboxSDKError {}
|
|
29
29
|
class SandboxPortNotProvisionedError extends SandboxSDKError {}
|
|
30
30
|
class SandboxInvalidPortError extends SandboxClientError {}
|
|
31
|
+
class ProtocolVersionMismatchError extends SandboxClientError {}
|
|
32
|
+
class SandboxMalformedFrameError extends SandboxClientError {}
|
|
31
33
|
|
|
32
34
|
module.exports = {
|
|
33
35
|
SandboxSDKError,
|
|
@@ -39,5 +41,7 @@ module.exports = {
|
|
|
39
41
|
SandboxWebSocketError,
|
|
40
42
|
SandboxCommandNotFoundError,
|
|
41
43
|
SandboxPortNotProvisionedError,
|
|
42
|
-
SandboxInvalidPortError
|
|
44
|
+
SandboxInvalidPortError,
|
|
45
|
+
ProtocolVersionMismatchError,
|
|
46
|
+
SandboxMalformedFrameError
|
|
43
47
|
}
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@ governing permissions and limitations under the License.
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const Sandbox = require('./Sandbox')
|
|
13
|
+
const { PROTOCOL_VERSION } = require('./constants')
|
|
13
14
|
const {
|
|
14
15
|
SandboxSDKError,
|
|
15
16
|
SandboxInitializationError,
|
|
@@ -20,11 +21,14 @@ const {
|
|
|
20
21
|
SandboxWebSocketError,
|
|
21
22
|
SandboxCommandNotFoundError,
|
|
22
23
|
SandboxPortNotProvisionedError,
|
|
23
|
-
SandboxInvalidPortError
|
|
24
|
+
SandboxInvalidPortError,
|
|
25
|
+
ProtocolVersionMismatchError,
|
|
26
|
+
SandboxMalformedFrameError
|
|
24
27
|
} = require('./errors')
|
|
25
28
|
|
|
26
29
|
module.exports = {
|
|
27
30
|
Sandbox,
|
|
31
|
+
SANDBOX_PROTOCOL_VERSION: PROTOCOL_VERSION,
|
|
28
32
|
SandboxSDKError,
|
|
29
33
|
SandboxInitializationError,
|
|
30
34
|
SandboxClientError,
|
|
@@ -34,5 +38,7 @@ module.exports = {
|
|
|
34
38
|
SandboxWebSocketError,
|
|
35
39
|
SandboxCommandNotFoundError,
|
|
36
40
|
SandboxPortNotProvisionedError,
|
|
37
|
-
SandboxInvalidPortError
|
|
41
|
+
SandboxInvalidPortError,
|
|
42
|
+
ProtocolVersionMismatchError,
|
|
43
|
+
SandboxMalformedFrameError
|
|
38
44
|
}
|
package/src/utils.js
CHANGED
|
@@ -16,7 +16,7 @@ const {
|
|
|
16
16
|
SandboxUnauthorizedError,
|
|
17
17
|
SandboxTimeoutError
|
|
18
18
|
} = require('./errors')
|
|
19
|
-
const { SANDBOX_SIZES } = require('./constants')
|
|
19
|
+
const { SANDBOX_SIZES, API_PREFIX } = require('./constants')
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Builds a Basic authorization header from a Runtime API key.
|
|
@@ -72,7 +72,7 @@ function normalizeApiHost (host) {
|
|
|
72
72
|
function buildWebSocketEndpoint (apiHost, namespace, sandboxId) {
|
|
73
73
|
const url = new URL(apiHost)
|
|
74
74
|
url.protocol = url.protocol === 'http:' ? 'ws:' : 'wss:'
|
|
75
|
-
url.pathname =
|
|
75
|
+
url.pathname = `${API_PREFIX}/namespaces/${namespace}/sandboxes/${sandboxId}/exec`
|
|
76
76
|
url.search = ''
|
|
77
77
|
return url.toString()
|
|
78
78
|
}
|
package/src/ws.js
CHANGED
|
@@ -13,6 +13,8 @@ const WebSocket = require('ws')
|
|
|
13
13
|
const {
|
|
14
14
|
SandboxClientError,
|
|
15
15
|
SandboxCommandNotFoundError,
|
|
16
|
+
ProtocolVersionMismatchError,
|
|
17
|
+
SandboxMalformedFrameError,
|
|
16
18
|
SandboxUnauthorizedError,
|
|
17
19
|
SandboxWebSocketError
|
|
18
20
|
} = require('./errors')
|
|
@@ -355,6 +357,16 @@ class SandboxSocket {
|
|
|
355
357
|
`Sandbox '${this.id}' rejected the WebSocket authentication token`
|
|
356
358
|
)
|
|
357
359
|
}
|
|
360
|
+
if (code === 4003) {
|
|
361
|
+
return new ProtocolVersionMismatchError(
|
|
362
|
+
`Sandbox '${this.id}' WebSocket protocol version does not match this SDK`
|
|
363
|
+
)
|
|
364
|
+
}
|
|
365
|
+
if (code === 4004) {
|
|
366
|
+
return new SandboxMalformedFrameError(
|
|
367
|
+
`Sandbox '${this.id}' rejected a malformed WebSocket frame`
|
|
368
|
+
)
|
|
369
|
+
}
|
|
358
370
|
return new SandboxWebSocketError(
|
|
359
371
|
`Sandbox '${this.id}' WebSocket closed with code ${code}`
|
|
360
372
|
)
|
package/test/Sandbox.test.js
CHANGED
|
@@ -17,11 +17,13 @@ const {
|
|
|
17
17
|
SandboxCommandNotFoundError,
|
|
18
18
|
SandboxInitializationError,
|
|
19
19
|
SandboxNotFoundError,
|
|
20
|
+
ProtocolVersionMismatchError,
|
|
20
21
|
SandboxPortNotProvisionedError,
|
|
21
22
|
SandboxInvalidPortError,
|
|
22
23
|
SandboxTimeoutError,
|
|
23
24
|
SandboxUnauthorizedError,
|
|
24
|
-
SandboxWebSocketError
|
|
25
|
+
SandboxWebSocketError,
|
|
26
|
+
SandboxMalformedFrameError
|
|
25
27
|
} = require('../src/errors')
|
|
26
28
|
|
|
27
29
|
jest.mock('ws')
|
|
@@ -199,6 +201,12 @@ describe('Sandbox', () => {
|
|
|
199
201
|
})
|
|
200
202
|
})
|
|
201
203
|
|
|
204
|
+
describe('protocolVersion', () => {
|
|
205
|
+
test('exposes the bundled sandbox protocol major', () => {
|
|
206
|
+
expect(Sandbox.protocolVersion).toBe('1')
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
|
|
202
210
|
// -------------------------------------------------------------------------
|
|
203
211
|
// Static factories
|
|
204
212
|
// -------------------------------------------------------------------------
|
|
@@ -213,6 +221,7 @@ describe('Sandbox', () => {
|
|
|
213
221
|
status: 'ready',
|
|
214
222
|
token: 'tok-new',
|
|
215
223
|
maxLifetime: 3600,
|
|
224
|
+
protocolVersion: '1',
|
|
216
225
|
previewUrls: {
|
|
217
226
|
3000: 'https://sb-new-3000.preview.example.net'
|
|
218
227
|
}
|
|
@@ -236,6 +245,7 @@ describe('Sandbox', () => {
|
|
|
236
245
|
|
|
237
246
|
expect(sandbox.id).toBe('sb-new')
|
|
238
247
|
expect(sandbox.status).toBe('ready')
|
|
248
|
+
expect(sandbox.protocolVersion).toBe('1')
|
|
239
249
|
expect(sandbox.previewUrls).toEqual(new Map([
|
|
240
250
|
[3000, 'https://sb-new-3000.preview.example.net']
|
|
241
251
|
]))
|
|
@@ -471,7 +481,8 @@ describe('Sandbox', () => {
|
|
|
471
481
|
sandboxId: 'sb-get',
|
|
472
482
|
status: 'running',
|
|
473
483
|
cluster: 'cluster-b',
|
|
474
|
-
region: 'va6'
|
|
484
|
+
region: 'va6',
|
|
485
|
+
protocolVersion: '1'
|
|
475
486
|
})
|
|
476
487
|
})
|
|
477
488
|
|
|
@@ -484,6 +495,7 @@ describe('Sandbox', () => {
|
|
|
484
495
|
expect(sandbox.id).toBe('sb-get')
|
|
485
496
|
expect(sandbox.status).toBe('running')
|
|
486
497
|
expect(sandbox.cluster).toBe('cluster-b')
|
|
498
|
+
expect(sandbox.protocolVersion).toBe('1')
|
|
487
499
|
})
|
|
488
500
|
|
|
489
501
|
test('stores idleTimeout from the get response on the instance', async () => {
|
|
@@ -602,6 +614,22 @@ describe('Sandbox', () => {
|
|
|
602
614
|
await expect(p).rejects.toThrow(SandboxUnauthorizedError)
|
|
603
615
|
})
|
|
604
616
|
|
|
617
|
+
test('rejects on protocol mismatch close code 4003 with ProtocolVersionMismatchError', async () => {
|
|
618
|
+
const sandbox = new Sandbox(BASE_OPTIONS)
|
|
619
|
+
const p = sandbox.connect()
|
|
620
|
+
sockets[0].open()
|
|
621
|
+
sockets[0].closeWith(4003)
|
|
622
|
+
await expect(p).rejects.toThrow(ProtocolVersionMismatchError)
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
test('rejects on malformed frame close code 4004 with SandboxMalformedFrameError', async () => {
|
|
626
|
+
const sandbox = new Sandbox(BASE_OPTIONS)
|
|
627
|
+
const p = sandbox.connect()
|
|
628
|
+
sockets[0].open()
|
|
629
|
+
sockets[0].closeWith(4004)
|
|
630
|
+
await expect(p).rejects.toThrow(SandboxMalformedFrameError)
|
|
631
|
+
})
|
|
632
|
+
|
|
605
633
|
test('rejects on unexpected socket close', async () => {
|
|
606
634
|
const sandbox = new Sandbox(BASE_OPTIONS)
|
|
607
635
|
const p = sandbox.connect()
|