freestyle-sandboxes 0.1.39 → 0.1.40
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 +328 -114
- package/index.d.cts +33 -4
- package/index.d.mts +33 -4
- package/index.mjs +328 -114
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -6009,6 +6009,64 @@ function composeVmSpecs(specs) {
|
|
|
6009
6009
|
}
|
|
6010
6010
|
|
|
6011
6011
|
const DEFAULT_CONFIGURE_BASE_IMAGE = "FROM debian:trixie-slim";
|
|
6012
|
+
const RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX = "freestyle-run-command";
|
|
6013
|
+
const WAIT_FOR_SYSTEMD_SERVICE_PREFIX = "freestyle-wait-for";
|
|
6014
|
+
function escapeRegExp(value) {
|
|
6015
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6016
|
+
}
|
|
6017
|
+
function getGeneratedServiceState(services, prefix) {
|
|
6018
|
+
const generatedPrefixes = [
|
|
6019
|
+
RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX,
|
|
6020
|
+
WAIT_FOR_SYSTEMD_SERVICE_PREFIX
|
|
6021
|
+
];
|
|
6022
|
+
let maxIndex = 0;
|
|
6023
|
+
let lastGeneratedServiceName;
|
|
6024
|
+
for (const service of services) {
|
|
6025
|
+
if (!service.name) {
|
|
6026
|
+
continue;
|
|
6027
|
+
}
|
|
6028
|
+
for (const generatedPrefix of generatedPrefixes) {
|
|
6029
|
+
const match = service.name.match(
|
|
6030
|
+
new RegExp(`^${escapeRegExp(generatedPrefix)}-(\\d+)$`)
|
|
6031
|
+
);
|
|
6032
|
+
if (!match) {
|
|
6033
|
+
continue;
|
|
6034
|
+
}
|
|
6035
|
+
if (generatedPrefix === prefix) {
|
|
6036
|
+
const index = Number.parseInt(match[1] ?? "0", 10);
|
|
6037
|
+
if (index > maxIndex) {
|
|
6038
|
+
maxIndex = index;
|
|
6039
|
+
}
|
|
6040
|
+
}
|
|
6041
|
+
lastGeneratedServiceName = service.name;
|
|
6042
|
+
break;
|
|
6043
|
+
}
|
|
6044
|
+
}
|
|
6045
|
+
return { maxIndex, lastGeneratedServiceName };
|
|
6046
|
+
}
|
|
6047
|
+
function appendServiceDependency(dependencies, dependency) {
|
|
6048
|
+
if (!dependency) {
|
|
6049
|
+
return dependencies ?? void 0;
|
|
6050
|
+
}
|
|
6051
|
+
const values = [...dependencies ?? []];
|
|
6052
|
+
if (!values.includes(dependency)) {
|
|
6053
|
+
values.push(dependency);
|
|
6054
|
+
}
|
|
6055
|
+
return values;
|
|
6056
|
+
}
|
|
6057
|
+
function buildWaitForScript(command, intervalSeconds) {
|
|
6058
|
+
const body = command.trim().split("\n").map((line) => ` ${line}`).join("\n");
|
|
6059
|
+
return [
|
|
6060
|
+
"while true; do",
|
|
6061
|
+
" if (",
|
|
6062
|
+
body,
|
|
6063
|
+
" ); then",
|
|
6064
|
+
" exit 0",
|
|
6065
|
+
" fi",
|
|
6066
|
+
` sleep ${intervalSeconds}`,
|
|
6067
|
+
"done"
|
|
6068
|
+
].join("\n");
|
|
6069
|
+
}
|
|
6012
6070
|
function processSystemdServices(services, existingFiles = {}) {
|
|
6013
6071
|
const additionalFiles = { ...existingFiles };
|
|
6014
6072
|
const processedServices = [];
|
|
@@ -6043,6 +6101,63 @@ ${bash}`;
|
|
|
6043
6101
|
}
|
|
6044
6102
|
return { services: processedServices, additionalFiles };
|
|
6045
6103
|
}
|
|
6104
|
+
function normalizeSystemdServices(services) {
|
|
6105
|
+
return services.map((service) => ({
|
|
6106
|
+
...service,
|
|
6107
|
+
after: service.after?.map((s) => s.includes(".") ? s : `${s}.service`),
|
|
6108
|
+
requires: service.requires?.map(
|
|
6109
|
+
(s) => s.includes(".") ? s : `${s}.service`
|
|
6110
|
+
),
|
|
6111
|
+
wantedBy: service.wantedBy?.map(
|
|
6112
|
+
(s) => s.includes(".") ? s : `${s}.service`
|
|
6113
|
+
)
|
|
6114
|
+
}));
|
|
6115
|
+
}
|
|
6116
|
+
function normalizePatchedServices(services) {
|
|
6117
|
+
return services.map((service) => ({
|
|
6118
|
+
...service,
|
|
6119
|
+
after: service.after?.map((s) => s.includes(".") ? s : `${s}.service`),
|
|
6120
|
+
requires: service.requires?.map(
|
|
6121
|
+
(s) => s.includes(".") ? s : `${s}.service`
|
|
6122
|
+
),
|
|
6123
|
+
wantedBy: service.wantedBy?.map(
|
|
6124
|
+
(s) => s.includes(".") ? s : `${s}.service`
|
|
6125
|
+
)
|
|
6126
|
+
}));
|
|
6127
|
+
}
|
|
6128
|
+
function normalizeTemplateForRequest(template) {
|
|
6129
|
+
const normalizedTemplate = {
|
|
6130
|
+
...template ?? {}
|
|
6131
|
+
};
|
|
6132
|
+
if (normalizedTemplate.template) {
|
|
6133
|
+
normalizedTemplate.template = normalizeTemplateForRequest(
|
|
6134
|
+
normalizedTemplate.template
|
|
6135
|
+
);
|
|
6136
|
+
}
|
|
6137
|
+
if (normalizedTemplate.baseImage) {
|
|
6138
|
+
normalizedTemplate.baseImage = normalizeBaseImage(
|
|
6139
|
+
normalizedTemplate.baseImage
|
|
6140
|
+
)?.toRaw();
|
|
6141
|
+
}
|
|
6142
|
+
normalizedTemplate.git = normalizeGitOptions(normalizedTemplate.git);
|
|
6143
|
+
if (normalizedTemplate.systemd?.services) {
|
|
6144
|
+
const normalizedServices = normalizeSystemdServices(
|
|
6145
|
+
normalizedTemplate.systemd.services
|
|
6146
|
+
);
|
|
6147
|
+
const { services: processedServices, additionalFiles: bashFiles } = processSystemdServices(
|
|
6148
|
+
normalizedServices,
|
|
6149
|
+
normalizedTemplate.additionalFiles ?? {}
|
|
6150
|
+
);
|
|
6151
|
+
normalizedTemplate.systemd.services = processedServices;
|
|
6152
|
+
normalizedTemplate.additionalFiles = bashFiles;
|
|
6153
|
+
}
|
|
6154
|
+
if (normalizedTemplate.systemd?.patchedServices) {
|
|
6155
|
+
normalizedTemplate.systemd.patchedServices = normalizePatchedServices(
|
|
6156
|
+
normalizedTemplate.systemd.patchedServices
|
|
6157
|
+
);
|
|
6158
|
+
}
|
|
6159
|
+
return normalizedTemplate;
|
|
6160
|
+
}
|
|
6046
6161
|
function normalizeGitOptions(git) {
|
|
6047
6162
|
if (!git) return git;
|
|
6048
6163
|
return {
|
|
@@ -6238,10 +6353,12 @@ class Vm {
|
|
|
6238
6353
|
params: { vm_id: this.vmId },
|
|
6239
6354
|
body: options
|
|
6240
6355
|
});
|
|
6241
|
-
const vmId = response.id;
|
|
6242
6356
|
return {
|
|
6243
|
-
|
|
6244
|
-
|
|
6357
|
+
forks: response.forks.map((fork) => ({
|
|
6358
|
+
vmId: fork.id,
|
|
6359
|
+
vm: this._freestyle.vms.ref({ vmId: fork.id })
|
|
6360
|
+
// Create a new Vm instance for the forked VM
|
|
6361
|
+
}))
|
|
6245
6362
|
};
|
|
6246
6363
|
}
|
|
6247
6364
|
/**
|
|
@@ -6390,10 +6507,14 @@ class VmSpec {
|
|
|
6390
6507
|
return { ...this.withDiscriminators };
|
|
6391
6508
|
}
|
|
6392
6509
|
mergeRaw(options) {
|
|
6510
|
+
const existingSnapshot = this.raw.snapshot;
|
|
6393
6511
|
this.raw = composeCreateVmOptions([
|
|
6394
6512
|
this.raw,
|
|
6395
6513
|
options
|
|
6396
6514
|
]);
|
|
6515
|
+
if (existingSnapshot !== void 0 && this.raw.snapshot === void 0) {
|
|
6516
|
+
this.raw.snapshot = existingSnapshot;
|
|
6517
|
+
}
|
|
6397
6518
|
return this;
|
|
6398
6519
|
}
|
|
6399
6520
|
clearBuilders() {
|
|
@@ -6477,9 +6598,74 @@ class VmSpec {
|
|
|
6477
6598
|
return this;
|
|
6478
6599
|
}
|
|
6479
6600
|
runCommands(...commands) {
|
|
6480
|
-
const
|
|
6481
|
-
|
|
6482
|
-
|
|
6601
|
+
const normalizedCommands = commands.map((command) => command.trim()).filter((command) => command.length > 0);
|
|
6602
|
+
if (normalizedCommands.length === 0) {
|
|
6603
|
+
return this;
|
|
6604
|
+
}
|
|
6605
|
+
const existingSystemd = this.raw.systemd ?? {};
|
|
6606
|
+
const existingServices = [...existingSystemd.services ?? []];
|
|
6607
|
+
let { maxIndex: maxRunCommandIndex, lastGeneratedServiceName } = getGeneratedServiceState(
|
|
6608
|
+
existingServices,
|
|
6609
|
+
RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX
|
|
6610
|
+
);
|
|
6611
|
+
for (const command of normalizedCommands) {
|
|
6612
|
+
const nextIndex = ++maxRunCommandIndex;
|
|
6613
|
+
const serviceName = `${RUN_COMMANDS_SYSTEMD_SERVICE_PREFIX}-${nextIndex}`;
|
|
6614
|
+
existingServices.push({
|
|
6615
|
+
name: serviceName,
|
|
6616
|
+
mode: "oneshot",
|
|
6617
|
+
deleteAfterSuccess: true,
|
|
6618
|
+
bash: command,
|
|
6619
|
+
...lastGeneratedServiceName ? {
|
|
6620
|
+
after: [lastGeneratedServiceName],
|
|
6621
|
+
requires: [lastGeneratedServiceName]
|
|
6622
|
+
} : {}
|
|
6623
|
+
});
|
|
6624
|
+
lastGeneratedServiceName = serviceName;
|
|
6625
|
+
}
|
|
6626
|
+
this.raw.systemd = {
|
|
6627
|
+
...existingSystemd,
|
|
6628
|
+
services: existingServices
|
|
6629
|
+
};
|
|
6630
|
+
return this;
|
|
6631
|
+
}
|
|
6632
|
+
waitFor(command, config = {}) {
|
|
6633
|
+
const trimmedCommand = command.trim();
|
|
6634
|
+
if (!trimmedCommand) {
|
|
6635
|
+
throw new Error("VmSpec.waitFor requires a non-empty command");
|
|
6636
|
+
}
|
|
6637
|
+
const intervalSeconds = config.intervalSeconds ?? 2;
|
|
6638
|
+
if (!Number.isFinite(intervalSeconds) || intervalSeconds <= 0) {
|
|
6639
|
+
throw new Error("VmSpec.waitFor intervalSeconds must be greater than 0");
|
|
6640
|
+
}
|
|
6641
|
+
const existingSystemd = this.raw.systemd ?? {};
|
|
6642
|
+
const existingServices = [...existingSystemd.services ?? []];
|
|
6643
|
+
const { maxIndex, lastGeneratedServiceName } = getGeneratedServiceState(
|
|
6644
|
+
existingServices,
|
|
6645
|
+
WAIT_FOR_SYSTEMD_SERVICE_PREFIX
|
|
6646
|
+
);
|
|
6647
|
+
const {
|
|
6648
|
+
intervalSeconds: _intervalSeconds,
|
|
6649
|
+
name,
|
|
6650
|
+
after,
|
|
6651
|
+
requires,
|
|
6652
|
+
timeoutSec,
|
|
6653
|
+
...rest
|
|
6654
|
+
} = config;
|
|
6655
|
+
existingServices.push({
|
|
6656
|
+
...rest,
|
|
6657
|
+
name: name ?? `${WAIT_FOR_SYSTEMD_SERVICE_PREFIX}-${maxIndex + 1}`,
|
|
6658
|
+
mode: "oneshot",
|
|
6659
|
+
// deleteAfterSuccess: true,
|
|
6660
|
+
timeoutSec: timeoutSec ?? 0,
|
|
6661
|
+
after: appendServiceDependency(after, lastGeneratedServiceName),
|
|
6662
|
+
requires: appendServiceDependency(requires, lastGeneratedServiceName),
|
|
6663
|
+
bash: buildWaitForScript(trimmedCommand, intervalSeconds)
|
|
6664
|
+
});
|
|
6665
|
+
this.raw.systemd = {
|
|
6666
|
+
...existingSystemd,
|
|
6667
|
+
services: existingServices
|
|
6668
|
+
};
|
|
6483
6669
|
return this;
|
|
6484
6670
|
}
|
|
6485
6671
|
repo(repo, path) {
|
|
@@ -6506,7 +6692,7 @@ class VmSpec {
|
|
|
6506
6692
|
function isVmSpecLike$1(value) {
|
|
6507
6693
|
return !!value && typeof value === "object" && "raw" in value && "with" in value;
|
|
6508
6694
|
}
|
|
6509
|
-
function isVmTemplateLike(value) {
|
|
6695
|
+
function isVmTemplateLike$1(value) {
|
|
6510
6696
|
return !!value && typeof value === "object" && "raw" in value && "with" in value;
|
|
6511
6697
|
}
|
|
6512
6698
|
async function convertSpecSnapshotsToTemplates(spec, processBuilders = true) {
|
|
@@ -6632,21 +6818,8 @@ class VmsNamespace {
|
|
|
6632
6818
|
}
|
|
6633
6819
|
}
|
|
6634
6820
|
if (options.systemd?.services) {
|
|
6635
|
-
const normalizedServices =
|
|
6636
|
-
|
|
6637
|
-
return {
|
|
6638
|
-
...service,
|
|
6639
|
-
after: service.after?.map(
|
|
6640
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6641
|
-
),
|
|
6642
|
-
requires: service.requires?.map(
|
|
6643
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6644
|
-
),
|
|
6645
|
-
wantedBy: service.wantedBy?.map(
|
|
6646
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6647
|
-
)
|
|
6648
|
-
};
|
|
6649
|
-
}
|
|
6821
|
+
const normalizedServices = normalizeSystemdServices(
|
|
6822
|
+
options.systemd.services
|
|
6650
6823
|
);
|
|
6651
6824
|
const { services: processedServices, additionalFiles: bashFiles } = processSystemdServices(
|
|
6652
6825
|
normalizedServices,
|
|
@@ -6656,19 +6829,8 @@ class VmsNamespace {
|
|
|
6656
6829
|
options.additionalFiles = bashFiles;
|
|
6657
6830
|
}
|
|
6658
6831
|
if (options.systemd?.patchedServices) {
|
|
6659
|
-
options.systemd.patchedServices =
|
|
6660
|
-
|
|
6661
|
-
service.after = service.after?.map(
|
|
6662
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6663
|
-
);
|
|
6664
|
-
service.requires = service.requires?.map(
|
|
6665
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6666
|
-
);
|
|
6667
|
-
service.wantedBy = service.wantedBy?.map(
|
|
6668
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6669
|
-
);
|
|
6670
|
-
return service;
|
|
6671
|
-
}
|
|
6832
|
+
options.systemd.patchedServices = normalizePatchedServices(
|
|
6833
|
+
options.systemd.patchedServices
|
|
6672
6834
|
);
|
|
6673
6835
|
}
|
|
6674
6836
|
if ("snapshot" in options) {
|
|
@@ -6701,7 +6863,7 @@ class VmsNamespace {
|
|
|
6701
6863
|
const specBuilders = isVmSpecLike$1(
|
|
6702
6864
|
options.spec
|
|
6703
6865
|
) ? collectSpecBuilders(options.spec) : void 0;
|
|
6704
|
-
const templateBuilders = isVmTemplateLike(options.template) ? options.template.with : void 0;
|
|
6866
|
+
const templateBuilders = isVmTemplateLike$1(options.template) ? options.template.with : void 0;
|
|
6705
6867
|
const builders = {
|
|
6706
6868
|
...templateBuilders || {},
|
|
6707
6869
|
...specBuilders || {},
|
|
@@ -6709,10 +6871,10 @@ class VmsNamespace {
|
|
|
6709
6871
|
};
|
|
6710
6872
|
const { with: _, spec: _spec, ...baseConfig } = options;
|
|
6711
6873
|
let config = baseConfig;
|
|
6712
|
-
if (isVmTemplateLike(config.template)) {
|
|
6874
|
+
if (isVmTemplateLike$1(config.template)) {
|
|
6713
6875
|
config.template = await processTemplateTree(config.template);
|
|
6714
6876
|
}
|
|
6715
|
-
if (isVmTemplateLike(config.template)) {
|
|
6877
|
+
if (isVmTemplateLike$1(config.template)) {
|
|
6716
6878
|
config.template = await ensureNestedTemplates(
|
|
6717
6879
|
config.template,
|
|
6718
6880
|
this.snapshots
|
|
@@ -6726,18 +6888,9 @@ class VmsNamespace {
|
|
|
6726
6888
|
}
|
|
6727
6889
|
}
|
|
6728
6890
|
if (config.systemd?.services) {
|
|
6729
|
-
const normalizedServices =
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6733
|
-
),
|
|
6734
|
-
requires: service.requires?.map(
|
|
6735
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6736
|
-
),
|
|
6737
|
-
wantedBy: service.wantedBy?.map(
|
|
6738
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6739
|
-
)
|
|
6740
|
-
}));
|
|
6891
|
+
const normalizedServices = normalizeSystemdServices(
|
|
6892
|
+
config.systemd.services
|
|
6893
|
+
);
|
|
6741
6894
|
const { services: processedServices, additionalFiles: bashFiles } = processSystemdServices(
|
|
6742
6895
|
normalizedServices,
|
|
6743
6896
|
config.additionalFiles ?? {}
|
|
@@ -6746,28 +6899,20 @@ class VmsNamespace {
|
|
|
6746
6899
|
config.additionalFiles = bashFiles;
|
|
6747
6900
|
}
|
|
6748
6901
|
if (config.systemd?.patchedServices) {
|
|
6749
|
-
config.systemd.patchedServices =
|
|
6750
|
-
|
|
6751
|
-
service.after = service.after?.map(
|
|
6752
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6753
|
-
);
|
|
6754
|
-
service.requires = service.requires?.map(
|
|
6755
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6756
|
-
);
|
|
6757
|
-
service.wantedBy = service.wantedBy?.map(
|
|
6758
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6759
|
-
);
|
|
6760
|
-
return service;
|
|
6761
|
-
}
|
|
6902
|
+
config.systemd.patchedServices = normalizePatchedServices(
|
|
6903
|
+
config.systemd.patchedServices
|
|
6762
6904
|
);
|
|
6763
6905
|
}
|
|
6764
6906
|
config.git = normalizeGitOptions(config.git);
|
|
6765
6907
|
const serializedBaseImage = normalizeBaseImage(config.baseImage)?.toRaw();
|
|
6766
|
-
const rawTemplate = isVmTemplateLike(config.template) ? config.template.raw : config.template;
|
|
6908
|
+
const rawTemplate = isVmTemplateLike$1(config.template) ? config.template.raw : config.template;
|
|
6767
6909
|
const requestTemplate = serializedBaseImage ? {
|
|
6768
6910
|
...rawTemplate ?? {},
|
|
6769
6911
|
baseImage: serializedBaseImage
|
|
6770
6912
|
} : rawTemplate;
|
|
6913
|
+
const normalizedRequestTemplate = requestTemplate ? normalizeTemplateForRequest(
|
|
6914
|
+
requestTemplate
|
|
6915
|
+
) : requestTemplate;
|
|
6771
6916
|
const {
|
|
6772
6917
|
baseImage: _baseImage,
|
|
6773
6918
|
template: _template,
|
|
@@ -6776,7 +6921,7 @@ class VmsNamespace {
|
|
|
6776
6921
|
const response = await this.freestyle._apiClient.post("/v1/vms", {
|
|
6777
6922
|
body: {
|
|
6778
6923
|
...requestConfig,
|
|
6779
|
-
template:
|
|
6924
|
+
template: normalizedRequestTemplate,
|
|
6780
6925
|
// Cast systemd since we've processed SystemdServiceInput[] to RawSystemdService[]
|
|
6781
6926
|
systemd: config.systemd,
|
|
6782
6927
|
// Normalize git options - default config to {}
|
|
@@ -6871,6 +7016,35 @@ function enhanceError(e) {
|
|
|
6871
7016
|
if (!e.message.includes("create --snapshot")) {
|
|
6872
7017
|
e.message = `${e.message}. Hint: use \`npx freestyle-sandboxes@latest vm create --snapshot ${e.body.snapshotId} --ssh --delete\` to debug.`;
|
|
6873
7018
|
}
|
|
7019
|
+
if (e.body.diagnostics) {
|
|
7020
|
+
const d = e.body.diagnostics;
|
|
7021
|
+
const parts = [];
|
|
7022
|
+
if (d.serviceStates.length > 0) {
|
|
7023
|
+
parts.push("Service states:");
|
|
7024
|
+
for (const g of d.serviceStates) {
|
|
7025
|
+
parts.push(
|
|
7026
|
+
` ${g.activeState}(${g.subState}): ${g.services.join(", ")}`
|
|
7027
|
+
);
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
const allLogs = [
|
|
7031
|
+
...d.failedServiceLogs ?? [],
|
|
7032
|
+
...d.additionalFailedServiceLogs ?? []
|
|
7033
|
+
];
|
|
7034
|
+
if (allLogs.length > 0) {
|
|
7035
|
+
parts.push("Failed service logs:");
|
|
7036
|
+
for (const l of allLogs) {
|
|
7037
|
+
parts.push(` --- ${l.unitName} ---`);
|
|
7038
|
+
parts.push(` ${l.log}`);
|
|
7039
|
+
}
|
|
7040
|
+
}
|
|
7041
|
+
if (parts.length > 0) {
|
|
7042
|
+
e.message = `${e.message}
|
|
7043
|
+
|
|
7044
|
+
Diagnostics:
|
|
7045
|
+
${parts.join("\n")}`;
|
|
7046
|
+
}
|
|
7047
|
+
}
|
|
6874
7048
|
}
|
|
6875
7049
|
return e;
|
|
6876
7050
|
}
|
|
@@ -6938,12 +7112,12 @@ class VmSnapshotsNamespace {
|
|
|
6938
7112
|
const { spec: _spec, ...rest } = requestOptions;
|
|
6939
7113
|
requestOptions = rest;
|
|
6940
7114
|
}
|
|
6941
|
-
if (isVmTemplateLike(requestOptions.template)) {
|
|
7115
|
+
if (isVmTemplateLike$1(requestOptions.template)) {
|
|
6942
7116
|
const processedTemplate = await processTemplateTree(
|
|
6943
7117
|
requestOptions.template
|
|
6944
7118
|
);
|
|
6945
7119
|
requestOptions.template = processedTemplate;
|
|
6946
|
-
if (isVmTemplateLike(processedTemplate.raw.template)) {
|
|
7120
|
+
if (isVmTemplateLike$1(processedTemplate.raw.template)) {
|
|
6947
7121
|
requestOptions.template = await ensureNestedTemplates(
|
|
6948
7122
|
processedTemplate,
|
|
6949
7123
|
this
|
|
@@ -6958,7 +7132,9 @@ class VmSnapshotsNamespace {
|
|
|
6958
7132
|
return this.apiClient.post("/v1/vms/snapshots", {
|
|
6959
7133
|
body: {
|
|
6960
7134
|
...requestOptions,
|
|
6961
|
-
template:
|
|
7135
|
+
template: normalizeTemplateForRequest(
|
|
7136
|
+
isVmTemplateLike$1(requestOptions.template) ? requestOptions.template.raw : requestOptions.template
|
|
7137
|
+
)
|
|
6962
7138
|
}
|
|
6963
7139
|
}).catch((e) => {
|
|
6964
7140
|
enhanceError(e);
|
|
@@ -6978,22 +7154,9 @@ async function processTemplateTree(template) {
|
|
|
6978
7154
|
);
|
|
6979
7155
|
}
|
|
6980
7156
|
if (template.raw.systemd?.services) {
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
after: service.after?.map((s) => s.includes(".") ? s : `${s}.service`),
|
|
6984
|
-
requires: service.requires?.map(
|
|
6985
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6986
|
-
),
|
|
6987
|
-
wantedBy: service.wantedBy?.map(
|
|
6988
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
6989
|
-
)
|
|
6990
|
-
}));
|
|
6991
|
-
const { services: processedServices, additionalFiles: bashFiles } = processSystemdServices(
|
|
6992
|
-
normalizedServices,
|
|
6993
|
-
template.raw.additionalFiles ?? {}
|
|
7157
|
+
template.raw.systemd.services = normalizeSystemdServices(
|
|
7158
|
+
template.raw.systemd.services
|
|
6994
7159
|
);
|
|
6995
|
-
template.raw.systemd.services = processedServices;
|
|
6996
|
-
template.raw.additionalFiles = bashFiles;
|
|
6997
7160
|
}
|
|
6998
7161
|
for (const key in template.with) {
|
|
6999
7162
|
const builder = template.with[key];
|
|
@@ -7010,7 +7173,7 @@ async function processTemplateTree(template) {
|
|
|
7010
7173
|
}
|
|
7011
7174
|
if (builder.configureNestedTemplate) {
|
|
7012
7175
|
let nestedTemplate;
|
|
7013
|
-
if (isVmTemplateLike(template.raw.template)) {
|
|
7176
|
+
if (isVmTemplateLike$1(template.raw.template)) {
|
|
7014
7177
|
nestedTemplate = template.raw.template;
|
|
7015
7178
|
} else {
|
|
7016
7179
|
nestedTemplate = new VmTemplate({});
|
|
@@ -7033,38 +7196,16 @@ async function processTemplateTree(template) {
|
|
|
7033
7196
|
);
|
|
7034
7197
|
}
|
|
7035
7198
|
if (template.raw.systemd?.services) {
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
after: service.after?.map((s) => s.includes(".") ? s : `${s}.service`),
|
|
7039
|
-
requires: service.requires?.map(
|
|
7040
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
7041
|
-
),
|
|
7042
|
-
wantedBy: service.wantedBy?.map(
|
|
7043
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
7044
|
-
)
|
|
7045
|
-
}));
|
|
7046
|
-
const { services: processedServices, additionalFiles: bashFiles } = processSystemdServices(
|
|
7047
|
-
normalizedServices,
|
|
7048
|
-
template.raw.additionalFiles ?? {}
|
|
7199
|
+
template.raw.systemd.services = normalizeSystemdServices(
|
|
7200
|
+
template.raw.systemd.services
|
|
7049
7201
|
);
|
|
7050
|
-
template.raw.systemd.services = processedServices;
|
|
7051
|
-
template.raw.additionalFiles = bashFiles;
|
|
7052
7202
|
}
|
|
7053
7203
|
if (template.raw.systemd?.patchedServices) {
|
|
7054
|
-
template.raw.systemd.patchedServices =
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
7058
|
-
),
|
|
7059
|
-
requires: service.requires?.map(
|
|
7060
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
7061
|
-
),
|
|
7062
|
-
wantedBy: service.wantedBy?.map(
|
|
7063
|
-
(s) => s.includes(".") ? s : `${s}.service`
|
|
7064
|
-
)
|
|
7065
|
-
}));
|
|
7204
|
+
template.raw.systemd.patchedServices = normalizePatchedServices(
|
|
7205
|
+
template.raw.systemd.patchedServices
|
|
7206
|
+
);
|
|
7066
7207
|
}
|
|
7067
|
-
if (isVmTemplateLike(template.raw.template)) {
|
|
7208
|
+
if (isVmTemplateLike$1(template.raw.template)) {
|
|
7068
7209
|
template.raw.template = await processTemplateTree(
|
|
7069
7210
|
template.raw.template
|
|
7070
7211
|
);
|
|
@@ -7073,7 +7214,7 @@ async function processTemplateTree(template) {
|
|
|
7073
7214
|
}
|
|
7074
7215
|
async function ensureNestedTemplates(template, snapshots) {
|
|
7075
7216
|
const templates = [template];
|
|
7076
|
-
while (isVmTemplateLike(templates.at(-1)?.raw.template)) {
|
|
7217
|
+
while (isVmTemplateLike$1(templates.at(-1)?.raw.template)) {
|
|
7077
7218
|
const innerTemplate = templates.at(-1).raw.template;
|
|
7078
7219
|
templates.at(-1).raw.template = void 0;
|
|
7079
7220
|
templates.push(innerTemplate);
|
|
@@ -7258,7 +7399,7 @@ async function readFiles(directory) {
|
|
|
7258
7399
|
}
|
|
7259
7400
|
|
|
7260
7401
|
async function debugCreateRequests(freestyle, optionsOrSpec = {}) {
|
|
7261
|
-
const options = isVmSpecLike(optionsOrSpec) ? { spec: optionsOrSpec } : optionsOrSpec;
|
|
7402
|
+
const options = isVmSpecLike(optionsOrSpec) ? { spec: cloneVmSpec(optionsOrSpec) } : cloneCreateOptions(optionsOrSpec);
|
|
7262
7403
|
const requests = [];
|
|
7263
7404
|
let snapshotCounter = 0;
|
|
7264
7405
|
let vmCounter = 0;
|
|
@@ -7305,6 +7446,79 @@ async function debugCreateRequests(freestyle, optionsOrSpec = {}) {
|
|
|
7305
7446
|
function isVmSpecLike(value) {
|
|
7306
7447
|
return !!value && typeof value === "object" && "raw" in value && "with" in value;
|
|
7307
7448
|
}
|
|
7449
|
+
function isVmTemplateLike(value) {
|
|
7450
|
+
return !!value && typeof value === "object" && "raw" in value && "with" in value;
|
|
7451
|
+
}
|
|
7452
|
+
function cloneCreateOptions(options) {
|
|
7453
|
+
return {
|
|
7454
|
+
...clonePlainObject(options),
|
|
7455
|
+
with: options.with,
|
|
7456
|
+
template: isVmTemplateLike(options.template) ? cloneVmTemplate(options.template) : cloneValue(options.template),
|
|
7457
|
+
spec: isVmSpecLike(options.spec) ? cloneVmSpec(options.spec) : void 0,
|
|
7458
|
+
snapshot: isVmSpecLike(options.snapshot) ? cloneVmSpec(options.snapshot) : void 0
|
|
7459
|
+
};
|
|
7460
|
+
}
|
|
7461
|
+
function cloneVmSpec(spec) {
|
|
7462
|
+
const clonedRaw = cloneVmSpecRaw(spec.raw);
|
|
7463
|
+
return new VmSpec({
|
|
7464
|
+
...clonedRaw,
|
|
7465
|
+
with: { ...spec.builders },
|
|
7466
|
+
__withDiscriminators: typeof spec.getBuilderDiscriminators === "function" ? spec.getBuilderDiscriminators() : void 0
|
|
7467
|
+
});
|
|
7468
|
+
}
|
|
7469
|
+
function cloneVmTemplate(template) {
|
|
7470
|
+
const clonedRaw = cloneVmTemplateRaw(template.raw);
|
|
7471
|
+
return new VmTemplate({
|
|
7472
|
+
...clonedRaw,
|
|
7473
|
+
with: { ...template.with }
|
|
7474
|
+
});
|
|
7475
|
+
}
|
|
7476
|
+
function cloneVmSpecRaw(raw) {
|
|
7477
|
+
const cloned = cloneVmTemplateRaw(raw);
|
|
7478
|
+
if (isVmSpecLike(raw.snapshot)) {
|
|
7479
|
+
cloned.snapshot = cloneVmSpec(raw.snapshot);
|
|
7480
|
+
} else if (raw.snapshot !== void 0) {
|
|
7481
|
+
cloned.snapshot = cloneValue(raw.snapshot);
|
|
7482
|
+
}
|
|
7483
|
+
return cloned;
|
|
7484
|
+
}
|
|
7485
|
+
function cloneVmTemplateRaw(raw) {
|
|
7486
|
+
const cloned = clonePlainObject(raw);
|
|
7487
|
+
if (isVmTemplateLike(raw.template)) {
|
|
7488
|
+
cloned.template = cloneVmTemplate(raw.template);
|
|
7489
|
+
} else if (raw.template !== void 0) {
|
|
7490
|
+
cloned.template = cloneValue(raw.template);
|
|
7491
|
+
}
|
|
7492
|
+
return cloned;
|
|
7493
|
+
}
|
|
7494
|
+
function clonePlainObject(value) {
|
|
7495
|
+
if (!value || typeof value !== "object") {
|
|
7496
|
+
return value;
|
|
7497
|
+
}
|
|
7498
|
+
const cloned = {};
|
|
7499
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
7500
|
+
cloned[key] = cloneValue(entry);
|
|
7501
|
+
}
|
|
7502
|
+
return cloned;
|
|
7503
|
+
}
|
|
7504
|
+
function cloneValue(value) {
|
|
7505
|
+
if (value instanceof VmBaseImage) {
|
|
7506
|
+
return new VmBaseImage(value.toRaw());
|
|
7507
|
+
}
|
|
7508
|
+
if (isVmSpecLike(value)) {
|
|
7509
|
+
return cloneVmSpec(value);
|
|
7510
|
+
}
|
|
7511
|
+
if (isVmTemplateLike(value)) {
|
|
7512
|
+
return cloneVmTemplate(value);
|
|
7513
|
+
}
|
|
7514
|
+
if (Array.isArray(value)) {
|
|
7515
|
+
return value.map((entry) => cloneValue(entry));
|
|
7516
|
+
}
|
|
7517
|
+
if (value && typeof value === "object") {
|
|
7518
|
+
return clonePlainObject(value);
|
|
7519
|
+
}
|
|
7520
|
+
return value;
|
|
7521
|
+
}
|
|
7308
7522
|
|
|
7309
7523
|
class Freestyle {
|
|
7310
7524
|
/**
|