@aerol-ai/aerolvm-sdk 0.8.1 → 0.8.2
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/dist/MicroVM.d.ts +133 -51
- package/dist/MicroVM.js +207 -99
- package/dist/errors.d.ts +52 -0
- package/dist/errors.js +89 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/internal/client.d.ts +222 -33
- package/dist/internal/client.js +1110 -83
- package/dist/internal/tar.d.ts +14 -0
- package/dist/internal/tar.js +79 -0
- package/dist/types.d.ts +448 -2
- package/package.json +1 -1
package/dist/MicroVM.js
CHANGED
|
@@ -4,10 +4,8 @@ const defaultAPIURL = "http://127.0.0.1:21212";
|
|
|
4
4
|
const authRequiredErrorMessage = "PAT token is required. Set patToken, SB_PAT_TOKEN or SB_API_TOKEN.";
|
|
5
5
|
export class MicroVM {
|
|
6
6
|
apiUrl;
|
|
7
|
-
patToken;
|
|
8
7
|
/** The team sent as `X-AerolVM-Team`, or `""` when none is. */
|
|
9
8
|
team;
|
|
10
|
-
client;
|
|
11
9
|
constructor(config = {}) {
|
|
12
10
|
const patToken = config.patToken ?? readEnv("SB_PAT_TOKEN") ?? readEnv("SB_API_TOKEN") ?? "";
|
|
13
11
|
const apiUrl = normalizeURL(config.apiUrl ?? readEnv("SB_API_URL") ?? defaultAPIURL);
|
|
@@ -16,9 +14,9 @@ export class MicroVM {
|
|
|
16
14
|
throw new Error(authRequiredErrorMessage);
|
|
17
15
|
}
|
|
18
16
|
this.apiUrl = apiUrl;
|
|
19
|
-
this
|
|
17
|
+
Object.defineProperty(this, "patToken", { value: patToken, enumerable: false });
|
|
20
18
|
this.team = team;
|
|
21
|
-
|
|
19
|
+
const client = new APIClient({
|
|
22
20
|
baseURL: apiUrl,
|
|
23
21
|
patToken,
|
|
24
22
|
team,
|
|
@@ -27,26 +25,29 @@ export class MicroVM {
|
|
|
27
25
|
retry: config.retry,
|
|
28
26
|
signal: config.signal,
|
|
29
27
|
});
|
|
28
|
+
Object.defineProperty(this, "client", { value: client, enumerable: false });
|
|
30
29
|
}
|
|
31
|
-
async create(options) {
|
|
32
|
-
const sandbox = await this.
|
|
33
|
-
|
|
30
|
+
async create(options, call) {
|
|
31
|
+
const sandbox = await this.clientFor(call).create(options);
|
|
32
|
+
const wrapped = this.wrap(sandbox.toJSON());
|
|
33
|
+
wrapped.destroyOnExit = options.destroyOnExit ?? false;
|
|
34
|
+
return wrapped;
|
|
34
35
|
}
|
|
35
|
-
async list(options) {
|
|
36
|
-
const sandboxes = await this.
|
|
36
|
+
async list(options, call) {
|
|
37
|
+
const sandboxes = await this.clientFor(call).list(options);
|
|
37
38
|
return sandboxes.map((sandbox) => this.wrap(sandbox.toJSON()));
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* Iterates one server page at a time. Use this for large fleet inventories so
|
|
41
42
|
* the SDK does not retain every sandbox in memory.
|
|
42
43
|
*/
|
|
43
|
-
async *listPages(options) {
|
|
44
|
-
for await (const page of this.
|
|
44
|
+
async *listPages(options, call) {
|
|
45
|
+
for await (const page of this.clientFor(call).listPages(options)) {
|
|
45
46
|
yield page.map((sandbox) => this.wrap(sandbox.toJSON()));
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
async get(id, options) {
|
|
49
|
-
const sandbox = await this.
|
|
49
|
+
async get(id, options, call) {
|
|
50
|
+
const sandbox = await this.clientFor(call).get(id, options);
|
|
50
51
|
return this.wrap(sandbox.toJSON());
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
@@ -54,52 +55,81 @@ export class MicroVM {
|
|
|
54
55
|
* Names are unique per owner. Throws when the server predates name lookup
|
|
55
56
|
* (it ignores `?name=`), rather than guessing from an unfiltered list.
|
|
56
57
|
*/
|
|
57
|
-
async getByName(name, options) {
|
|
58
|
-
const sandbox = await this.
|
|
58
|
+
async getByName(name, options, call) {
|
|
59
|
+
const sandbox = await this.clientFor(call).getByName(name, options);
|
|
59
60
|
return sandbox === null ? null : this.wrap(sandbox.toJSON());
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Returns the caller's sandbox called `name`, creating it from `options`
|
|
64
|
+
* when there is none. `created` is true only when this call made the
|
|
65
|
+
* sandbox. Safe to retry and to run at the same time from many processes:
|
|
66
|
+
* names are unique per owner, so when two callers race to create the same
|
|
67
|
+
* name, one gets a 409 and reads the winner's sandbox instead. An existing
|
|
68
|
+
* sandbox is returned as it is; its image and settings are not compared
|
|
69
|
+
* with `options`.
|
|
70
|
+
*/
|
|
71
|
+
async getOrCreate(name, options, call) {
|
|
72
|
+
const result = await this.clientFor(call).getOrCreate(name, options);
|
|
73
|
+
const sandbox = this.wrap(result.sandbox.toJSON());
|
|
74
|
+
// destroyOnExit applies only to a sandbox this call created. One it found
|
|
75
|
+
// may be in use by another program that shares the name.
|
|
76
|
+
sandbox.destroyOnExit = result.created ? (options.destroyOnExit ?? false) : false;
|
|
77
|
+
return { sandbox, created: result.created };
|
|
78
|
+
}
|
|
79
|
+
async start(id, call) {
|
|
80
|
+
const sandbox = await this.clientFor(call).start(id);
|
|
63
81
|
return this.wrap(sandbox.toJSON());
|
|
64
82
|
}
|
|
65
|
-
async stop(id) {
|
|
66
|
-
const sandbox = await this.
|
|
83
|
+
async stop(id, call) {
|
|
84
|
+
const sandbox = await this.clientFor(call).stop(id);
|
|
67
85
|
return this.wrap(sandbox.toJSON());
|
|
68
86
|
}
|
|
69
|
-
async createSnapshot(id, name, options = {}) {
|
|
70
|
-
return this.
|
|
87
|
+
async createSnapshot(id, name, options = {}, call) {
|
|
88
|
+
return this.clientFor(call).createSnapshot(id, name, options);
|
|
71
89
|
}
|
|
72
|
-
async registerSnapshot(options) {
|
|
73
|
-
return this.
|
|
90
|
+
async registerSnapshot(options, call) {
|
|
91
|
+
return this.clientFor(call).registerSnapshot(options);
|
|
74
92
|
}
|
|
75
|
-
async registerSnapshotFromImage(name, image, options = {}) {
|
|
76
|
-
return this.
|
|
93
|
+
async registerSnapshotFromImage(name, image, options = {}, call) {
|
|
94
|
+
return this.clientFor(call).registerSnapshotFromImage(name, image, options);
|
|
77
95
|
}
|
|
78
96
|
/** Look a snapshot up by name. In a cluster the request is routed to the node holding the image. */
|
|
79
|
-
async getSnapshot(name) {
|
|
80
|
-
return this.
|
|
97
|
+
async getSnapshot(name, call) {
|
|
98
|
+
return this.clientFor(call).getSnapshot(name);
|
|
81
99
|
}
|
|
82
100
|
/** List the caller's snapshots, one name-ordered page at a time. */
|
|
83
|
-
async listSnapshots(options = {}) {
|
|
84
|
-
return this.
|
|
101
|
+
async listSnapshots(options = {}, call) {
|
|
102
|
+
return this.clientFor(call).listSnapshots(options);
|
|
85
103
|
}
|
|
86
104
|
/** Delete a snapshot by name (idempotent 404 if it does not exist). */
|
|
87
|
-
async deleteSnapshot(name) {
|
|
88
|
-
return this.
|
|
105
|
+
async deleteSnapshot(name, call) {
|
|
106
|
+
return this.clientFor(call).deleteSnapshot(name);
|
|
107
|
+
}
|
|
108
|
+
async destroy(id, call) {
|
|
109
|
+
await this.clientFor(call).destroy(id);
|
|
89
110
|
}
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Deletes every sandbox of yours that carries all of `options.tags` and
|
|
113
|
+
* returns the IDs of the ones now gone. It lists every page first, then
|
|
114
|
+
* deletes them one at a time. A sandbox that is already gone (404) counts
|
|
115
|
+
* as deleted, so a second call, or two calls at once, is safe. Any other
|
|
116
|
+
* failed delete stops the call and is thrown; the sandboxes already
|
|
117
|
+
* deleted stay deleted, and calling it again finishes the job. `tags`
|
|
118
|
+
* must not be empty.
|
|
119
|
+
*/
|
|
120
|
+
async destroyAll(options, call) {
|
|
121
|
+
return this.clientFor(call).destroyAll(options.tags);
|
|
92
122
|
}
|
|
93
|
-
async resize(id, options) {
|
|
94
|
-
const sandbox = await this.
|
|
123
|
+
async resize(id, options, call) {
|
|
124
|
+
const sandbox = await this.clientFor(call).resize(id, options);
|
|
95
125
|
return this.wrap(sandbox.toJSON());
|
|
96
126
|
}
|
|
97
|
-
async updateLifecycle(id, lifecycle) {
|
|
98
|
-
const sandbox = await this.
|
|
127
|
+
async updateLifecycle(id, lifecycle, call) {
|
|
128
|
+
const sandbox = await this.clientFor(call).updateLifecycle(id, lifecycle);
|
|
99
129
|
return this.wrap(sandbox.toJSON());
|
|
100
130
|
}
|
|
101
|
-
async reconcile() {
|
|
102
|
-
await this.
|
|
131
|
+
async reconcile(call) {
|
|
132
|
+
await this.clientFor(call).reconcile();
|
|
103
133
|
}
|
|
104
134
|
/**
|
|
105
135
|
* Build an {@link Image} on the daemon and optionally push the result to a
|
|
@@ -107,40 +137,103 @@ export class MicroVM {
|
|
|
107
137
|
* persisted by the daemon. Returns the local content-addressed tag and,
|
|
108
138
|
* when push was requested, the pushed reference.
|
|
109
139
|
*/
|
|
110
|
-
async buildImage(image, options) {
|
|
111
|
-
return this.
|
|
140
|
+
async buildImage(image, options, call) {
|
|
141
|
+
return this.clientFor(call).buildImage(image, options);
|
|
112
142
|
}
|
|
113
|
-
async health() {
|
|
114
|
-
return this.
|
|
143
|
+
async health(call) {
|
|
144
|
+
return this.clientFor(call).health();
|
|
115
145
|
}
|
|
116
146
|
/**
|
|
117
147
|
* Asks whether a sandbox created with these egress fields would reach a
|
|
118
148
|
* destination, using the same matcher the filter enforces. No sandbox is
|
|
119
149
|
* needed.
|
|
120
150
|
*/
|
|
121
|
-
async checkNetworkPolicy(options) {
|
|
122
|
-
return this.
|
|
151
|
+
async checkNetworkPolicy(options, call) {
|
|
152
|
+
return this.clientFor(call).checkNetworkPolicy(options);
|
|
123
153
|
}
|
|
124
154
|
/**
|
|
125
155
|
* Creates or replaces a named egress profile (a full replace: the same body
|
|
126
156
|
* twice is a no-op). Sandboxes reference it through `egressProfiles`, and a
|
|
127
157
|
* change reaches every one of them.
|
|
128
158
|
*/
|
|
129
|
-
async putEgressProfile(name, options) {
|
|
130
|
-
return this.
|
|
159
|
+
async putEgressProfile(name, options, call) {
|
|
160
|
+
return this.clientFor(call).putEgressProfile(name, options);
|
|
131
161
|
}
|
|
132
|
-
async getEgressProfile(name) {
|
|
133
|
-
return this.
|
|
162
|
+
async getEgressProfile(name, call) {
|
|
163
|
+
return this.clientFor(call).getEgressProfile(name);
|
|
134
164
|
}
|
|
135
|
-
async listEgressProfiles(options) {
|
|
136
|
-
return this.
|
|
165
|
+
async listEgressProfiles(options, call) {
|
|
166
|
+
return this.clientFor(call).listEgressProfiles(options);
|
|
137
167
|
}
|
|
138
168
|
/** Deletes a profile; one that sandboxes still reference is refused (409). */
|
|
139
|
-
async deleteEgressProfile(name) {
|
|
140
|
-
return this.
|
|
169
|
+
async deleteEgressProfile(name, call) {
|
|
170
|
+
return this.clientFor(call).deleteEgressProfile(name);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Sets how many ready sandboxes every server with a warm pool keeps for an
|
|
174
|
+
* image (a full replace: the same call twice is a no-op). A create that names
|
|
175
|
+
* the image then starts from a warm sandbox. Admin only.
|
|
176
|
+
*/
|
|
177
|
+
async putWarmPool(image, options, call) {
|
|
178
|
+
return this.clientFor(call).putWarmPool(image, options);
|
|
179
|
+
}
|
|
180
|
+
/** Returns an image's warm-pool entry with its status (ready and target, per server). */
|
|
181
|
+
async getWarmPool(image, call) {
|
|
182
|
+
return this.clientFor(call).getWarmPool(image);
|
|
183
|
+
}
|
|
184
|
+
/** Returns every warm-pool entry, by image, with its status. */
|
|
185
|
+
async listWarmPools(call) {
|
|
186
|
+
return this.clientFor(call).listWarmPools();
|
|
187
|
+
}
|
|
188
|
+
/** Deletes an image's warm-pool entry; its warm sandboxes are removed. Deleting a missing entry succeeds. */
|
|
189
|
+
async deleteWarmPool(image, call) {
|
|
190
|
+
return this.clientFor(call).deleteWarmPool(image);
|
|
141
191
|
}
|
|
142
|
-
|
|
143
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Puts a role tag on a team's cloud identity allow list, or changes its
|
|
194
|
+
* minimum caller role (`"runner"` or `"admin"`). Admin only. The same call
|
|
195
|
+
* twice changes nothing, so it is safe to retry.
|
|
196
|
+
*/
|
|
197
|
+
async putIdentityRole(tag, options, call) {
|
|
198
|
+
return this.clientFor(call).putIdentityRole(tag, options);
|
|
199
|
+
}
|
|
200
|
+
/** Lists a team's cloud identity allow list, one page at a time. Admin only. */
|
|
201
|
+
async listIdentityRoles(options, call) {
|
|
202
|
+
return this.clientFor(call).listIdentityRoles(options);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Takes a role tag off a team's allow list. Admin only. Sandboxes that use
|
|
206
|
+
* it keep their current token (at most one hour) and get no new one.
|
|
207
|
+
* Deleting a tag that is already gone succeeds.
|
|
208
|
+
*/
|
|
209
|
+
async deleteIdentityRole(tag, options, call) {
|
|
210
|
+
return this.clientFor(call).deleteIdentityRole(tag, options);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Sets a team's quota: the most sandboxes, CPU and memory its sandboxes
|
|
214
|
+
* may hold. Admin only. The same limits twice change nothing. A create,
|
|
215
|
+
* resize or start past the quota fails with 429 `team_quota_exceeded`.
|
|
216
|
+
*/
|
|
217
|
+
async putTeamQuota(team, options, call) {
|
|
218
|
+
return this.clientFor(call).putTeamQuota(team, options);
|
|
219
|
+
}
|
|
220
|
+
/** Reads a team's quota and what the team holds now. 404 if it has none. */
|
|
221
|
+
async getTeamQuota(team, call) {
|
|
222
|
+
return this.clientFor(call).getTeamQuota(team);
|
|
223
|
+
}
|
|
224
|
+
/** Removes a team's quota. Removing one that is already gone succeeds. */
|
|
225
|
+
async deleteTeamQuota(team, call) {
|
|
226
|
+
return this.clientFor(call).deleteTeamQuota(team);
|
|
227
|
+
}
|
|
228
|
+
async mounts(sandboxID, call) {
|
|
229
|
+
return this.clientFor(call).mounts(sandboxID);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Make every token issued for a sandbox so far stop working (see
|
|
233
|
+
* `sandbox.revokeTokens()`). A token made after the call works.
|
|
234
|
+
*/
|
|
235
|
+
async revokeSandboxTokens(sandboxID, call) {
|
|
236
|
+
return this.clientFor(call).revokeSandboxTokens(sandboxID);
|
|
144
237
|
}
|
|
145
238
|
/**
|
|
146
239
|
* Read a sandbox's clone-generation token. The token changes whenever the
|
|
@@ -148,35 +241,46 @@ export class MicroVM {
|
|
|
148
241
|
* Read-only — the SDK cannot reseed a process inside the guest; see the
|
|
149
242
|
* "Randomness in cloned sandboxes" docs page for the in-guest reseed pattern.
|
|
150
243
|
*/
|
|
151
|
-
async cloneGeneration(sandboxID) {
|
|
152
|
-
return this.
|
|
244
|
+
async cloneGeneration(sandboxID, call) {
|
|
245
|
+
return this.clientFor(call).cloneGeneration(sandboxID);
|
|
153
246
|
}
|
|
154
247
|
execStream(sandboxID, options) {
|
|
155
248
|
return this.client.execStream(sandboxID, options);
|
|
156
249
|
}
|
|
157
|
-
|
|
158
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Watch a folder in a sandbox for changes: `onEvent` gets each create,
|
|
252
|
+
* write, remove, rename and chmod, in batches every 250 ms. Resolves once
|
|
253
|
+
* the watch is in place. gVisor and Firecracker sandboxes only; Docker,
|
|
254
|
+
* containerd, WASM and isolate sandboxes reject with a 501
|
|
255
|
+
* `MicroVMApiError`. A sandbox whose agent predates file watching rejects
|
|
256
|
+
* with `MicroVMUnsupportedFeatureError`.
|
|
257
|
+
*/
|
|
258
|
+
async watchFiles(sandboxID, path, onEvent, options = {}) {
|
|
259
|
+
return this.client.watchFiles(sandboxID, path, onEvent, options);
|
|
260
|
+
}
|
|
261
|
+
async createSession(sandboxID, options, call) {
|
|
262
|
+
return this.clientFor(call).createSession(sandboxID, options);
|
|
159
263
|
}
|
|
160
|
-
async listSessions(sandboxID) {
|
|
161
|
-
return this.
|
|
264
|
+
async listSessions(sandboxID, call) {
|
|
265
|
+
return this.clientFor(call).listSessions(sandboxID);
|
|
162
266
|
}
|
|
163
|
-
async getSession(sandboxID, sessionID) {
|
|
164
|
-
return this.
|
|
267
|
+
async getSession(sandboxID, sessionID, call) {
|
|
268
|
+
return this.clientFor(call).getSession(sandboxID, sessionID);
|
|
165
269
|
}
|
|
166
|
-
async deleteSession(sandboxID, sessionID) {
|
|
167
|
-
await this.
|
|
270
|
+
async deleteSession(sandboxID, sessionID, call) {
|
|
271
|
+
await this.clientFor(call).deleteSession(sandboxID, sessionID);
|
|
168
272
|
}
|
|
169
|
-
async signalSession(sandboxID, sessionID, signal) {
|
|
170
|
-
await this.
|
|
273
|
+
async signalSession(sandboxID, sessionID, signal, call) {
|
|
274
|
+
await this.clientFor(call).signalSession(sandboxID, sessionID, signal);
|
|
171
275
|
}
|
|
172
|
-
async resizeSession(sandboxID, sessionID, cols, rows) {
|
|
173
|
-
await this.
|
|
276
|
+
async resizeSession(sandboxID, sessionID, cols, rows, call) {
|
|
277
|
+
await this.clientFor(call).resizeSession(sandboxID, sessionID, cols, rows);
|
|
174
278
|
}
|
|
175
|
-
async sessionLog(sandboxID, sessionID) {
|
|
176
|
-
return this.
|
|
279
|
+
async sessionLog(sandboxID, sessionID, call) {
|
|
280
|
+
return this.clientFor(call).sessionLog(sandboxID, sessionID);
|
|
177
281
|
}
|
|
178
|
-
async sessionRecording(sandboxID, sessionID) {
|
|
179
|
-
return this.
|
|
282
|
+
async sessionRecording(sandboxID, sessionID, call) {
|
|
283
|
+
return this.clientFor(call).sessionRecording(sandboxID, sessionID);
|
|
180
284
|
}
|
|
181
285
|
attachSession(sandboxID, sessionID, options = {}) {
|
|
182
286
|
return this.client.attachSession(sandboxID, sessionID, options);
|
|
@@ -191,42 +295,42 @@ export class MicroVM {
|
|
|
191
295
|
* duplicate ID returns 409 so a retried CI step does not create two
|
|
192
296
|
* rows for the same logical template.
|
|
193
297
|
*/
|
|
194
|
-
async createTemplate(options) {
|
|
195
|
-
return this.
|
|
298
|
+
async createTemplate(options, call) {
|
|
299
|
+
return this.clientFor(call).createTemplate(options);
|
|
196
300
|
}
|
|
197
|
-
async listTemplates() {
|
|
198
|
-
return this.
|
|
301
|
+
async listTemplates(call) {
|
|
302
|
+
return this.clientFor(call).listTemplates();
|
|
199
303
|
}
|
|
200
|
-
async getTemplate(id) {
|
|
201
|
-
return this.
|
|
304
|
+
async getTemplate(id, call) {
|
|
305
|
+
return this.clientFor(call).getTemplate(id);
|
|
202
306
|
}
|
|
203
|
-
async deleteTemplate(id) {
|
|
204
|
-
await this.
|
|
307
|
+
async deleteTemplate(id, call) {
|
|
308
|
+
await this.clientFor(call).deleteTemplate(id);
|
|
205
309
|
}
|
|
206
310
|
/**
|
|
207
311
|
* Register a WASM module in the host catalogue. Resolution is synchronous —
|
|
208
312
|
* the returned row is typically already `ready`. Use the row's `id` or
|
|
209
313
|
* `moduleRef` on subsequent `create` calls with `runtime: "wasm"`.
|
|
210
314
|
*/
|
|
211
|
-
async createWasmModule(options) {
|
|
212
|
-
return this.
|
|
315
|
+
async createWasmModule(options, call) {
|
|
316
|
+
return this.clientFor(call).createWasmModule(options);
|
|
213
317
|
}
|
|
214
|
-
async listWasmModules() {
|
|
215
|
-
return this.
|
|
318
|
+
async listWasmModules(call) {
|
|
319
|
+
return this.clientFor(call).listWasmModules();
|
|
216
320
|
}
|
|
217
|
-
async getWasmModule(id) {
|
|
218
|
-
return this.
|
|
321
|
+
async getWasmModule(id, call) {
|
|
322
|
+
return this.clientFor(call).getWasmModule(id);
|
|
219
323
|
}
|
|
220
|
-
async deleteWasmModule(id) {
|
|
221
|
-
await this.
|
|
324
|
+
async deleteWasmModule(id, call) {
|
|
325
|
+
await this.clientFor(call).deleteWasmModule(id);
|
|
222
326
|
}
|
|
223
327
|
/**
|
|
224
328
|
* Upload a compiled core-wasip1 module to the registry under your own
|
|
225
329
|
* credentials and get back the `oci://` ref to use as `moduleRef` on create.
|
|
226
330
|
* The daemon validates and forwards the bytes; it never stores them.
|
|
227
331
|
*/
|
|
228
|
-
async pushWasmModule(options) {
|
|
229
|
-
return this.
|
|
332
|
+
async pushWasmModule(options, call) {
|
|
333
|
+
return this.clientFor(call).pushWasmModule(options);
|
|
230
334
|
}
|
|
231
335
|
/**
|
|
232
336
|
* Re-run the snapshot phase against an existing template. Idempotent
|
|
@@ -239,8 +343,8 @@ export class MicroVM {
|
|
|
239
343
|
* where rebuild is not safe (build in flight) or not supported
|
|
240
344
|
* (`ready_no_snapshot` / `failed` — those need delete+recreate today).
|
|
241
345
|
*/
|
|
242
|
-
async rebuildTemplate(id) {
|
|
243
|
-
return this.
|
|
346
|
+
async rebuildTemplate(id, call) {
|
|
347
|
+
return this.clientFor(call).rebuildTemplate(id);
|
|
244
348
|
}
|
|
245
349
|
/**
|
|
246
350
|
* Cluster-level DNS helpers. Exposed as a namespaced accessor (rather
|
|
@@ -252,15 +356,15 @@ export class MicroVM {
|
|
|
252
356
|
get dns() {
|
|
253
357
|
const client = this.client;
|
|
254
358
|
return {
|
|
255
|
-
target: () => client.ingressDNS(),
|
|
359
|
+
target: (call) => client.withSignal(call?.signal).ingressDNS(),
|
|
256
360
|
};
|
|
257
361
|
}
|
|
258
362
|
/**
|
|
259
363
|
* Who the server says the caller is: principal, role, team and when the
|
|
260
364
|
* credential expires. Every valid credential may ask.
|
|
261
365
|
*/
|
|
262
|
-
async whoami() {
|
|
263
|
-
return this.
|
|
366
|
+
async whoami(call) {
|
|
367
|
+
return this.clientFor(call).whoami();
|
|
264
368
|
}
|
|
265
369
|
/**
|
|
266
370
|
* Scoped API tokens (`avm_…`) for services and CI, as
|
|
@@ -270,11 +374,15 @@ export class MicroVM {
|
|
|
270
374
|
get tokens() {
|
|
271
375
|
const client = this.client;
|
|
272
376
|
return {
|
|
273
|
-
create: (options) => client.createAPIToken(options),
|
|
274
|
-
list: () => client.listAPITokens(),
|
|
275
|
-
revoke: (id) => client.revokeAPIToken(id),
|
|
377
|
+
create: (options, call) => client.withSignal(call?.signal).createAPIToken(options),
|
|
378
|
+
list: (call) => client.withSignal(call?.signal).listAPITokens(),
|
|
379
|
+
revoke: (id, call) => client.withSignal(call?.signal).revokeAPIToken(id),
|
|
276
380
|
};
|
|
277
381
|
}
|
|
382
|
+
/** The client for one call: the real one, or a view carrying the call's signal. */
|
|
383
|
+
clientFor(call) {
|
|
384
|
+
return this.client.withSignal(call?.signal);
|
|
385
|
+
}
|
|
278
386
|
wrap(sandbox) {
|
|
279
387
|
return new Sandbox(this.client, sandbox);
|
|
280
388
|
}
|
package/dist/errors.d.ts
CHANGED
|
@@ -26,3 +26,55 @@ export declare class MicroVMApiError extends Error {
|
|
|
26
26
|
retryAfterMs?: number;
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
+
/** HTTP 404: the sandbox, file, snapshot or other thing the call named does not exist (or is not yours). */
|
|
30
|
+
export declare class MicroVMNotFoundError extends MicroVMApiError {
|
|
31
|
+
}
|
|
32
|
+
/** HTTP 409: the call clashes with what is there now, such as a sandbox name you already use. */
|
|
33
|
+
export declare class MicroVMConflictError extends MicroVMApiError {
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* HTTP 503: the server has no room for the call right now or is shedding
|
|
37
|
+
* load. The SDK has already retried it; try again later.
|
|
38
|
+
*/
|
|
39
|
+
export declare class MicroVMCapacityError extends MicroVMApiError {
|
|
40
|
+
}
|
|
41
|
+
/** HTTP 408 or 504: the server, or a proxy in front of it, gave up waiting. */
|
|
42
|
+
export declare class MicroVMTimeoutError extends MicroVMApiError {
|
|
43
|
+
}
|
|
44
|
+
/** HTTP 401 or 403: the token is missing, wrong or expired (401), or it may not do this (403). */
|
|
45
|
+
export declare class MicroVMAuthError extends MicroVMApiError {
|
|
46
|
+
}
|
|
47
|
+
/** The most specific {@link MicroVMApiError} subclass for a status. */
|
|
48
|
+
export declare function apiErrorFor(status: number, message: string, options?: {
|
|
49
|
+
code?: string;
|
|
50
|
+
retryAfterMs?: number;
|
|
51
|
+
}): MicroVMApiError;
|
|
52
|
+
/**
|
|
53
|
+
* The sandbox's agent (toolboxd) is older than an option this call needs. An
|
|
54
|
+
* older agent would silently ignore the option (an overwrite guard, an output
|
|
55
|
+
* cap), so the SDK refuses instead of sending it. Restart the sandbox, or
|
|
56
|
+
* re-create its Firecracker template, to get the current agent.
|
|
57
|
+
*/
|
|
58
|
+
export declare class MicroVMUnsupportedFeatureError extends Error {
|
|
59
|
+
/** The sandbox whose agent is too old. */
|
|
60
|
+
readonly sandboxID: string;
|
|
61
|
+
/** The features the agent did not list. */
|
|
62
|
+
readonly features: string[];
|
|
63
|
+
/** The agent's version when it reported one. */
|
|
64
|
+
readonly agentVersion: string;
|
|
65
|
+
/**
|
|
66
|
+
* Set (for example "wasm") when the sandbox's runtime cannot offer the
|
|
67
|
+
* features at all; a restart does not help there.
|
|
68
|
+
*/
|
|
69
|
+
readonly runtime: string;
|
|
70
|
+
constructor(sandboxID: string, features: string[], agentVersion?: string, runtime?: string);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A download was larger than its `maxBytes`. Thrown before reading when the
|
|
74
|
+
* server states the size, otherwise as soon as more arrives.
|
|
75
|
+
*/
|
|
76
|
+
export declare class MicroVMFileTooLargeError extends Error {
|
|
77
|
+
readonly path: string;
|
|
78
|
+
readonly maxBytes: number;
|
|
79
|
+
constructor(path: string, maxBytes: number);
|
|
80
|
+
}
|
package/dist/errors.js
CHANGED
|
@@ -29,3 +29,92 @@ export class MicroVMApiError extends Error {
|
|
|
29
29
|
this.retryAfterMs = options.retryAfterMs;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
+
// The typed errors below extend MicroVMApiError, so code that catches
|
|
33
|
+
// MicroVMApiError and reads `status` keeps working unchanged; new code can
|
|
34
|
+
// test `instanceof` for the one case it handles instead of comparing numbers.
|
|
35
|
+
// They keep `name` "MicroVMApiError": code that checks the name (often done
|
|
36
|
+
// where two copies of the SDK make instanceof unreliable) keeps working too.
|
|
37
|
+
/** HTTP 404: the sandbox, file, snapshot or other thing the call named does not exist (or is not yours). */
|
|
38
|
+
export class MicroVMNotFoundError extends MicroVMApiError {
|
|
39
|
+
}
|
|
40
|
+
/** HTTP 409: the call clashes with what is there now, such as a sandbox name you already use. */
|
|
41
|
+
export class MicroVMConflictError extends MicroVMApiError {
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* HTTP 503: the server has no room for the call right now or is shedding
|
|
45
|
+
* load. The SDK has already retried it; try again later.
|
|
46
|
+
*/
|
|
47
|
+
export class MicroVMCapacityError extends MicroVMApiError {
|
|
48
|
+
}
|
|
49
|
+
/** HTTP 408 or 504: the server, or a proxy in front of it, gave up waiting. */
|
|
50
|
+
export class MicroVMTimeoutError extends MicroVMApiError {
|
|
51
|
+
}
|
|
52
|
+
/** HTTP 401 or 403: the token is missing, wrong or expired (401), or it may not do this (403). */
|
|
53
|
+
export class MicroVMAuthError extends MicroVMApiError {
|
|
54
|
+
}
|
|
55
|
+
const API_ERROR_CLASSES = {
|
|
56
|
+
401: MicroVMAuthError,
|
|
57
|
+
403: MicroVMAuthError,
|
|
58
|
+
404: MicroVMNotFoundError,
|
|
59
|
+
408: MicroVMTimeoutError,
|
|
60
|
+
409: MicroVMConflictError,
|
|
61
|
+
503: MicroVMCapacityError,
|
|
62
|
+
504: MicroVMTimeoutError,
|
|
63
|
+
};
|
|
64
|
+
/** The most specific {@link MicroVMApiError} subclass for a status. */
|
|
65
|
+
export function apiErrorFor(status, message, options = {}) {
|
|
66
|
+
const ErrorClass = API_ERROR_CLASSES[status] ?? MicroVMApiError;
|
|
67
|
+
return new ErrorClass(status, message, options);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The sandbox's agent (toolboxd) is older than an option this call needs. An
|
|
71
|
+
* older agent would silently ignore the option (an overwrite guard, an output
|
|
72
|
+
* cap), so the SDK refuses instead of sending it. Restart the sandbox, or
|
|
73
|
+
* re-create its Firecracker template, to get the current agent.
|
|
74
|
+
*/
|
|
75
|
+
export class MicroVMUnsupportedFeatureError extends Error {
|
|
76
|
+
/** The sandbox whose agent is too old. */
|
|
77
|
+
sandboxID;
|
|
78
|
+
/** The features the agent did not list. */
|
|
79
|
+
features;
|
|
80
|
+
/** The agent's version when it reported one. */
|
|
81
|
+
agentVersion;
|
|
82
|
+
/**
|
|
83
|
+
* Set (for example "wasm") when the sandbox's runtime cannot offer the
|
|
84
|
+
* features at all; a restart does not help there.
|
|
85
|
+
*/
|
|
86
|
+
runtime;
|
|
87
|
+
constructor(sandboxID, features, agentVersion = "", runtime = "") {
|
|
88
|
+
const agent = agentVersion ? `toolboxd ${agentVersion}` : "an older toolboxd";
|
|
89
|
+
super(runtime
|
|
90
|
+
? `sandbox ${sandboxID} is a ${runtimeDisplayName(runtime)} sandbox, which does not support ${features.join(", ")}`
|
|
91
|
+
: `sandbox ${sandboxID} runs ${agent}, which does not support ${features.join(", ")}; ` +
|
|
92
|
+
"restart the sandbox, or re-create its Firecracker template, to get the current agent");
|
|
93
|
+
this.name = "MicroVMUnsupportedFeatureError";
|
|
94
|
+
this.sandboxID = sandboxID;
|
|
95
|
+
this.features = features;
|
|
96
|
+
this.agentVersion = agentVersion;
|
|
97
|
+
this.runtime = runtime;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function runtimeDisplayName(runtime) {
|
|
101
|
+
if (runtime === "wasm")
|
|
102
|
+
return "WebAssembly";
|
|
103
|
+
if (runtime === "isolate")
|
|
104
|
+
return "V8 isolate";
|
|
105
|
+
return runtime;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A download was larger than its `maxBytes`. Thrown before reading when the
|
|
109
|
+
* server states the size, otherwise as soon as more arrives.
|
|
110
|
+
*/
|
|
111
|
+
export class MicroVMFileTooLargeError extends Error {
|
|
112
|
+
path;
|
|
113
|
+
maxBytes;
|
|
114
|
+
constructor(path, maxBytes) {
|
|
115
|
+
super(`${path} is larger than maxBytes (${maxBytes} bytes)`);
|
|
116
|
+
this.name = "MicroVMFileTooLargeError";
|
|
117
|
+
this.path = path;
|
|
118
|
+
this.maxBytes = maxBytes;
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { MicroVM } from "./MicroVM.js";
|
|
2
2
|
export { Sandbox } from "./Sandbox.js";
|
|
3
3
|
export { Image } from "./Image.js";
|
|
4
|
-
export { MicroVMApiError } from "./errors.js";
|
|
5
|
-
export
|
|
4
|
+
export { MicroVMApiError, MicroVMAuthError, MicroVMCapacityError, MicroVMConflictError, MicroVMFileTooLargeError, MicroVMNotFoundError, MicroVMTimeoutError, MicroVMUnsupportedFeatureError, } from "./errors.js";
|
|
5
|
+
export { DEFAULT_LIST_LIMIT } from "./internal/client.js";
|
|
6
|
+
export type { GetOrCreateResult, MicroVMConfig, Tokens } from "./MicroVM.js";
|
|
6
7
|
export type { RetryConfig } from "./internal/client.js";
|
|
7
|
-
export type { AddCustomDomainOptions, APIToken, APITokenList, CreateAPITokenOptions, CreatedAPIToken, WhoAmI, WhoAmIPrincipal, AuditEvent, AuditOptions, AuditPage, EgressProfile, EgressProfileList, EgressProfileOptions, EgressProfileRef, EgressInject, EgressRule, ListEgressProfilesOptions, NetworkLearned, NetworkLearnedEntry, NetworkPolicy, NetworkPolicyCheckOptions, NetworkPolicyCheckResult, NetworkPolicyOptions, BinaryLike, BuildImageOptions, BuildImagePushOptions, BuildImageResult, CloneGeneration, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, CustomDomain, CustomDomainDNSRecords, CustomDomainStatus, DNSRecord, DNSRecordType, ExecRequest, ExecResult, ExecExitInfo, ExposedPort, ExposePortOptions, ExposeProtocol, ExposeResult, Failover, FailoverPolicy, GetOptions, HealthStatus, IngressTarget, IngressTargetSource, Lifecycle, ListOptions, MountSpec, MountSpecRedacted, MountType, PlatformVolumeMount, CreateSnapshotOptions, RegisterSnapshotOptions, ListSnapshotsOptions, SnapshotList, RegistryAuth, ResizeOptions, Sandbox as SandboxData, SandboxSnapshot, SandboxStatus, Session, SessionAttachHandle, SessionAttachOptions, SessionStatus, Template, TemplatePushState, TemplateStatus, WasmModule, WasmModuleStatus, PushWasmModuleOptions, PushWasmModuleResult, UpdateLifecycleOptions, } from "./types.js";
|
|
8
|
+
export type { AddCustomDomainOptions, APIToken, APITokenList, CreateAPITokenOptions, CreatedAPIToken, CreateSandboxTokenOptions, RevokeSandboxTokensResult, SandboxToken, WhoAmI, WhoAmIPrincipal, AuditEvent, AuditOptions, AuditPage, EgressProfile, EgressProfileList, EgressProfileOptions, EgressProfileRef, IdentityOptions, IdentityRole, IdentityRoleList, IdentityRoleOptions, ListIdentityRolesOptions, SandboxIdentity, EgressInject, EgressRule, ListEgressProfilesOptions, WarmPool, WarmPoolOnImageChange, WarmPoolOptions, WarmPoolServerStatus, WarmPoolStatus, NetworkLearned, NetworkLearnedEntry, NetworkPolicy, NetworkPolicyCheckOptions, NetworkPolicyCheckResult, NetworkPolicyOptions, BinaryLike, BuildImageOptions, BuildImagePushOptions, CallOptions, BuildImageResult, CloneGeneration, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, DestroyAllOptions, CustomDomain, CustomDomainDNSRecords, CustomDomainStatus, DNSRecord, DNSRecordType, ExecRequest, ExecResult, ExecExitInfo, ExposedPort, ExposePortOptions, ExposeProtocol, ExposeResult, ExposeVisibility, Failover, FailoverPolicy, FileEvent, FileEventType, FileWatchHandle, FileInfo, FileList, UploadFileOptions, DownloadFileOptions, FileMatch, ListFilesOptions, DeleteFileOptions, MakeDirOptions, MoveFileOptions, CopyFileOptions, PlacementRule, TeamQuota, TeamQuotaOptions, TeamQuotaUsage, GetOptions, HealthStatus, IngressTarget, IngressTargetSource, Lifecycle, ListOptions, MountSpec, MountSpecRedacted, MountType, PlatformVolumeMount, CreateSnapshotOptions, RegisterSnapshotOptions, ListSnapshotsOptions, SnapshotList, RegistryAuth, ResizeOptions, Sandbox as SandboxData, SandboxSnapshot, SandboxStatus, StatusReason, Session, SessionAttachHandle, SessionAttachOptions, SessionStatus, Template, TemplatePushState, TemplateStatus, WasmModule, WasmModuleStatus, PushWasmModuleOptions, PushWasmModuleResult, UpdateLifecycleOptions, WatchFilesOptions, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { MicroVM } from "./MicroVM.js";
|
|
2
2
|
export { Sandbox } from "./Sandbox.js";
|
|
3
3
|
export { Image } from "./Image.js";
|
|
4
|
-
export { MicroVMApiError } from "./errors.js";
|
|
4
|
+
export { MicroVMApiError, MicroVMAuthError, MicroVMCapacityError, MicroVMConflictError, MicroVMFileTooLargeError, MicroVMNotFoundError, MicroVMTimeoutError, MicroVMUnsupportedFeatureError, } from "./errors.js";
|
|
5
|
+
export { DEFAULT_LIST_LIMIT } from "./internal/client.js";
|