freestyle-sandboxes 0.1.41 → 0.1.43
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/index.cjs +183 -34
- package/index.d.cts +41 -9
- package/index.d.mts +41 -9
- package/index.mjs +183 -34
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -3763,6 +3763,9 @@ class ApiClient {
|
|
|
3763
3763
|
};
|
|
3764
3764
|
return this.fetchFn(url, finalOptions);
|
|
3765
3765
|
}
|
|
3766
|
+
resolveUrl(path, params, query) {
|
|
3767
|
+
return this.buildUrl(path, params, query);
|
|
3768
|
+
}
|
|
3766
3769
|
getRaw(path, options) {
|
|
3767
3770
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3768
3771
|
return this.requestRaw("GET", url, void 0, options?.headers);
|
|
@@ -3777,6 +3780,11 @@ class ApiClient {
|
|
|
3777
3780
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3778
3781
|
return this.request("POST", url, options?.body, options?.headers);
|
|
3779
3782
|
}
|
|
3783
|
+
postRaw(path, ...args) {
|
|
3784
|
+
const options = args[0];
|
|
3785
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3786
|
+
return this.requestRaw("POST", url, options?.body, options?.headers);
|
|
3787
|
+
}
|
|
3780
3788
|
put(path, ...args) {
|
|
3781
3789
|
const options = args[0];
|
|
3782
3790
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
@@ -5648,6 +5656,7 @@ function composeCreateVmOptions(arr) {
|
|
|
5648
5656
|
result.activityThresholdBytes = options.activityThresholdBytes;
|
|
5649
5657
|
if (options.discriminator !== void 0)
|
|
5650
5658
|
result.discriminator = options.discriminator;
|
|
5659
|
+
if (options.skipCache !== void 0) result.skipCache = options.skipCache;
|
|
5651
5660
|
if (options.persistence !== void 0)
|
|
5652
5661
|
result.persistence = options.persistence;
|
|
5653
5662
|
if (options.ports !== void 0) {
|
|
@@ -5795,6 +5804,7 @@ function composeCreateVmOptions(arr) {
|
|
|
5795
5804
|
aptDeps: newTemplate.aptDeps ?? baseTemplate.aptDeps,
|
|
5796
5805
|
vcpuCount: newTemplate.vcpuCount !== void 0 ? newTemplate.vcpuCount : baseTemplate.vcpuCount,
|
|
5797
5806
|
discriminator: newTemplate.discriminator ?? baseTemplate.discriminator,
|
|
5807
|
+
skipCache: newTemplate.skipCache ?? baseTemplate.skipCache,
|
|
5798
5808
|
workdir: newTemplate.workdir !== void 0 ? newTemplate.workdir : baseTemplate.workdir,
|
|
5799
5809
|
idleTimeoutSeconds: newTemplate.idleTimeoutSeconds !== void 0 ? newTemplate.idleTimeoutSeconds : baseTemplate.idleTimeoutSeconds,
|
|
5800
5810
|
waitForReadySignal: newTemplate.waitForReadySignal !== void 0 ? newTemplate.waitForReadySignal : baseTemplate.waitForReadySignal,
|
|
@@ -6011,6 +6021,94 @@ function composeVmSpecs(specs) {
|
|
|
6011
6021
|
const DEFAULT_CONFIGURE_BASE_IMAGE = "FROM debian:trixie-slim";
|
|
6012
6022
|
const RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX = "freestyle-run-command";
|
|
6013
6023
|
const WAIT_FOR_SYSTEMD_SERVICE_PREFIX = "freestyle-wait-for";
|
|
6024
|
+
const BACKGROUND_AFTER_SECS_HEADER = "x-freestyle-background-after-secs";
|
|
6025
|
+
const BACKGROUND_REQUEST_ID_HEADER = "x-freestyle-background-request-id";
|
|
6026
|
+
const DEFAULT_BACKGROUND_AFTER_SECS = 5;
|
|
6027
|
+
const DEFAULT_BACKGROUND_POLL_INTERVAL_MS = 2e3;
|
|
6028
|
+
function delay(ms) {
|
|
6029
|
+
const timerApi = globalThis;
|
|
6030
|
+
return new Promise((resolve) => timerApi.setTimeout(resolve, ms));
|
|
6031
|
+
}
|
|
6032
|
+
function extractBackgroundRequestId(response, body) {
|
|
6033
|
+
return response.headers.get(BACKGROUND_REQUEST_ID_HEADER) ?? body?.requestId ?? body?.request_id;
|
|
6034
|
+
}
|
|
6035
|
+
async function parseJsonResponse(response) {
|
|
6036
|
+
return await response.json();
|
|
6037
|
+
}
|
|
6038
|
+
async function readResponseError(response, fallbackMessage) {
|
|
6039
|
+
const responseText = await response.text();
|
|
6040
|
+
if (!responseText) {
|
|
6041
|
+
return fallbackMessage;
|
|
6042
|
+
}
|
|
6043
|
+
try {
|
|
6044
|
+
const errorBody = JSON.parse(responseText);
|
|
6045
|
+
return errorBody.message ?? errorBody.error ?? responseText;
|
|
6046
|
+
} catch {
|
|
6047
|
+
return responseText;
|
|
6048
|
+
}
|
|
6049
|
+
}
|
|
6050
|
+
async function emitBackgroundLogs(apiClient, requestId, logger, seenLogs) {
|
|
6051
|
+
const response = await apiClient.fetch(
|
|
6052
|
+
apiClient.resolveUrl("/observability/v1/logs", void 0, { requestId }),
|
|
6053
|
+
{ method: "GET" }
|
|
6054
|
+
);
|
|
6055
|
+
if (!response.ok) {
|
|
6056
|
+
return;
|
|
6057
|
+
}
|
|
6058
|
+
const payload = await response.json();
|
|
6059
|
+
for (const entry of payload.logs ?? []) {
|
|
6060
|
+
const key = `${entry.timestamp} ${entry.message}`;
|
|
6061
|
+
if (seenLogs.has(key)) {
|
|
6062
|
+
continue;
|
|
6063
|
+
}
|
|
6064
|
+
seenLogs.add(key);
|
|
6065
|
+
logger(`[${entry.timestamp}] ${entry.message}`);
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
async function waitForBackgroundRequest(apiClient, requestId, logger) {
|
|
6069
|
+
const seenLogs = /* @__PURE__ */ new Set();
|
|
6070
|
+
const resultUrl = apiClient.resolveUrl(
|
|
6071
|
+
`/auth/v1/background-requests/${encodeURIComponent(requestId)}`
|
|
6072
|
+
);
|
|
6073
|
+
while (true) {
|
|
6074
|
+
await emitBackgroundLogs(apiClient, requestId, logger, seenLogs);
|
|
6075
|
+
const response = await apiClient.fetch(resultUrl, { method: "GET" });
|
|
6076
|
+
if (response.status === 202) {
|
|
6077
|
+
await delay(DEFAULT_BACKGROUND_POLL_INTERVAL_MS);
|
|
6078
|
+
continue;
|
|
6079
|
+
}
|
|
6080
|
+
if (!response.ok) {
|
|
6081
|
+
const message = await readResponseError(
|
|
6082
|
+
response,
|
|
6083
|
+
`Background request ${requestId} failed`
|
|
6084
|
+
);
|
|
6085
|
+
throw new Error(message);
|
|
6086
|
+
}
|
|
6087
|
+
return parseJsonResponse(response);
|
|
6088
|
+
}
|
|
6089
|
+
}
|
|
6090
|
+
async function postWithBackgroundLogger(apiClient, path, options, logger) {
|
|
6091
|
+
const response = await apiClient.postRaw(path, {
|
|
6092
|
+
...options,
|
|
6093
|
+
headers: logger ? {
|
|
6094
|
+
...options.headers ?? {},
|
|
6095
|
+
[BACKGROUND_AFTER_SECS_HEADER]: String(DEFAULT_BACKGROUND_AFTER_SECS)
|
|
6096
|
+
} : options.headers
|
|
6097
|
+
});
|
|
6098
|
+
if (response.status !== 202 || !logger) {
|
|
6099
|
+
return parseJsonResponse(response);
|
|
6100
|
+
}
|
|
6101
|
+
const accepted = await parseJsonResponse(
|
|
6102
|
+
response
|
|
6103
|
+
);
|
|
6104
|
+
const requestId = extractBackgroundRequestId(response, accepted);
|
|
6105
|
+
if (!requestId) {
|
|
6106
|
+
throw new Error(
|
|
6107
|
+
`Background request response for ${path} did not include a request ID`
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
return waitForBackgroundRequest(apiClient, requestId, logger);
|
|
6111
|
+
}
|
|
6014
6112
|
function escapeRegExp(value) {
|
|
6015
6113
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6016
6114
|
}
|
|
@@ -6392,9 +6490,9 @@ class Vm {
|
|
|
6392
6490
|
ref({ vmId }) {
|
|
6393
6491
|
return new Vm({ vmId, freestyle: this._freestyle });
|
|
6394
6492
|
}
|
|
6395
|
-
async delete(
|
|
6493
|
+
async delete() {
|
|
6396
6494
|
return this.apiClient.delete("/v1/vms/{vm_id}", {
|
|
6397
|
-
params: { vm_id: vmId }
|
|
6495
|
+
params: { vm_id: this.vmId }
|
|
6398
6496
|
});
|
|
6399
6497
|
}
|
|
6400
6498
|
}
|
|
@@ -6545,7 +6643,10 @@ class VmSpec {
|
|
|
6545
6643
|
}
|
|
6546
6644
|
ensureSnapshot() {
|
|
6547
6645
|
if (!isVmSpecLike$1(this.raw.snapshot)) {
|
|
6548
|
-
this.raw.snapshot =
|
|
6646
|
+
this.raw.snapshot = new VmSpec({
|
|
6647
|
+
discriminator: this.raw.discriminator,
|
|
6648
|
+
skipCache: this.raw.skipCache
|
|
6649
|
+
});
|
|
6549
6650
|
}
|
|
6550
6651
|
return this.raw.snapshot;
|
|
6551
6652
|
}
|
|
@@ -6574,6 +6675,9 @@ class VmSpec {
|
|
|
6574
6675
|
discriminator(value) {
|
|
6575
6676
|
return this.mergeRaw({ discriminator: value });
|
|
6576
6677
|
}
|
|
6678
|
+
skipCache() {
|
|
6679
|
+
return this.mergeRaw({ skipCache: true });
|
|
6680
|
+
}
|
|
6577
6681
|
workdir(path) {
|
|
6578
6682
|
return this.mergeRaw({ workdir: path });
|
|
6579
6683
|
}
|
|
@@ -6800,7 +6904,10 @@ async function processOuterSpecBuilders(spec) {
|
|
|
6800
6904
|
snapshotSpec = spec.raw.snapshot;
|
|
6801
6905
|
} else {
|
|
6802
6906
|
const inheritedDiscriminator = spec.getBuilderDiscriminator(key) ?? spec.raw.discriminator;
|
|
6803
|
-
snapshotSpec =
|
|
6907
|
+
snapshotSpec = new VmSpec({
|
|
6908
|
+
discriminator: inheritedDiscriminator,
|
|
6909
|
+
skipCache: spec.raw.skipCache
|
|
6910
|
+
});
|
|
6804
6911
|
spec.raw.snapshot = snapshotSpec;
|
|
6805
6912
|
}
|
|
6806
6913
|
spec.raw.snapshot = await builder.configureSnapshotSpec(snapshotSpec);
|
|
@@ -6827,7 +6934,10 @@ async function processSpecTree(spec) {
|
|
|
6827
6934
|
snapshotSpec = spec.raw.snapshot;
|
|
6828
6935
|
} else {
|
|
6829
6936
|
const inheritedDiscriminator = spec.getBuilderDiscriminator(key) ?? spec.raw.discriminator;
|
|
6830
|
-
snapshotSpec =
|
|
6937
|
+
snapshotSpec = new VmSpec({
|
|
6938
|
+
discriminator: inheritedDiscriminator,
|
|
6939
|
+
skipCache: spec.raw.skipCache
|
|
6940
|
+
});
|
|
6831
6941
|
spec.raw.snapshot = snapshotSpec;
|
|
6832
6942
|
}
|
|
6833
6943
|
spec.raw.snapshot = await builder.configureSnapshotSpec(snapshotSpec);
|
|
@@ -6872,9 +6982,15 @@ class VmsNamespace {
|
|
|
6872
6982
|
}
|
|
6873
6983
|
snapshots;
|
|
6874
6984
|
async create(options = {}) {
|
|
6985
|
+
let logger;
|
|
6875
6986
|
if (isVmSpecLike$1(options)) {
|
|
6876
6987
|
options = { spec: cloneVmSpecTree(options) };
|
|
6877
6988
|
} else {
|
|
6989
|
+
logger = options.logger;
|
|
6990
|
+
if ("logger" in options) {
|
|
6991
|
+
const { logger: _logger, ...rest } = options;
|
|
6992
|
+
options = rest;
|
|
6993
|
+
}
|
|
6878
6994
|
if (isVmSpecLike$1(options.spec)) {
|
|
6879
6995
|
options.spec = cloneVmSpecTree(options.spec);
|
|
6880
6996
|
}
|
|
@@ -6954,7 +7070,8 @@ class VmsNamespace {
|
|
|
6954
7070
|
if (isVmTemplateLike$1(config.template)) {
|
|
6955
7071
|
config.template = await ensureNestedTemplates(
|
|
6956
7072
|
config.template,
|
|
6957
|
-
this.snapshots
|
|
7073
|
+
this.snapshots,
|
|
7074
|
+
logger
|
|
6958
7075
|
);
|
|
6959
7076
|
}
|
|
6960
7077
|
const keys = Object.keys(builders);
|
|
@@ -6995,16 +7112,21 @@ class VmsNamespace {
|
|
|
6995
7112
|
template: _template,
|
|
6996
7113
|
...requestConfig
|
|
6997
7114
|
} = config;
|
|
6998
|
-
const response = await
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7115
|
+
const response = await postWithBackgroundLogger(
|
|
7116
|
+
this.freestyle._apiClient,
|
|
7117
|
+
"/v1/vms",
|
|
7118
|
+
{
|
|
7119
|
+
body: {
|
|
7120
|
+
...requestConfig,
|
|
7121
|
+
template: normalizedRequestTemplate,
|
|
7122
|
+
// Cast systemd since we've processed SystemdServiceInput[] to RawSystemdService[]
|
|
7123
|
+
systemd: config.systemd,
|
|
7124
|
+
// Normalize git options - default config to {}
|
|
7125
|
+
git: normalizeGitOptions(config.git)
|
|
7126
|
+
}
|
|
7127
|
+
},
|
|
7128
|
+
logger
|
|
7129
|
+
).catch((e) => {
|
|
7008
7130
|
enhanceError(e);
|
|
7009
7131
|
throw e;
|
|
7010
7132
|
});
|
|
@@ -7160,11 +7282,12 @@ class VmSnapshotsNamespace {
|
|
|
7160
7282
|
this.apiClient = apiClient;
|
|
7161
7283
|
}
|
|
7162
7284
|
async ensure(options) {
|
|
7285
|
+
const { logger, ...restOptions } = options;
|
|
7163
7286
|
let requestOptions = {
|
|
7164
|
-
...
|
|
7165
|
-
spec: isVmSpecLike$1(
|
|
7166
|
-
snapshot: isVmSpecLike$1(
|
|
7167
|
-
template: isVmTemplateLike$1(
|
|
7287
|
+
...restOptions,
|
|
7288
|
+
spec: isVmSpecLike$1(restOptions.spec) ? cloneVmSpecTree(restOptions.spec) : void 0,
|
|
7289
|
+
snapshot: isVmSpecLike$1(restOptions.snapshot) ? cloneVmSpecTree(restOptions.snapshot) : void 0,
|
|
7290
|
+
template: isVmTemplateLike$1(restOptions.template) ? cloneVmTemplateTree(restOptions.template) : restOptions.template
|
|
7168
7291
|
};
|
|
7169
7292
|
if (isVmSpecLike$1(requestOptions.snapshot)) {
|
|
7170
7293
|
if (isVmSpecLike$1(requestOptions.spec)) {
|
|
@@ -7202,7 +7325,8 @@ class VmSnapshotsNamespace {
|
|
|
7202
7325
|
if (isVmTemplateLike$1(processedTemplate.raw.template)) {
|
|
7203
7326
|
requestOptions.template = await ensureNestedTemplates(
|
|
7204
7327
|
processedTemplate,
|
|
7205
|
-
this
|
|
7328
|
+
this,
|
|
7329
|
+
logger
|
|
7206
7330
|
);
|
|
7207
7331
|
}
|
|
7208
7332
|
}
|
|
@@ -7211,18 +7335,43 @@ class VmSnapshotsNamespace {
|
|
|
7211
7335
|
"snapshots.ensure requires a template or spec to build a snapshot"
|
|
7212
7336
|
);
|
|
7213
7337
|
}
|
|
7214
|
-
return
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7338
|
+
return postWithBackgroundLogger(
|
|
7339
|
+
this.apiClient,
|
|
7340
|
+
"/v1/vms/snapshots",
|
|
7341
|
+
{
|
|
7342
|
+
body: {
|
|
7343
|
+
...requestOptions,
|
|
7344
|
+
template: normalizeTemplateForRequest(
|
|
7345
|
+
isVmTemplateLike$1(requestOptions.template) ? requestOptions.template.raw : requestOptions.template
|
|
7346
|
+
)
|
|
7347
|
+
}
|
|
7348
|
+
},
|
|
7349
|
+
logger
|
|
7350
|
+
).catch((e) => {
|
|
7222
7351
|
enhanceError(e);
|
|
7223
7352
|
throw e;
|
|
7224
7353
|
});
|
|
7225
7354
|
}
|
|
7355
|
+
async create(options) {
|
|
7356
|
+
return this.ensure(options);
|
|
7357
|
+
}
|
|
7358
|
+
async delete({ snapshotId }) {
|
|
7359
|
+
const path = "/v1/vms/snapshots/{snapshot_id}";
|
|
7360
|
+
const response = await this.apiClient.fetch(
|
|
7361
|
+
this.apiClient.resolveUrl(path, { snapshot_id: snapshotId }),
|
|
7362
|
+
{ method: "DELETE" }
|
|
7363
|
+
);
|
|
7364
|
+
if (!response.ok) {
|
|
7365
|
+
const errorBody = await response.json().catch(() => null);
|
|
7366
|
+
if (errorBody?.code) {
|
|
7367
|
+
throw errorFromJSON(errorBody);
|
|
7368
|
+
}
|
|
7369
|
+
throw new Error(
|
|
7370
|
+
`Failed to delete snapshot: ${response.status} ${response.statusText}`
|
|
7371
|
+
);
|
|
7372
|
+
}
|
|
7373
|
+
return await response.json();
|
|
7374
|
+
}
|
|
7226
7375
|
}
|
|
7227
7376
|
async function processTemplateTree(template) {
|
|
7228
7377
|
if (template.raw.baseImage) {
|
|
@@ -7294,24 +7443,24 @@ async function processTemplateTree(template) {
|
|
|
7294
7443
|
}
|
|
7295
7444
|
return template;
|
|
7296
7445
|
}
|
|
7297
|
-
async function ensureNestedTemplates(template, snapshots) {
|
|
7446
|
+
async function ensureNestedTemplates(template, snapshots, logger) {
|
|
7298
7447
|
const templates = [template];
|
|
7299
7448
|
while (isVmTemplateLike$1(templates.at(-1)?.raw.template)) {
|
|
7300
7449
|
const innerTemplate = templates.at(-1).raw.template;
|
|
7301
7450
|
templates.at(-1).raw.template = void 0;
|
|
7302
7451
|
templates.push(innerTemplate);
|
|
7303
7452
|
}
|
|
7304
|
-
return await layerTemplates(templates, snapshots);
|
|
7453
|
+
return await layerTemplates(templates, snapshots, logger);
|
|
7305
7454
|
}
|
|
7306
|
-
async function layerTemplates(templates, snapshots) {
|
|
7455
|
+
async function layerTemplates(templates, snapshots, logger) {
|
|
7307
7456
|
if (templates.length === 1) {
|
|
7308
7457
|
return templates[0];
|
|
7309
7458
|
}
|
|
7310
|
-
let lastSnapshotId = (await snapshots.ensure({ template: templates.pop() })).snapshotId;
|
|
7459
|
+
let lastSnapshotId = (await snapshots.ensure({ template: templates.pop(), logger })).snapshotId;
|
|
7311
7460
|
while (templates.length > 1) {
|
|
7312
7461
|
const template = templates.pop();
|
|
7313
7462
|
template.raw.snapshotId = lastSnapshotId;
|
|
7314
|
-
lastSnapshotId = (await snapshots.ensure({ template })).snapshotId;
|
|
7463
|
+
lastSnapshotId = (await snapshots.ensure({ template, logger })).snapshotId;
|
|
7315
7464
|
}
|
|
7316
7465
|
const outermost = templates.pop();
|
|
7317
7466
|
outermost.raw.snapshotId = lastSnapshotId;
|
package/index.d.cts
CHANGED
|
@@ -4467,6 +4467,12 @@ interface PostV1VmsRequestBody {
|
|
|
4467
4467
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
4468
4468
|
*/
|
|
4469
4469
|
aptDeps?: string[] | null;
|
|
4470
|
+
/**
|
|
4471
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
4472
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
4473
|
+
* cache entry for future requests that do not set skipCache.
|
|
4474
|
+
*/
|
|
4475
|
+
skipCache?: boolean | null;
|
|
4470
4476
|
};
|
|
4471
4477
|
/**
|
|
4472
4478
|
* @deprecated
|
|
@@ -4883,6 +4889,12 @@ interface PostV1VmsSnapshotsRequestBody {
|
|
|
4883
4889
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
4884
4890
|
*/
|
|
4885
4891
|
aptDeps?: string[] | null;
|
|
4892
|
+
/**
|
|
4893
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
4894
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
4895
|
+
* cache entry for future requests that do not set skipCache.
|
|
4896
|
+
*/
|
|
4897
|
+
skipCache?: boolean | null;
|
|
4886
4898
|
};
|
|
4887
4899
|
persistence?: null | ({
|
|
4888
4900
|
priority?: number | null;
|
|
@@ -6695,9 +6707,11 @@ declare class ApiClient {
|
|
|
6695
6707
|
private requestRaw;
|
|
6696
6708
|
private request;
|
|
6697
6709
|
fetch(url: string, options?: RequestInit): Promise<Response>;
|
|
6710
|
+
resolveUrl(path: string, params?: Record<string, string>, query?: Record<string, any>): string;
|
|
6698
6711
|
getRaw<P extends keyof GetPathMap>(path: P, options?: GetPathMap[P]["options"]): Promise<Response>;
|
|
6699
6712
|
get<P extends keyof GetPathMap>(path: P, ...args: GetPathMap[P]["options"] extends undefined ? [options?: GetPathMap[P]["options"]] : [options: GetPathMap[P]["options"]]): Promise<GetPathMap[P]["response"]>;
|
|
6700
6713
|
post<P extends keyof PostPathMap>(path: P, ...args: PostPathMap[P]["options"] extends undefined ? [options?: PostPathMap[P]["options"]] : [options: PostPathMap[P]["options"]]): Promise<PostPathMap[P]["response"]>;
|
|
6714
|
+
postRaw<P extends keyof PostPathMap>(path: P, ...args: PostPathMap[P]["options"] extends undefined ? [options?: PostPathMap[P]["options"]] : [options: PostPathMap[P]["options"]]): Promise<Response>;
|
|
6701
6715
|
put<P extends keyof PutPathMap>(path: P, ...args: PutPathMap[P]["options"] extends undefined ? [options?: PutPathMap[P]["options"]] : [options: PutPathMap[P]["options"]]): Promise<PutPathMap[P]["response"]>;
|
|
6702
6716
|
delete<P extends keyof DeletePathMap>(path: P, ...args: DeletePathMap[P]["options"] extends undefined ? [options?: DeletePathMap[P]["options"]] : [options: DeletePathMap[P]["options"]]): Promise<DeletePathMap[P]["response"]>;
|
|
6703
6717
|
patch<P extends keyof PatchPathMap>(path: P, ...args: PatchPathMap[P]["options"] extends undefined ? [options?: PatchPathMap[P]["options"]] : [options: PatchPathMap[P]["options"]]): Promise<PatchPathMap[P]["response"]>;
|
|
@@ -11909,6 +11923,12 @@ interface CreateSnapshotRequest {
|
|
|
11909
11923
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
11910
11924
|
*/
|
|
11911
11925
|
aptDeps?: string[] | null;
|
|
11926
|
+
/**
|
|
11927
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
11928
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
11929
|
+
* cache entry for future requests that do not set skipCache.
|
|
11930
|
+
*/
|
|
11931
|
+
skipCache?: boolean | null;
|
|
11912
11932
|
};
|
|
11913
11933
|
persistence?: null | ({
|
|
11914
11934
|
priority?: number | null;
|
|
@@ -12295,6 +12315,16 @@ type SystemdServiceInput = Omit<RawSystemdService, "mode" | "exec"> & {
|
|
|
12295
12315
|
type VmWaitForConfig = Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
12296
12316
|
intervalSeconds?: number;
|
|
12297
12317
|
};
|
|
12318
|
+
type BackgroundRequestLogger = (message: string) => void;
|
|
12319
|
+
type SnapshotCreateOptions<T extends Record<string, VmWithLike> = {}> = Omit<PostV1VmsSnapshotsRequestBody, "template"> & {
|
|
12320
|
+
template?: VmTemplate<T> | PostV1VmsSnapshotsRequestBody["template"];
|
|
12321
|
+
spec?: VmSpec<T>;
|
|
12322
|
+
snapshot?: VmSpec<T>;
|
|
12323
|
+
logger?: BackgroundRequestLogger;
|
|
12324
|
+
};
|
|
12325
|
+
type SnapshotDeleteResponse = {
|
|
12326
|
+
snapshotId: string;
|
|
12327
|
+
};
|
|
12298
12328
|
/**
|
|
12299
12329
|
* Terminal management operations for a VM.
|
|
12300
12330
|
*/
|
|
@@ -12428,9 +12458,7 @@ declare class Vm {
|
|
|
12428
12458
|
ref({ vmId }: {
|
|
12429
12459
|
vmId: string;
|
|
12430
12460
|
}): Vm;
|
|
12431
|
-
delete(
|
|
12432
|
-
vmId: string;
|
|
12433
|
-
}): Promise<ResponseDeleteV1VmsVmId200>;
|
|
12461
|
+
delete(): Promise<ResponseDeleteV1VmsVmId200>;
|
|
12434
12462
|
}
|
|
12435
12463
|
/**
|
|
12436
12464
|
* Git configuration with optional config (defaults to {})
|
|
@@ -12496,6 +12524,7 @@ declare class VmSpec<T extends Record<string, VmWithLike> = {}> {
|
|
|
12496
12524
|
readySignalTimeoutSeconds(value: number): this;
|
|
12497
12525
|
waitForReadySignal(value: boolean): this;
|
|
12498
12526
|
discriminator(value: string): this;
|
|
12527
|
+
skipCache(): this;
|
|
12499
12528
|
workdir(path: string): this;
|
|
12500
12529
|
aptDeps(...deps: string[]): this;
|
|
12501
12530
|
users(users: NonNullable<CreateVmOptions["users"]>): this;
|
|
@@ -12532,6 +12561,7 @@ declare class VmsNamespace {
|
|
|
12532
12561
|
template?: VmTemplate<T>;
|
|
12533
12562
|
spec?: VmSpec<T>;
|
|
12534
12563
|
snapshot?: VmSpec<T>;
|
|
12564
|
+
logger?: BackgroundRequestLogger;
|
|
12535
12565
|
}): Promise<Omit<ResponsePostV1Vms200, "consoleUrl"> & {
|
|
12536
12566
|
vmId: string;
|
|
12537
12567
|
vm: Vm & {
|
|
@@ -12575,11 +12605,11 @@ declare class VmsNamespace {
|
|
|
12575
12605
|
declare class VmSnapshotsNamespace {
|
|
12576
12606
|
private apiClient;
|
|
12577
12607
|
constructor(apiClient: ApiClient);
|
|
12578
|
-
ensure<T extends Record<string, VmWithLike>>(options:
|
|
12579
|
-
|
|
12580
|
-
|
|
12581
|
-
|
|
12582
|
-
}): Promise<
|
|
12608
|
+
ensure<T extends Record<string, VmWithLike>>(options: SnapshotCreateOptions<T>): Promise<ResponsePostV1VmsSnapshots200>;
|
|
12609
|
+
create<T extends Record<string, VmWithLike>>(options: SnapshotCreateOptions<T>): Promise<ResponsePostV1VmsSnapshots200>;
|
|
12610
|
+
delete({ snapshotId }: {
|
|
12611
|
+
snapshotId: string;
|
|
12612
|
+
}): Promise<SnapshotDeleteResponse>;
|
|
12583
12613
|
}
|
|
12584
12614
|
type CreateVmOptions = Omit<PostV1VmsRequestBody, "template" | "systemd" | "git"> & {
|
|
12585
12615
|
rootfsSizeGb?: number | null;
|
|
@@ -12595,6 +12625,8 @@ type CreateVmOptions = Omit<PostV1VmsRequestBody, "template" | "systemd" | "git"
|
|
|
12595
12625
|
};
|
|
12596
12626
|
git?: null | GitOptions;
|
|
12597
12627
|
discriminator?: CreateSnapshotRequest["template"]["discriminator"];
|
|
12628
|
+
skipCache?: CreateSnapshotRequest["template"]["skipCache"];
|
|
12629
|
+
logger?: BackgroundRequestLogger;
|
|
12598
12630
|
};
|
|
12599
12631
|
|
|
12600
12632
|
type CronSchedule = {
|
|
@@ -12743,4 +12775,4 @@ declare class Freestyle {
|
|
|
12743
12775
|
declare const freestyle: Freestyle;
|
|
12744
12776
|
|
|
12745
12777
|
export { CronNamespace, Deployment, errors as Errors, FileSystem, Freestyle, GitRepo, Identity, requests as Requests, responses as Responses, Systemd, SystemdService, Vm, VmBaseImage, VmBuilder, VmService, VmSpec, VmTemplate, VmWith, VmWithInstance, debugCreateRequests, freestyle, readFiles };
|
|
12746
|
-
export type { CreateVmOptions, CronSchedule, FreestyleOptions, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
|
12778
|
+
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, FreestyleOptions, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
package/index.d.mts
CHANGED
|
@@ -4467,6 +4467,12 @@ interface PostV1VmsRequestBody {
|
|
|
4467
4467
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
4468
4468
|
*/
|
|
4469
4469
|
aptDeps?: string[] | null;
|
|
4470
|
+
/**
|
|
4471
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
4472
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
4473
|
+
* cache entry for future requests that do not set skipCache.
|
|
4474
|
+
*/
|
|
4475
|
+
skipCache?: boolean | null;
|
|
4470
4476
|
};
|
|
4471
4477
|
/**
|
|
4472
4478
|
* @deprecated
|
|
@@ -4883,6 +4889,12 @@ interface PostV1VmsSnapshotsRequestBody {
|
|
|
4883
4889
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
4884
4890
|
*/
|
|
4885
4891
|
aptDeps?: string[] | null;
|
|
4892
|
+
/**
|
|
4893
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
4894
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
4895
|
+
* cache entry for future requests that do not set skipCache.
|
|
4896
|
+
*/
|
|
4897
|
+
skipCache?: boolean | null;
|
|
4886
4898
|
};
|
|
4887
4899
|
persistence?: null | ({
|
|
4888
4900
|
priority?: number | null;
|
|
@@ -6695,9 +6707,11 @@ declare class ApiClient {
|
|
|
6695
6707
|
private requestRaw;
|
|
6696
6708
|
private request;
|
|
6697
6709
|
fetch(url: string, options?: RequestInit): Promise<Response>;
|
|
6710
|
+
resolveUrl(path: string, params?: Record<string, string>, query?: Record<string, any>): string;
|
|
6698
6711
|
getRaw<P extends keyof GetPathMap>(path: P, options?: GetPathMap[P]["options"]): Promise<Response>;
|
|
6699
6712
|
get<P extends keyof GetPathMap>(path: P, ...args: GetPathMap[P]["options"] extends undefined ? [options?: GetPathMap[P]["options"]] : [options: GetPathMap[P]["options"]]): Promise<GetPathMap[P]["response"]>;
|
|
6700
6713
|
post<P extends keyof PostPathMap>(path: P, ...args: PostPathMap[P]["options"] extends undefined ? [options?: PostPathMap[P]["options"]] : [options: PostPathMap[P]["options"]]): Promise<PostPathMap[P]["response"]>;
|
|
6714
|
+
postRaw<P extends keyof PostPathMap>(path: P, ...args: PostPathMap[P]["options"] extends undefined ? [options?: PostPathMap[P]["options"]] : [options: PostPathMap[P]["options"]]): Promise<Response>;
|
|
6701
6715
|
put<P extends keyof PutPathMap>(path: P, ...args: PutPathMap[P]["options"] extends undefined ? [options?: PutPathMap[P]["options"]] : [options: PutPathMap[P]["options"]]): Promise<PutPathMap[P]["response"]>;
|
|
6702
6716
|
delete<P extends keyof DeletePathMap>(path: P, ...args: DeletePathMap[P]["options"] extends undefined ? [options?: DeletePathMap[P]["options"]] : [options: DeletePathMap[P]["options"]]): Promise<DeletePathMap[P]["response"]>;
|
|
6703
6717
|
patch<P extends keyof PatchPathMap>(path: P, ...args: PatchPathMap[P]["options"] extends undefined ? [options?: PatchPathMap[P]["options"]] : [options: PatchPathMap[P]["options"]]): Promise<PatchPathMap[P]["response"]>;
|
|
@@ -11909,6 +11923,12 @@ interface CreateSnapshotRequest {
|
|
|
11909
11923
|
* These packages will be installed using `apt-get install` on VM startup.
|
|
11910
11924
|
*/
|
|
11911
11925
|
aptDeps?: string[] | null;
|
|
11926
|
+
/**
|
|
11927
|
+
* When true, bypasses the snapshot cache and always creates a new snapshot.
|
|
11928
|
+
* The new snapshot still stores the template hash, so it becomes the updated
|
|
11929
|
+
* cache entry for future requests that do not set skipCache.
|
|
11930
|
+
*/
|
|
11931
|
+
skipCache?: boolean | null;
|
|
11912
11932
|
};
|
|
11913
11933
|
persistence?: null | ({
|
|
11914
11934
|
priority?: number | null;
|
|
@@ -12295,6 +12315,16 @@ type SystemdServiceInput = Omit<RawSystemdService, "mode" | "exec"> & {
|
|
|
12295
12315
|
type VmWaitForConfig = Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
12296
12316
|
intervalSeconds?: number;
|
|
12297
12317
|
};
|
|
12318
|
+
type BackgroundRequestLogger = (message: string) => void;
|
|
12319
|
+
type SnapshotCreateOptions<T extends Record<string, VmWithLike> = {}> = Omit<PostV1VmsSnapshotsRequestBody, "template"> & {
|
|
12320
|
+
template?: VmTemplate<T> | PostV1VmsSnapshotsRequestBody["template"];
|
|
12321
|
+
spec?: VmSpec<T>;
|
|
12322
|
+
snapshot?: VmSpec<T>;
|
|
12323
|
+
logger?: BackgroundRequestLogger;
|
|
12324
|
+
};
|
|
12325
|
+
type SnapshotDeleteResponse = {
|
|
12326
|
+
snapshotId: string;
|
|
12327
|
+
};
|
|
12298
12328
|
/**
|
|
12299
12329
|
* Terminal management operations for a VM.
|
|
12300
12330
|
*/
|
|
@@ -12428,9 +12458,7 @@ declare class Vm {
|
|
|
12428
12458
|
ref({ vmId }: {
|
|
12429
12459
|
vmId: string;
|
|
12430
12460
|
}): Vm;
|
|
12431
|
-
delete(
|
|
12432
|
-
vmId: string;
|
|
12433
|
-
}): Promise<ResponseDeleteV1VmsVmId200>;
|
|
12461
|
+
delete(): Promise<ResponseDeleteV1VmsVmId200>;
|
|
12434
12462
|
}
|
|
12435
12463
|
/**
|
|
12436
12464
|
* Git configuration with optional config (defaults to {})
|
|
@@ -12496,6 +12524,7 @@ declare class VmSpec<T extends Record<string, VmWithLike> = {}> {
|
|
|
12496
12524
|
readySignalTimeoutSeconds(value: number): this;
|
|
12497
12525
|
waitForReadySignal(value: boolean): this;
|
|
12498
12526
|
discriminator(value: string): this;
|
|
12527
|
+
skipCache(): this;
|
|
12499
12528
|
workdir(path: string): this;
|
|
12500
12529
|
aptDeps(...deps: string[]): this;
|
|
12501
12530
|
users(users: NonNullable<CreateVmOptions["users"]>): this;
|
|
@@ -12532,6 +12561,7 @@ declare class VmsNamespace {
|
|
|
12532
12561
|
template?: VmTemplate<T>;
|
|
12533
12562
|
spec?: VmSpec<T>;
|
|
12534
12563
|
snapshot?: VmSpec<T>;
|
|
12564
|
+
logger?: BackgroundRequestLogger;
|
|
12535
12565
|
}): Promise<Omit<ResponsePostV1Vms200, "consoleUrl"> & {
|
|
12536
12566
|
vmId: string;
|
|
12537
12567
|
vm: Vm & {
|
|
@@ -12575,11 +12605,11 @@ declare class VmsNamespace {
|
|
|
12575
12605
|
declare class VmSnapshotsNamespace {
|
|
12576
12606
|
private apiClient;
|
|
12577
12607
|
constructor(apiClient: ApiClient);
|
|
12578
|
-
ensure<T extends Record<string, VmWithLike>>(options:
|
|
12579
|
-
|
|
12580
|
-
|
|
12581
|
-
|
|
12582
|
-
}): Promise<
|
|
12608
|
+
ensure<T extends Record<string, VmWithLike>>(options: SnapshotCreateOptions<T>): Promise<ResponsePostV1VmsSnapshots200>;
|
|
12609
|
+
create<T extends Record<string, VmWithLike>>(options: SnapshotCreateOptions<T>): Promise<ResponsePostV1VmsSnapshots200>;
|
|
12610
|
+
delete({ snapshotId }: {
|
|
12611
|
+
snapshotId: string;
|
|
12612
|
+
}): Promise<SnapshotDeleteResponse>;
|
|
12583
12613
|
}
|
|
12584
12614
|
type CreateVmOptions = Omit<PostV1VmsRequestBody, "template" | "systemd" | "git"> & {
|
|
12585
12615
|
rootfsSizeGb?: number | null;
|
|
@@ -12595,6 +12625,8 @@ type CreateVmOptions = Omit<PostV1VmsRequestBody, "template" | "systemd" | "git"
|
|
|
12595
12625
|
};
|
|
12596
12626
|
git?: null | GitOptions;
|
|
12597
12627
|
discriminator?: CreateSnapshotRequest["template"]["discriminator"];
|
|
12628
|
+
skipCache?: CreateSnapshotRequest["template"]["skipCache"];
|
|
12629
|
+
logger?: BackgroundRequestLogger;
|
|
12598
12630
|
};
|
|
12599
12631
|
|
|
12600
12632
|
type CronSchedule = {
|
|
@@ -12743,4 +12775,4 @@ declare class Freestyle {
|
|
|
12743
12775
|
declare const freestyle: Freestyle;
|
|
12744
12776
|
|
|
12745
12777
|
export { CronNamespace, Deployment, errors as Errors, FileSystem, Freestyle, GitRepo, Identity, requests as Requests, responses as Responses, Systemd, SystemdService, Vm, VmBaseImage, VmBuilder, VmService, VmSpec, VmTemplate, VmWith, VmWithInstance, debugCreateRequests, freestyle, readFiles };
|
|
12746
|
-
export type { CreateVmOptions, CronSchedule, FreestyleOptions, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
|
12778
|
+
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, FreestyleOptions, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
package/index.mjs
CHANGED
|
@@ -3761,6 +3761,9 @@ class ApiClient {
|
|
|
3761
3761
|
};
|
|
3762
3762
|
return this.fetchFn(url, finalOptions);
|
|
3763
3763
|
}
|
|
3764
|
+
resolveUrl(path, params, query) {
|
|
3765
|
+
return this.buildUrl(path, params, query);
|
|
3766
|
+
}
|
|
3764
3767
|
getRaw(path, options) {
|
|
3765
3768
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3766
3769
|
return this.requestRaw("GET", url, void 0, options?.headers);
|
|
@@ -3775,6 +3778,11 @@ class ApiClient {
|
|
|
3775
3778
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3776
3779
|
return this.request("POST", url, options?.body, options?.headers);
|
|
3777
3780
|
}
|
|
3781
|
+
postRaw(path, ...args) {
|
|
3782
|
+
const options = args[0];
|
|
3783
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
3784
|
+
return this.requestRaw("POST", url, options?.body, options?.headers);
|
|
3785
|
+
}
|
|
3778
3786
|
put(path, ...args) {
|
|
3779
3787
|
const options = args[0];
|
|
3780
3788
|
const url = this.buildUrl(path, options?.params, options?.query);
|
|
@@ -5646,6 +5654,7 @@ function composeCreateVmOptions(arr) {
|
|
|
5646
5654
|
result.activityThresholdBytes = options.activityThresholdBytes;
|
|
5647
5655
|
if (options.discriminator !== void 0)
|
|
5648
5656
|
result.discriminator = options.discriminator;
|
|
5657
|
+
if (options.skipCache !== void 0) result.skipCache = options.skipCache;
|
|
5649
5658
|
if (options.persistence !== void 0)
|
|
5650
5659
|
result.persistence = options.persistence;
|
|
5651
5660
|
if (options.ports !== void 0) {
|
|
@@ -5793,6 +5802,7 @@ function composeCreateVmOptions(arr) {
|
|
|
5793
5802
|
aptDeps: newTemplate.aptDeps ?? baseTemplate.aptDeps,
|
|
5794
5803
|
vcpuCount: newTemplate.vcpuCount !== void 0 ? newTemplate.vcpuCount : baseTemplate.vcpuCount,
|
|
5795
5804
|
discriminator: newTemplate.discriminator ?? baseTemplate.discriminator,
|
|
5805
|
+
skipCache: newTemplate.skipCache ?? baseTemplate.skipCache,
|
|
5796
5806
|
workdir: newTemplate.workdir !== void 0 ? newTemplate.workdir : baseTemplate.workdir,
|
|
5797
5807
|
idleTimeoutSeconds: newTemplate.idleTimeoutSeconds !== void 0 ? newTemplate.idleTimeoutSeconds : baseTemplate.idleTimeoutSeconds,
|
|
5798
5808
|
waitForReadySignal: newTemplate.waitForReadySignal !== void 0 ? newTemplate.waitForReadySignal : baseTemplate.waitForReadySignal,
|
|
@@ -6009,6 +6019,94 @@ function composeVmSpecs(specs) {
|
|
|
6009
6019
|
const DEFAULT_CONFIGURE_BASE_IMAGE = "FROM debian:trixie-slim";
|
|
6010
6020
|
const RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX = "freestyle-run-command";
|
|
6011
6021
|
const WAIT_FOR_SYSTEMD_SERVICE_PREFIX = "freestyle-wait-for";
|
|
6022
|
+
const BACKGROUND_AFTER_SECS_HEADER = "x-freestyle-background-after-secs";
|
|
6023
|
+
const BACKGROUND_REQUEST_ID_HEADER = "x-freestyle-background-request-id";
|
|
6024
|
+
const DEFAULT_BACKGROUND_AFTER_SECS = 5;
|
|
6025
|
+
const DEFAULT_BACKGROUND_POLL_INTERVAL_MS = 2e3;
|
|
6026
|
+
function delay(ms) {
|
|
6027
|
+
const timerApi = globalThis;
|
|
6028
|
+
return new Promise((resolve) => timerApi.setTimeout(resolve, ms));
|
|
6029
|
+
}
|
|
6030
|
+
function extractBackgroundRequestId(response, body) {
|
|
6031
|
+
return response.headers.get(BACKGROUND_REQUEST_ID_HEADER) ?? body?.requestId ?? body?.request_id;
|
|
6032
|
+
}
|
|
6033
|
+
async function parseJsonResponse(response) {
|
|
6034
|
+
return await response.json();
|
|
6035
|
+
}
|
|
6036
|
+
async function readResponseError(response, fallbackMessage) {
|
|
6037
|
+
const responseText = await response.text();
|
|
6038
|
+
if (!responseText) {
|
|
6039
|
+
return fallbackMessage;
|
|
6040
|
+
}
|
|
6041
|
+
try {
|
|
6042
|
+
const errorBody = JSON.parse(responseText);
|
|
6043
|
+
return errorBody.message ?? errorBody.error ?? responseText;
|
|
6044
|
+
} catch {
|
|
6045
|
+
return responseText;
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
async function emitBackgroundLogs(apiClient, requestId, logger, seenLogs) {
|
|
6049
|
+
const response = await apiClient.fetch(
|
|
6050
|
+
apiClient.resolveUrl("/observability/v1/logs", void 0, { requestId }),
|
|
6051
|
+
{ method: "GET" }
|
|
6052
|
+
);
|
|
6053
|
+
if (!response.ok) {
|
|
6054
|
+
return;
|
|
6055
|
+
}
|
|
6056
|
+
const payload = await response.json();
|
|
6057
|
+
for (const entry of payload.logs ?? []) {
|
|
6058
|
+
const key = `${entry.timestamp} ${entry.message}`;
|
|
6059
|
+
if (seenLogs.has(key)) {
|
|
6060
|
+
continue;
|
|
6061
|
+
}
|
|
6062
|
+
seenLogs.add(key);
|
|
6063
|
+
logger(`[${entry.timestamp}] ${entry.message}`);
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
async function waitForBackgroundRequest(apiClient, requestId, logger) {
|
|
6067
|
+
const seenLogs = /* @__PURE__ */ new Set();
|
|
6068
|
+
const resultUrl = apiClient.resolveUrl(
|
|
6069
|
+
`/auth/v1/background-requests/${encodeURIComponent(requestId)}`
|
|
6070
|
+
);
|
|
6071
|
+
while (true) {
|
|
6072
|
+
await emitBackgroundLogs(apiClient, requestId, logger, seenLogs);
|
|
6073
|
+
const response = await apiClient.fetch(resultUrl, { method: "GET" });
|
|
6074
|
+
if (response.status === 202) {
|
|
6075
|
+
await delay(DEFAULT_BACKGROUND_POLL_INTERVAL_MS);
|
|
6076
|
+
continue;
|
|
6077
|
+
}
|
|
6078
|
+
if (!response.ok) {
|
|
6079
|
+
const message = await readResponseError(
|
|
6080
|
+
response,
|
|
6081
|
+
`Background request ${requestId} failed`
|
|
6082
|
+
);
|
|
6083
|
+
throw new Error(message);
|
|
6084
|
+
}
|
|
6085
|
+
return parseJsonResponse(response);
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
async function postWithBackgroundLogger(apiClient, path, options, logger) {
|
|
6089
|
+
const response = await apiClient.postRaw(path, {
|
|
6090
|
+
...options,
|
|
6091
|
+
headers: logger ? {
|
|
6092
|
+
...options.headers ?? {},
|
|
6093
|
+
[BACKGROUND_AFTER_SECS_HEADER]: String(DEFAULT_BACKGROUND_AFTER_SECS)
|
|
6094
|
+
} : options.headers
|
|
6095
|
+
});
|
|
6096
|
+
if (response.status !== 202 || !logger) {
|
|
6097
|
+
return parseJsonResponse(response);
|
|
6098
|
+
}
|
|
6099
|
+
const accepted = await parseJsonResponse(
|
|
6100
|
+
response
|
|
6101
|
+
);
|
|
6102
|
+
const requestId = extractBackgroundRequestId(response, accepted);
|
|
6103
|
+
if (!requestId) {
|
|
6104
|
+
throw new Error(
|
|
6105
|
+
`Background request response for ${path} did not include a request ID`
|
|
6106
|
+
);
|
|
6107
|
+
}
|
|
6108
|
+
return waitForBackgroundRequest(apiClient, requestId, logger);
|
|
6109
|
+
}
|
|
6012
6110
|
function escapeRegExp(value) {
|
|
6013
6111
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6014
6112
|
}
|
|
@@ -6390,9 +6488,9 @@ class Vm {
|
|
|
6390
6488
|
ref({ vmId }) {
|
|
6391
6489
|
return new Vm({ vmId, freestyle: this._freestyle });
|
|
6392
6490
|
}
|
|
6393
|
-
async delete(
|
|
6491
|
+
async delete() {
|
|
6394
6492
|
return this.apiClient.delete("/v1/vms/{vm_id}", {
|
|
6395
|
-
params: { vm_id: vmId }
|
|
6493
|
+
params: { vm_id: this.vmId }
|
|
6396
6494
|
});
|
|
6397
6495
|
}
|
|
6398
6496
|
}
|
|
@@ -6543,7 +6641,10 @@ class VmSpec {
|
|
|
6543
6641
|
}
|
|
6544
6642
|
ensureSnapshot() {
|
|
6545
6643
|
if (!isVmSpecLike$1(this.raw.snapshot)) {
|
|
6546
|
-
this.raw.snapshot =
|
|
6644
|
+
this.raw.snapshot = new VmSpec({
|
|
6645
|
+
discriminator: this.raw.discriminator,
|
|
6646
|
+
skipCache: this.raw.skipCache
|
|
6647
|
+
});
|
|
6547
6648
|
}
|
|
6548
6649
|
return this.raw.snapshot;
|
|
6549
6650
|
}
|
|
@@ -6572,6 +6673,9 @@ class VmSpec {
|
|
|
6572
6673
|
discriminator(value) {
|
|
6573
6674
|
return this.mergeRaw({ discriminator: value });
|
|
6574
6675
|
}
|
|
6676
|
+
skipCache() {
|
|
6677
|
+
return this.mergeRaw({ skipCache: true });
|
|
6678
|
+
}
|
|
6575
6679
|
workdir(path) {
|
|
6576
6680
|
return this.mergeRaw({ workdir: path });
|
|
6577
6681
|
}
|
|
@@ -6798,7 +6902,10 @@ async function processOuterSpecBuilders(spec) {
|
|
|
6798
6902
|
snapshotSpec = spec.raw.snapshot;
|
|
6799
6903
|
} else {
|
|
6800
6904
|
const inheritedDiscriminator = spec.getBuilderDiscriminator(key) ?? spec.raw.discriminator;
|
|
6801
|
-
snapshotSpec =
|
|
6905
|
+
snapshotSpec = new VmSpec({
|
|
6906
|
+
discriminator: inheritedDiscriminator,
|
|
6907
|
+
skipCache: spec.raw.skipCache
|
|
6908
|
+
});
|
|
6802
6909
|
spec.raw.snapshot = snapshotSpec;
|
|
6803
6910
|
}
|
|
6804
6911
|
spec.raw.snapshot = await builder.configureSnapshotSpec(snapshotSpec);
|
|
@@ -6825,7 +6932,10 @@ async function processSpecTree(spec) {
|
|
|
6825
6932
|
snapshotSpec = spec.raw.snapshot;
|
|
6826
6933
|
} else {
|
|
6827
6934
|
const inheritedDiscriminator = spec.getBuilderDiscriminator(key) ?? spec.raw.discriminator;
|
|
6828
|
-
snapshotSpec =
|
|
6935
|
+
snapshotSpec = new VmSpec({
|
|
6936
|
+
discriminator: inheritedDiscriminator,
|
|
6937
|
+
skipCache: spec.raw.skipCache
|
|
6938
|
+
});
|
|
6829
6939
|
spec.raw.snapshot = snapshotSpec;
|
|
6830
6940
|
}
|
|
6831
6941
|
spec.raw.snapshot = await builder.configureSnapshotSpec(snapshotSpec);
|
|
@@ -6870,9 +6980,15 @@ class VmsNamespace {
|
|
|
6870
6980
|
}
|
|
6871
6981
|
snapshots;
|
|
6872
6982
|
async create(options = {}) {
|
|
6983
|
+
let logger;
|
|
6873
6984
|
if (isVmSpecLike$1(options)) {
|
|
6874
6985
|
options = { spec: cloneVmSpecTree(options) };
|
|
6875
6986
|
} else {
|
|
6987
|
+
logger = options.logger;
|
|
6988
|
+
if ("logger" in options) {
|
|
6989
|
+
const { logger: _logger, ...rest } = options;
|
|
6990
|
+
options = rest;
|
|
6991
|
+
}
|
|
6876
6992
|
if (isVmSpecLike$1(options.spec)) {
|
|
6877
6993
|
options.spec = cloneVmSpecTree(options.spec);
|
|
6878
6994
|
}
|
|
@@ -6952,7 +7068,8 @@ class VmsNamespace {
|
|
|
6952
7068
|
if (isVmTemplateLike$1(config.template)) {
|
|
6953
7069
|
config.template = await ensureNestedTemplates(
|
|
6954
7070
|
config.template,
|
|
6955
|
-
this.snapshots
|
|
7071
|
+
this.snapshots,
|
|
7072
|
+
logger
|
|
6956
7073
|
);
|
|
6957
7074
|
}
|
|
6958
7075
|
const keys = Object.keys(builders);
|
|
@@ -6993,16 +7110,21 @@ class VmsNamespace {
|
|
|
6993
7110
|
template: _template,
|
|
6994
7111
|
...requestConfig
|
|
6995
7112
|
} = config;
|
|
6996
|
-
const response = await
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7113
|
+
const response = await postWithBackgroundLogger(
|
|
7114
|
+
this.freestyle._apiClient,
|
|
7115
|
+
"/v1/vms",
|
|
7116
|
+
{
|
|
7117
|
+
body: {
|
|
7118
|
+
...requestConfig,
|
|
7119
|
+
template: normalizedRequestTemplate,
|
|
7120
|
+
// Cast systemd since we've processed SystemdServiceInput[] to RawSystemdService[]
|
|
7121
|
+
systemd: config.systemd,
|
|
7122
|
+
// Normalize git options - default config to {}
|
|
7123
|
+
git: normalizeGitOptions(config.git)
|
|
7124
|
+
}
|
|
7125
|
+
},
|
|
7126
|
+
logger
|
|
7127
|
+
).catch((e) => {
|
|
7006
7128
|
enhanceError(e);
|
|
7007
7129
|
throw e;
|
|
7008
7130
|
});
|
|
@@ -7158,11 +7280,12 @@ class VmSnapshotsNamespace {
|
|
|
7158
7280
|
this.apiClient = apiClient;
|
|
7159
7281
|
}
|
|
7160
7282
|
async ensure(options) {
|
|
7283
|
+
const { logger, ...restOptions } = options;
|
|
7161
7284
|
let requestOptions = {
|
|
7162
|
-
...
|
|
7163
|
-
spec: isVmSpecLike$1(
|
|
7164
|
-
snapshot: isVmSpecLike$1(
|
|
7165
|
-
template: isVmTemplateLike$1(
|
|
7285
|
+
...restOptions,
|
|
7286
|
+
spec: isVmSpecLike$1(restOptions.spec) ? cloneVmSpecTree(restOptions.spec) : void 0,
|
|
7287
|
+
snapshot: isVmSpecLike$1(restOptions.snapshot) ? cloneVmSpecTree(restOptions.snapshot) : void 0,
|
|
7288
|
+
template: isVmTemplateLike$1(restOptions.template) ? cloneVmTemplateTree(restOptions.template) : restOptions.template
|
|
7166
7289
|
};
|
|
7167
7290
|
if (isVmSpecLike$1(requestOptions.snapshot)) {
|
|
7168
7291
|
if (isVmSpecLike$1(requestOptions.spec)) {
|
|
@@ -7200,7 +7323,8 @@ class VmSnapshotsNamespace {
|
|
|
7200
7323
|
if (isVmTemplateLike$1(processedTemplate.raw.template)) {
|
|
7201
7324
|
requestOptions.template = await ensureNestedTemplates(
|
|
7202
7325
|
processedTemplate,
|
|
7203
|
-
this
|
|
7326
|
+
this,
|
|
7327
|
+
logger
|
|
7204
7328
|
);
|
|
7205
7329
|
}
|
|
7206
7330
|
}
|
|
@@ -7209,18 +7333,43 @@ class VmSnapshotsNamespace {
|
|
|
7209
7333
|
"snapshots.ensure requires a template or spec to build a snapshot"
|
|
7210
7334
|
);
|
|
7211
7335
|
}
|
|
7212
|
-
return
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7336
|
+
return postWithBackgroundLogger(
|
|
7337
|
+
this.apiClient,
|
|
7338
|
+
"/v1/vms/snapshots",
|
|
7339
|
+
{
|
|
7340
|
+
body: {
|
|
7341
|
+
...requestOptions,
|
|
7342
|
+
template: normalizeTemplateForRequest(
|
|
7343
|
+
isVmTemplateLike$1(requestOptions.template) ? requestOptions.template.raw : requestOptions.template
|
|
7344
|
+
)
|
|
7345
|
+
}
|
|
7346
|
+
},
|
|
7347
|
+
logger
|
|
7348
|
+
).catch((e) => {
|
|
7220
7349
|
enhanceError(e);
|
|
7221
7350
|
throw e;
|
|
7222
7351
|
});
|
|
7223
7352
|
}
|
|
7353
|
+
async create(options) {
|
|
7354
|
+
return this.ensure(options);
|
|
7355
|
+
}
|
|
7356
|
+
async delete({ snapshotId }) {
|
|
7357
|
+
const path = "/v1/vms/snapshots/{snapshot_id}";
|
|
7358
|
+
const response = await this.apiClient.fetch(
|
|
7359
|
+
this.apiClient.resolveUrl(path, { snapshot_id: snapshotId }),
|
|
7360
|
+
{ method: "DELETE" }
|
|
7361
|
+
);
|
|
7362
|
+
if (!response.ok) {
|
|
7363
|
+
const errorBody = await response.json().catch(() => null);
|
|
7364
|
+
if (errorBody?.code) {
|
|
7365
|
+
throw errorFromJSON(errorBody);
|
|
7366
|
+
}
|
|
7367
|
+
throw new Error(
|
|
7368
|
+
`Failed to delete snapshot: ${response.status} ${response.statusText}`
|
|
7369
|
+
);
|
|
7370
|
+
}
|
|
7371
|
+
return await response.json();
|
|
7372
|
+
}
|
|
7224
7373
|
}
|
|
7225
7374
|
async function processTemplateTree(template) {
|
|
7226
7375
|
if (template.raw.baseImage) {
|
|
@@ -7292,24 +7441,24 @@ async function processTemplateTree(template) {
|
|
|
7292
7441
|
}
|
|
7293
7442
|
return template;
|
|
7294
7443
|
}
|
|
7295
|
-
async function ensureNestedTemplates(template, snapshots) {
|
|
7444
|
+
async function ensureNestedTemplates(template, snapshots, logger) {
|
|
7296
7445
|
const templates = [template];
|
|
7297
7446
|
while (isVmTemplateLike$1(templates.at(-1)?.raw.template)) {
|
|
7298
7447
|
const innerTemplate = templates.at(-1).raw.template;
|
|
7299
7448
|
templates.at(-1).raw.template = void 0;
|
|
7300
7449
|
templates.push(innerTemplate);
|
|
7301
7450
|
}
|
|
7302
|
-
return await layerTemplates(templates, snapshots);
|
|
7451
|
+
return await layerTemplates(templates, snapshots, logger);
|
|
7303
7452
|
}
|
|
7304
|
-
async function layerTemplates(templates, snapshots) {
|
|
7453
|
+
async function layerTemplates(templates, snapshots, logger) {
|
|
7305
7454
|
if (templates.length === 1) {
|
|
7306
7455
|
return templates[0];
|
|
7307
7456
|
}
|
|
7308
|
-
let lastSnapshotId = (await snapshots.ensure({ template: templates.pop() })).snapshotId;
|
|
7457
|
+
let lastSnapshotId = (await snapshots.ensure({ template: templates.pop(), logger })).snapshotId;
|
|
7309
7458
|
while (templates.length > 1) {
|
|
7310
7459
|
const template = templates.pop();
|
|
7311
7460
|
template.raw.snapshotId = lastSnapshotId;
|
|
7312
|
-
lastSnapshotId = (await snapshots.ensure({ template })).snapshotId;
|
|
7461
|
+
lastSnapshotId = (await snapshots.ensure({ template, logger })).snapshotId;
|
|
7313
7462
|
}
|
|
7314
7463
|
const outermost = templates.pop();
|
|
7315
7464
|
outermost.raw.snapshotId = lastSnapshotId;
|