hostctl 0.1.41 → 0.1.42

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/index.js CHANGED
@@ -2581,7 +2581,7 @@ var Verbosity = {
2581
2581
  };
2582
2582
 
2583
2583
  // src/version.ts
2584
- var version = "0.1.41";
2584
+ var version = "0.1.42";
2585
2585
 
2586
2586
  // src/commands/pkg/create.ts
2587
2587
  import { promises as fs5 } from "fs";
@@ -6186,7 +6186,7 @@ __export(dir_exports, {
6186
6186
  // src/core/dir/exists.ts
6187
6187
  async function run5(context) {
6188
6188
  const { params, exec, error } = context;
6189
- const { path: path10 } = params;
6189
+ const { path: path10, sudo = false } = params;
6190
6190
  if (!path10) {
6191
6191
  error('Required parameter "path" is missing');
6192
6192
  return {
@@ -6196,8 +6196,7 @@ async function run5(context) {
6196
6196
  };
6197
6197
  }
6198
6198
  try {
6199
- const command = ["test", "-d", path10].join(" ");
6200
- const { success: exists2 } = await exec(command);
6199
+ const { success: exists2 } = await exec(["test", "-d", path10], { sudo });
6201
6200
  return {
6202
6201
  exists: exists2,
6203
6202
  success: true
@@ -6423,7 +6422,7 @@ var copy_default2 = task(run9, { name: "core.dir.copy", description: "Dir copy."
6423
6422
 
6424
6423
  // src/core/dir/create.ts
6425
6424
  async function runFn(context) {
6426
- const { params, exec, run: run245 } = context;
6425
+ const { params, exec, run: run247 } = context;
6427
6426
  const { path: path10, mode, owner } = params;
6428
6427
  if (!path10) {
6429
6428
  return {
@@ -6447,7 +6446,7 @@ async function runFn(context) {
6447
6446
  }
6448
6447
  let chmodSuccess = true;
6449
6448
  if (mode && mkdirSuccess) {
6450
- const chmodResult = await run245(chmod_default({ path: path10, mode, sudo: !!owner }));
6449
+ const chmodResult = await run247(chmod_default({ path: path10, mode, sudo: !!owner }));
6451
6450
  chmodSuccess = chmodResult?.success ?? false;
6452
6451
  }
6453
6452
  return {
@@ -6525,7 +6524,7 @@ var chgrp_default = task(run10, { name: "core.file.chgrp", description: "Chgrp."
6525
6524
  // src/core/file/exists.ts
6526
6525
  async function run11(context) {
6527
6526
  const { params, exec, error } = context;
6528
- const { path: path10 } = params;
6527
+ const { path: path10, sudo = false } = params;
6529
6528
  if (!path10) {
6530
6529
  error('Required parameter "path" is missing');
6531
6530
  return {
@@ -6535,7 +6534,7 @@ async function run11(context) {
6535
6534
  };
6536
6535
  }
6537
6536
  try {
6538
- const { success: exists2 } = await exec(["test", "-f", path10]);
6537
+ const { success: exists2 } = await exec(["test", "-f", path10], { sudo });
6539
6538
  return {
6540
6539
  exists: exists2,
6541
6540
  success: true
@@ -6553,7 +6552,7 @@ var exists_default2 = task(run11, { name: "core.file.exists", description: "File
6553
6552
  // src/core/file/touch.ts
6554
6553
  async function run12(context) {
6555
6554
  const { params, exec, run: runTask, error } = context;
6556
- const { file, mode, owner } = params;
6555
+ const { file, mode, owner, sudo = false } = params;
6557
6556
  if (!file) {
6558
6557
  error('Required parameter "file" is missing');
6559
6558
  return {
@@ -6565,6 +6564,8 @@ async function run12(context) {
6565
6564
  const touchCommandArray = [];
6566
6565
  if (owner) {
6567
6566
  touchCommandArray.push("sudo", "-u", owner);
6567
+ } else if (sudo) {
6568
+ touchCommandArray.push("sudo");
6568
6569
  }
6569
6570
  touchCommandArray.push("touch", file);
6570
6571
  const { success: touchSuccess } = await exec(touchCommandArray);
@@ -6580,8 +6581,7 @@ async function run12(context) {
6580
6581
  chmod_default({
6581
6582
  path: file,
6582
6583
  mode,
6583
- sudo: !!owner
6584
- // Original logic: sudo for chmod is based on owner presence
6584
+ sudo: !!owner || sudo
6585
6585
  })
6586
6586
  );
6587
6587
  chmodSuccess = chmodResult?.success ?? false;
@@ -6601,7 +6601,7 @@ var touch_default = task(run12, { name: "core.file.touch", description: "Touches
6601
6601
  // src/core/file/delete.ts
6602
6602
  async function run13(context) {
6603
6603
  const { params, exec, error } = context;
6604
- const { path: path10, recursive = false, force = false } = params;
6604
+ const { path: path10, recursive = false, force = false, sudo = false } = params;
6605
6605
  if (!path10) {
6606
6606
  error('Required parameter "path" is missing');
6607
6607
  return {
@@ -6610,8 +6610,8 @@ async function run13(context) {
6610
6610
  };
6611
6611
  }
6612
6612
  try {
6613
- const p = Path.new(path10);
6614
- if (!await p.exists()) {
6613
+ const { success: exists2 } = await exec(["test", "-e", path10], { sudo });
6614
+ if (!exists2) {
6615
6615
  return {
6616
6616
  success: true
6617
6617
  };
@@ -6625,7 +6625,7 @@ async function run13(context) {
6625
6625
  }
6626
6626
  args.push("--");
6627
6627
  args.push(path10);
6628
- const { success } = await exec(["rm", ...args]);
6628
+ const { success } = await exec(["rm", ...args], { sudo });
6629
6629
  return {
6630
6630
  success
6631
6631
  };
@@ -6695,6 +6695,17 @@ var KeySequence = {
6695
6695
  // src/core/file/edit.ts
6696
6696
  import { dirname as dirname2 } from "path";
6697
6697
 
6698
+ // src/util/ansi.ts
6699
+ var OSC_SEQUENCE_REGEX = /\u001b\][\s\S]*?(?:\u0007|\u001b\\)/g;
6700
+ var CSI_SEQUENCE_REGEX = /\u001b\[[0-9;?]*[ -\/]*[@-~]/g;
6701
+ var TWO_CHAR_ESCAPE_REGEX = /\u001b[@-_]/g;
6702
+ function stripAnsiSequences(input) {
6703
+ if (!input) {
6704
+ return "";
6705
+ }
6706
+ return input.replace(OSC_SEQUENCE_REGEX, "").replace(CSI_SEQUENCE_REGEX, "").replace(TWO_CHAR_ESCAPE_REGEX, "").replace(/\u0007/g, "");
6707
+ }
6708
+
6698
6709
  // src/core/file/grep.ts
6699
6710
  async function run15(context) {
6700
6711
  const { params, exec, error } = context;
@@ -6710,7 +6721,8 @@ async function run15(context) {
6710
6721
  after_context,
6711
6722
  context: contextLines,
6712
6723
  max_count,
6713
- return_lines = false
6724
+ return_lines = false,
6725
+ sudo = false
6714
6726
  } = params;
6715
6727
  if (!file) {
6716
6728
  error('Required parameter "file" is missing');
@@ -6750,12 +6762,13 @@ async function run15(context) {
6750
6762
  if (after_context !== void 0) grepArgs.push("-A", String(after_context));
6751
6763
  if (max_count !== void 0) grepArgs.push("-m", String(max_count));
6752
6764
  grepArgs.push(pattern, file);
6753
- const { success, stdout } = await exec(grepArgs);
6765
+ const { success, stdout } = await exec(grepArgs, { sudo });
6766
+ const cleanedStdout = stripAnsiSequences(stdout);
6754
6767
  if (!needContent) {
6755
- const count = stdout ? parseInt(stdout.trim(), 10) : 0;
6768
+ const count = cleanedStdout ? parseInt(cleanedStdout.trim(), 10) : 0;
6756
6769
  return { found: success, count, success: true };
6757
6770
  }
6758
- const lines = stdout ? stdout.trim().split("\n").map((l) => l.replace(/\r$/, "")).filter((l) => l.length > 0) : [];
6771
+ const lines = cleanedStdout ? cleanedStdout.trim().split("\n").map((l) => l.replace(/\r$/, "")).filter((l) => l.length > 0) : [];
6759
6772
  return {
6760
6773
  found: success,
6761
6774
  count: lines.length,
@@ -6786,7 +6799,7 @@ async function ensureFile(context, file, sudo) {
6786
6799
  await exec(["touch", file], { sudo });
6787
6800
  }
6788
6801
  async function runFn2(context) {
6789
- const { params, exec, info, run: run245, error } = context;
6802
+ const { params, exec, info, run: run247, error } = context;
6790
6803
  const {
6791
6804
  file,
6792
6805
  state = "present",
@@ -8082,8 +8095,8 @@ async function run37(context) {
8082
8095
  }
8083
8096
  try {
8084
8097
  const cmd = `curl -fsSL ${url} | gpg --dearmor -o ${keyring}`;
8085
- info(`Executing: ${cmd}`);
8086
- const result = await exec(cmd, { sudo });
8098
+ info(`Adding apt key from ${url} to ${keyring}`);
8099
+ const result = await exec(["bash", "-lc", cmd], { sudo });
8087
8100
  if (result.exitCode !== 0) {
8088
8101
  const errorMsg = `Failed to add key: ${result.stderr}`;
8089
8102
  error(errorMsg);
@@ -8115,9 +8128,11 @@ async function run38(context) {
8115
8128
  }
8116
8129
  const listFilePath = path5.join("/etc/apt/sources.list.d", `${name}.list`);
8117
8130
  try {
8118
- const cmd = `echo "${repo}" > ${listFilePath}`;
8119
- info(`Executing: ${cmd}`);
8120
- const result = await exec(cmd, { sudo });
8131
+ const heredoc = `cat <<'EOF' > ${listFilePath}
8132
+ ${repo}
8133
+ EOF`;
8134
+ info(`Writing repository definition to ${listFilePath}`);
8135
+ const result = await exec(["bash", "-lc", heredoc], { sudo });
8121
8136
  if (result.exitCode !== 0) {
8122
8137
  const errorMsg = `Failed to add repository: ${result.stderr}`;
8123
8138
  error(errorMsg);
@@ -9809,13 +9824,13 @@ var PACKAGE_MANAGERS = {
9809
9824
  },
9810
9825
  pacman: {
9811
9826
  name: "pacman",
9812
- installCommand: ["pacman", "-S", "--noconfirm", "--needed", "--quiet"],
9813
- uninstallCommand: ["pacman", "-R", "--noconfirm", "--cascade", "--quiet"],
9814
- updateCommand: ["pacman", "-Sy", "--quiet"],
9815
- upgradeCommand: ["pacman", "-Syu", "--noconfirm", "--quiet"],
9827
+ installCommand: ["pacman", "-S", "--noconfirm", "--needed"],
9828
+ uninstallCommand: ["pacman", "-R", "--noconfirm", "--cascade"],
9829
+ updateCommand: ["pacman", "-Sy"],
9830
+ upgradeCommand: ["pacman", "-Syu", "--noconfirm"],
9816
9831
  searchCommand: ["pacman", "-Ss"],
9817
- listCommand: ["pacman", "-Q", "--quiet"],
9818
- cleanCommand: ["pacman", "-Sc", "--noconfirm", "--quiet"]
9832
+ listCommand: ["pacman", "-Q"],
9833
+ cleanCommand: ["pacman", "-Sc", "--noconfirm"]
9819
9834
  },
9820
9835
  zypper: {
9821
9836
  name: "zypper",
@@ -9882,28 +9897,41 @@ var PACKAGE_MANAGERS = {
9882
9897
  cleanCommand: ["brew", "cleanup", "--quiet", "--no-progress"]
9883
9898
  }
9884
9899
  };
9900
+ async function commandExists(exec, binary) {
9901
+ const candidates = [
9902
+ ["/bin/sh", "-c", `command -v ${binary} >/dev/null 2>&1`],
9903
+ ["which", binary],
9904
+ ["cmd", "/c", `where ${binary}`]
9905
+ ];
9906
+ for (const candidate of candidates) {
9907
+ try {
9908
+ const result = await exec(candidate);
9909
+ if (result.exitCode === 0) {
9910
+ return true;
9911
+ }
9912
+ } catch {
9913
+ }
9914
+ }
9915
+ return false;
9916
+ }
9885
9917
  async function detectPackageManager(context) {
9886
9918
  const { exec } = context;
9887
9919
  try {
9888
9920
  const managers = [
9889
- { name: "apt", test: "which apt-get" },
9890
- { name: "apk", test: "which apk" },
9891
- { name: "dnf", test: "which dnf" },
9892
- { name: "yum", test: "which yum" },
9893
- { name: "pacman", test: "which pacman" },
9894
- { name: "zypper", test: "which zypper" },
9895
- { name: "eopkg", test: "which eopkg" },
9896
- { name: "winget", test: "which winget" },
9897
- { name: "choco", test: "which choco" },
9898
- { name: "brew", test: "which brew" }
9921
+ { name: "apt", binary: "apt-get" },
9922
+ { name: "apk", binary: "apk" },
9923
+ { name: "dnf", binary: "dnf" },
9924
+ { name: "yum", binary: "yum" },
9925
+ { name: "pacman", binary: "pacman" },
9926
+ { name: "zypper", binary: "zypper" },
9927
+ { name: "eopkg", binary: "eopkg" },
9928
+ { name: "winget", binary: "winget" },
9929
+ { name: "choco", binary: "choco" },
9930
+ { name: "brew", binary: "brew" }
9899
9931
  ];
9900
9932
  for (const manager of managers) {
9901
- try {
9902
- const result = await exec(manager.test);
9903
- if (result.exitCode === 0) {
9904
- return PACKAGE_MANAGERS[manager.name];
9905
- }
9906
- } catch {
9933
+ if (await commandExists(exec, manager.binary)) {
9934
+ return PACKAGE_MANAGERS[manager.name];
9907
9935
  }
9908
9936
  }
9909
9937
  } catch (error) {
@@ -11234,23 +11262,48 @@ var docker_exports = {};
11234
11262
  __export(docker_exports, {
11235
11263
  addUsers: () => add_users_default,
11236
11264
  install: () => install_default6,
11237
- installCompose: () => install_compose_default
11265
+ installCompose: () => install_compose_default,
11266
+ runContainer: () => run_container_default,
11267
+ runContainerDetached: () => run_container_detached_default
11238
11268
  });
11239
11269
 
11240
11270
  // src/core/docker/installers/debian.ts
11241
- async function installForDebian(context, _variant, installComposePlugin) {
11242
- const { info, error, run: runTask } = context;
11243
- info("Running Debian/Ubuntu installation workflow...");
11271
+ var LEGACY_PACKAGES = ["docker", "docker-engine", "docker.io", "containerd", "runc"];
11272
+ var KEYRING_PATH = "/etc/apt/keyrings/docker.gpg";
11273
+ function resolveAptDistro(variant) {
11274
+ if (variant?.toLowerCase().includes("ubuntu")) {
11275
+ return "ubuntu";
11276
+ }
11277
+ return "debian";
11278
+ }
11279
+ async function getCodename(exec) {
11280
+ const result = await exec(["bash", "-lc", '. /etc/os-release && echo "$VERSION_CODENAME"']);
11281
+ if (result.exitCode === 0) {
11282
+ return result.stdout.trim();
11283
+ }
11284
+ return void 0;
11285
+ }
11286
+ async function getArchitecture(exec) {
11287
+ const result = await exec(["dpkg", "--print-architecture"]);
11288
+ if (result.exitCode === 0) {
11289
+ return result.stdout.trim();
11290
+ }
11291
+ return void 0;
11292
+ }
11293
+ async function installForDebian(context, variant, installComposePlugin) {
11294
+ const { info, error, run: runTask, exec } = context;
11295
+ info("Running Debian/Ubuntu installation workflow using official Docker instructions...");
11244
11296
  try {
11297
+ await exec(["bash", "-lc", `apt-get remove -y ${LEGACY_PACKAGES.join(" ")} || true`], { sudo: true });
11245
11298
  const updateResult = await runTask(core_default.pkg.update({}));
11246
11299
  if (!updateResult?.success) {
11247
- const message = `Failed to update package list: ${updateResult?.error ?? "Unknown error"}`;
11300
+ const message = `Failed to update package list before prerequisites: ${updateResult?.error ?? "Unknown error"}`;
11248
11301
  error(message);
11249
11302
  return { success: false, error: message };
11250
11303
  }
11251
11304
  const prereqResult = await runTask(
11252
11305
  core_default.pkg.install({
11253
- package: ["apt-transport-https", "ca-certificates", "curl", "gnupg", "lsb-release"]
11306
+ package: ["ca-certificates", "curl", "gnupg"]
11254
11307
  })
11255
11308
  );
11256
11309
  if (!prereqResult?.success) {
@@ -11258,10 +11311,12 @@ async function installForDebian(context, _variant, installComposePlugin) {
11258
11311
  error(message);
11259
11312
  return { success: false, error: message };
11260
11313
  }
11314
+ await exec(["install", "-m", "0755", "-d", "/etc/apt/keyrings"], { sudo: true });
11315
+ const distro = resolveAptDistro(variant);
11261
11316
  const gpgResult = await runTask(
11262
11317
  core_default.apt.add_key({
11263
- url: "https://download.docker.com/linux/ubuntu/gpg",
11264
- keyring: "/usr/share/keyrings/docker-archive-keyring.gpg"
11318
+ url: `https://download.docker.com/linux/${distro}/gpg`,
11319
+ keyring: KEYRING_PATH
11265
11320
  })
11266
11321
  );
11267
11322
  if (!gpgResult?.success) {
@@ -11269,9 +11324,23 @@ async function installForDebian(context, _variant, installComposePlugin) {
11269
11324
  error(message);
11270
11325
  return { success: false, error: message };
11271
11326
  }
11327
+ await exec(["chmod", "a+r", KEYRING_PATH], { sudo: true });
11328
+ const architecture = await getArchitecture(exec);
11329
+ if (!architecture) {
11330
+ const message = "Unable to determine system architecture via dpkg.";
11331
+ error(message);
11332
+ return { success: false, error: message };
11333
+ }
11334
+ const codename = await getCodename(exec);
11335
+ if (!codename) {
11336
+ const message = "Unable to determine OS codename for Docker repository.";
11337
+ error(message);
11338
+ return { success: false, error: message };
11339
+ }
11340
+ const repoLine = `deb [arch=${architecture} signed-by=${KEYRING_PATH}] https://download.docker.com/linux/${distro} ${codename} stable`;
11272
11341
  const repoResult = await runTask(
11273
11342
  core_default.apt.add_repository({
11274
- repo: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu jammy stable",
11343
+ repo: repoLine,
11275
11344
  name: "docker"
11276
11345
  })
11277
11346
  );
@@ -11280,26 +11349,36 @@ async function installForDebian(context, _variant, installComposePlugin) {
11280
11349
  error(message);
11281
11350
  return { success: false, error: message };
11282
11351
  }
11283
- const dockerResult = await runTask(
11284
- core_default.pkg.install({
11285
- package: ["docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin"]
11286
- })
11287
- );
11352
+ const refreshResult = await runTask(core_default.pkg.update({}));
11353
+ if (!refreshResult?.success) {
11354
+ const message = `Failed to refresh package cache after adding Docker repository: ${refreshResult?.error ?? "Unknown error"}`;
11355
+ error(message);
11356
+ return { success: false, error: message };
11357
+ }
11358
+ const packages = ["docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin"];
11359
+ if (installComposePlugin) {
11360
+ packages.push("docker-compose-plugin");
11361
+ }
11362
+ const dockerResult = await runTask(core_default.pkg.install({ package: packages }));
11288
11363
  if (!dockerResult?.success) {
11289
11364
  const message = `Failed to install Docker Engine: ${dockerResult?.error ?? "Unknown error"}`;
11290
11365
  error(message);
11291
11366
  return { success: false, error: message };
11292
11367
  }
11293
- if (installComposePlugin) {
11294
- const composeResult = await runTask(core_default.pkg.install({ package: "docker-compose-plugin" }));
11295
- if (!composeResult?.success) {
11296
- const message = `Failed to install Docker Compose plugin: ${composeResult?.error ?? "Unknown error"}`;
11297
- error(message);
11298
- return { success: false, error: message };
11299
- }
11368
+ await exec(["systemctl", "daemon-reload"], { sudo: true }).catch(() => {
11369
+ });
11370
+ const enableResult = await runTask(core_default.systemd.enable({ service: "docker", sudo: true }));
11371
+ if (!enableResult?.success) {
11372
+ const message = `Failed to enable docker service: ${enableResult?.error ?? "Unknown error"}`;
11373
+ error(message);
11374
+ return { success: false, error: message };
11375
+ }
11376
+ const startResult = await runTask(core_default.systemd.start({ service: "docker", sudo: true }));
11377
+ if (!startResult?.success) {
11378
+ const message = `Failed to start docker service: ${startResult?.error ?? "Unknown error"}`;
11379
+ error(message);
11380
+ return { success: false, error: message };
11300
11381
  }
11301
- await runTask(core_default.systemd.enable({ service: "docker" }));
11302
- await runTask(core_default.systemd.start({ service: "docker" }));
11303
11382
  return { success: true };
11304
11383
  } catch (e) {
11305
11384
  const message = `An unexpected error occurred: ${e instanceof Error ? e.message : String(e)}`;
@@ -11308,64 +11387,386 @@ async function installForDebian(context, _variant, installComposePlugin) {
11308
11387
  }
11309
11388
  }
11310
11389
 
11390
+ // src/core/docker/installers/kernel-prereqs.ts
11391
+ var DEFAULT_MODULES = [
11392
+ "overlay",
11393
+ "br_netfilter",
11394
+ "bridge",
11395
+ "veth",
11396
+ "ip_tables",
11397
+ "iptable_filter",
11398
+ "iptable_mangle",
11399
+ "iptable_raw",
11400
+ "iptable_nat",
11401
+ "ip6table_filter",
11402
+ "ip6table_mangle",
11403
+ "ip6table_raw",
11404
+ "ip6table_nat",
11405
+ "nf_tables",
11406
+ "nft_chain_nat",
11407
+ "nfnetlink",
11408
+ "nf_nat",
11409
+ "nf_nat_ipv4",
11410
+ "nf_nat_ipv6",
11411
+ "nf_conntrack",
11412
+ "nf_conntrack_ipv4",
11413
+ "nf_conntrack_ipv6",
11414
+ "xt_conntrack",
11415
+ "xt_addrtype",
11416
+ "xt_comment",
11417
+ "xt_mark",
11418
+ "xt_nat",
11419
+ "xt_MASQUERADE"
11420
+ ];
11421
+ var DEFAULT_SYSCTL = {
11422
+ "net.bridge.bridge-nf-call-iptables": "1",
11423
+ "net.bridge.bridge-nf-call-ip6tables": "1",
11424
+ "net.bridge.bridge-nf-call-arptables": "1",
11425
+ "net.ipv4.ip_forward": "1"
11426
+ };
11427
+ var DEFAULT_MODULES_FILE = "/etc/modules-load.d/hostctl-docker.conf";
11428
+ var DEFAULT_SYSCTL_FILE = "/etc/sysctl.d/99-hostctl-docker.conf";
11429
+ async function ensureDockerKernelPrereqs(context, options = {}) {
11430
+ const modules = options.modules ?? DEFAULT_MODULES;
11431
+ const sysctlEntries = options.sysctl ?? DEFAULT_SYSCTL;
11432
+ const modulesFile = options.modulesFile ?? DEFAULT_MODULES_FILE;
11433
+ const sysctlFile = options.sysctlFile ?? DEFAULT_SYSCTL_FILE;
11434
+ const { debug, info } = context;
11435
+ const failedModules = [];
11436
+ const failedSysctls = [];
11437
+ if (modules.length) {
11438
+ const uniqueModules = Array.from(new Set(modules.filter((name) => typeof name === "string" && name.length > 0)));
11439
+ const moduleContent = `${uniqueModules.join("\n")}
11440
+ `;
11441
+ const moduleScript = [`cat <<'EOF' > ${modulesFile}`, moduleContent, "EOF"].join("\n");
11442
+ await context.exec(["bash", "-lc", moduleScript], { sudo: true }).catch(() => {
11443
+ });
11444
+ for (const moduleName of uniqueModules) {
11445
+ try {
11446
+ const result = await context.exec(["modprobe", moduleName], { sudo: true });
11447
+ if (result.exitCode !== 0) {
11448
+ failedModules.push(moduleName);
11449
+ debug?.(
11450
+ `modprobe ${moduleName} exited with ${result.exitCode}: ${result.stderr || result.stdout || "no output"}`
11451
+ );
11452
+ }
11453
+ } catch (error) {
11454
+ failedModules.push(moduleName);
11455
+ debug?.(`Failed to modprobe ${moduleName}: ${error.message}`);
11456
+ }
11457
+ }
11458
+ }
11459
+ const sysctlKeys = Object.keys(sysctlEntries);
11460
+ if (sysctlKeys.length) {
11461
+ const sysctlContent = `${sysctlKeys.map((key) => `${key} = ${sysctlEntries[key]}`).join("\n")}
11462
+ `;
11463
+ const sysctlScript = [`cat <<'EOF' > ${sysctlFile}`, sysctlContent, "EOF"].join("\n");
11464
+ await context.exec(["bash", "-lc", sysctlScript], { sudo: true }).catch(() => {
11465
+ });
11466
+ for (const [key, value] of Object.entries(sysctlEntries)) {
11467
+ try {
11468
+ const result = await context.exec(["sysctl", "-w", `${key}=${value}`], { sudo: true });
11469
+ if (result.exitCode !== 0) {
11470
+ failedSysctls.push(key);
11471
+ debug?.(`sysctl write ${key} failed with ${result.exitCode}: ${result.stderr || result.stdout || "no output"}`);
11472
+ }
11473
+ } catch (error) {
11474
+ failedSysctls.push(key);
11475
+ debug?.(`Failed to write sysctl ${key}: ${error.message}`);
11476
+ }
11477
+ }
11478
+ }
11479
+ if (failedModules.length) {
11480
+ info?.(
11481
+ `Unable to load kernel modules required by Docker: ${failedModules.join(
11482
+ ", "
11483
+ )}. Containers may fail to start if the hypervisor kernel omits these modules.`
11484
+ );
11485
+ }
11486
+ if (failedSysctls.length) {
11487
+ info?.(
11488
+ `Failed to apply Docker networking sysctl keys: ${failedSysctls.join(
11489
+ ", "
11490
+ )}. Check kernel support for these parameters.`
11491
+ );
11492
+ }
11493
+ }
11494
+ async function ensureNftNatTables(context) {
11495
+ const { info } = context;
11496
+ const script = `
11497
+ set -e
11498
+ if ! command -v nft >/dev/null 2>&1; then
11499
+ exit 0
11500
+ fi
11501
+ ensure_table() {
11502
+ local family="$1"
11503
+ if nft list table "$family" nat >/dev/null 2>&1; then
11504
+ return 0
11505
+ fi
11506
+ nft add table "$family" nat >/dev/null 2>&1 || true
11507
+ }
11508
+ ensure_chain() {
11509
+ local family="$1"
11510
+ local chain="$2"
11511
+ local hook="$3"
11512
+ local priority="$4"
11513
+ if nft list chain "$family" nat "$chain" >/dev/null 2>&1; then
11514
+ return 0
11515
+ fi
11516
+ nft add chain "$family" nat "$chain" "{ type nat hook $hook priority $priority; policy accept; }" >/dev/null 2>&1 || true
11517
+ }
11518
+ for family in ip ip6; do
11519
+ ensure_table "$family"
11520
+ ensure_chain "$family" PREROUTING prerouting dstnat
11521
+ ensure_chain "$family" INPUT input dstnat
11522
+ ensure_chain "$family" OUTPUT output dstnat
11523
+ ensure_chain "$family" POSTROUTING postrouting srcnat
11524
+ done
11525
+ `.trim();
11526
+ const result = await context.exec(["bash", "-lc", script], { sudo: true }).catch((error) => {
11527
+ info?.(`Failed to ensure nftables nat tables: ${error.message}`);
11528
+ return void 0;
11529
+ });
11530
+ if (result?.exitCode === 0) {
11531
+ info?.("Ensured nftables nat tables/chains with nat priorities exist for ip and ip6 families.");
11532
+ }
11533
+ }
11534
+
11311
11535
  // src/core/docker/installers/fedora.ts
11312
- async function installForFedora(context, installComposePlugin) {
11313
- const { info, error, run: runTask } = context;
11314
- info("Running Fedora/RHEL/CentOS installation workflow...");
11536
+ var LEGACY_PACKAGES2 = [
11537
+ "docker",
11538
+ "docker-client",
11539
+ "docker-client-latest",
11540
+ "docker-common",
11541
+ "docker-latest",
11542
+ "docker-latest-logrotate",
11543
+ "docker-logrotate",
11544
+ "docker-engine",
11545
+ "podman-docker"
11546
+ ];
11547
+ function resolveRepoBase(variant) {
11548
+ const normalized = variant?.toLowerCase() ?? "";
11549
+ if (normalized.includes("fedora")) {
11550
+ return "fedora";
11551
+ }
11552
+ if (normalized.includes("rhel")) {
11553
+ return "rhel";
11554
+ }
11555
+ return "centos";
11556
+ }
11557
+ async function hasCommand(exec, binary) {
11558
+ const result = await exec(["bash", "-lc", `command -v ${binary}`]);
11559
+ return result.exitCode === 0;
11560
+ }
11561
+ async function detectPackageManager2(exec) {
11562
+ if (await hasCommand(exec, "dnf")) {
11563
+ return "dnf";
11564
+ }
11565
+ return "yum";
11566
+ }
11567
+ function repoFallbackContent(repoBase) {
11568
+ return `[docker-ce-stable]
11569
+ name=Docker CE Stable - $basearch
11570
+ baseurl=https://download.docker.com/linux/${repoBase}/$releasever/$basearch/stable
11571
+ enabled=1
11572
+ gpgcheck=1
11573
+ gpgkey=https://download.docker.com/linux/${repoBase}/gpg`;
11574
+ }
11575
+ async function refreshPackageMetadata(exec, manager) {
11576
+ const command = manager === "dnf" ? ["dnf", "-y", "makecache", "--refresh", "--quiet"] : ["yum", "-y", "makecache", "--quiet"];
11577
+ const result = await exec(command, { sudo: true });
11578
+ if (result.exitCode === 0) {
11579
+ return { success: true };
11580
+ }
11581
+ const failure = result.stderr?.trim() || result.stdout?.trim() || `exit ${result.exitCode}`;
11582
+ return { success: false, error: failure };
11583
+ }
11584
+ async function installKernelModulePackages(context, manager) {
11585
+ const { exec, info } = context;
11315
11586
  try {
11316
- const updateResult = await runTask(core_default.pkg.update({}));
11317
- if (!updateResult?.success) {
11318
- const message = `Failed to update package list: ${updateResult?.error ?? "Unknown error"}`;
11319
- error(message);
11320
- return { success: false, error: message };
11587
+ const kernelResult = await exec(["uname", "-r"]);
11588
+ const release = kernelResult.stdout.trim();
11589
+ if (!release) {
11590
+ return;
11321
11591
  }
11322
- const prereqResult = await runTask(
11592
+ const packages = [`kernel-modules-${release}`, `kernel-modules-extra-${release}`];
11593
+ const installCommand = manager === "dnf" ? `dnf install -y --skip-broken --setopt=install_weak_deps=0 ${packages.join(" ")}` : `yum install -y ${packages.join(" ")}`;
11594
+ const result = await exec(["bash", "-lc", installCommand], { sudo: true });
11595
+ if (result.exitCode === 0) {
11596
+ info?.(`Ensured kernel module packages for ${release} are installed.`);
11597
+ } else {
11598
+ info?.(
11599
+ `Failed to install kernel module packages (${packages.join(
11600
+ ", "
11601
+ )}) for ${release}: ${result.stderr || result.stdout || `exit ${result.exitCode}`}`
11602
+ );
11603
+ }
11604
+ } catch (error) {
11605
+ info?.(`Unable to install kernel module packages: ${error.message}`);
11606
+ }
11607
+ }
11608
+ async function ensureIptablesBackend(context, runTask, manager, backend) {
11609
+ const { info } = context;
11610
+ if (backend === "legacy") {
11611
+ const legacyResult = await runTask(
11323
11612
  core_default.pkg.install({
11324
- package: ["yum-utils", "device-mapper-persistent-data", "lvm2"]
11613
+ package: ["iptables-legacy"],
11614
+ packageManager: manager
11325
11615
  })
11326
11616
  );
11617
+ if (!legacyResult?.success) {
11618
+ info?.(
11619
+ "iptables-legacy package could not be installed (may not exist for this distro); attempting to switch existing binaries."
11620
+ );
11621
+ }
11622
+ }
11623
+ const suffix = backend === "legacy" ? "legacy" : "nft";
11624
+ const script = `
11625
+ set +e
11626
+ switch_backend() {
11627
+ local tool="$1"
11628
+ local suffix="$2"
11629
+ local target=""
11630
+ for candidate in /usr/sbin/\${tool}-\${suffix} /usr/bin/\${tool}-\${suffix}; do
11631
+ if [ -x "$candidate" ]; then
11632
+ target="$candidate"
11633
+ break
11634
+ fi
11635
+ done
11636
+ if [ -z "$target" ]; then
11637
+ return 1
11638
+ fi
11639
+ if command -v alternatives >/dev/null 2>&1; then
11640
+ alternatives --set "$tool" "$target" >/dev/null 2>&1 || true
11641
+ fi
11642
+ if command -v update-alternatives >/dev/null 2>&1; then
11643
+ update-alternatives --set "$tool" "$target" >/dev/null 2>&1 || true
11644
+ fi
11645
+ ln -sf "$target" "/usr/sbin/$tool" 2>/dev/null || true
11646
+ ln -sf "$target" "/usr/bin/$tool" 2>/dev/null || true
11647
+ return 0
11648
+ }
11649
+ status=0
11650
+ for tool in iptables ip6tables ebtables arptables; do
11651
+ if ! switch_backend "$tool" "${suffix}"; then
11652
+ status=1
11653
+ fi
11654
+ done
11655
+ exit $status
11656
+ `.trim();
11657
+ const switchResult = await context.exec(["bash", "-lc", script], { sudo: true });
11658
+ if (switchResult.exitCode !== 0) {
11659
+ info?.(`Failed to switch iptables utilities to the ${backend} backend (exit ${switchResult.exitCode}).`);
11660
+ return false;
11661
+ }
11662
+ try {
11663
+ const version2 = await context.exec(["iptables", "--version"], { sudo: true });
11664
+ const output = version2.stdout.trim();
11665
+ const expected = backend === "legacy" ? "(legacy)" : "(nf_tables)";
11666
+ const matches2 = output.includes(expected);
11667
+ info?.(`iptables now reports: ${output}`);
11668
+ return matches2;
11669
+ } catch (error) {
11670
+ info?.(`Unable to verify iptables backend: ${error.message}`);
11671
+ return false;
11672
+ }
11673
+ }
11674
+ async function installForFedora(context, variant, installComposePlugin) {
11675
+ const { info, error, run: runTask, exec } = context;
11676
+ info("Running Fedora/RHEL/CentOS installation workflow using official Docker instructions...");
11677
+ try {
11678
+ const manager = await detectPackageManager2(exec);
11679
+ const repoBase = resolveRepoBase(variant);
11680
+ const repoUrl = `https://download.docker.com/linux/${repoBase}/docker-ce.repo`;
11681
+ info(`Removing legacy/conflicting Docker packages via ${manager}...`);
11682
+ await exec(["bash", "-lc", `${manager} remove -y ${LEGACY_PACKAGES2.join(" ")} || true`], { sudo: true });
11683
+ info("Refreshing package metadata before installing prerequisites...");
11684
+ const metadataResult = await refreshPackageMetadata(exec, manager);
11685
+ if (!metadataResult.success) {
11686
+ const message = `Failed to refresh package metadata before prerequisites: ${metadataResult.error ?? "Unknown error"}`;
11687
+ error(message);
11688
+ return { success: false, error: message };
11689
+ }
11690
+ const pluginPackage = manager === "dnf" ? "dnf-plugins-core" : "yum-utils";
11691
+ const prereqPackages = [pluginPackage, "device-mapper-persistent-data", "lvm2", "iproute", "iptables"];
11692
+ if (repoBase !== "fedora") {
11693
+ prereqPackages.push("kernel-modules");
11694
+ prereqPackages.push("kernel-modules-extra");
11695
+ }
11696
+ info(`Installing prerequisite packages: ${prereqPackages.join(", ")}...`);
11697
+ const prereqResult = await runTask(core_default.pkg.install({ package: prereqPackages }));
11327
11698
  if (!prereqResult?.success) {
11328
- const message = `Failed to install prerequisites: ${prereqResult?.error ?? "Unknown error"}`;
11699
+ const message = `Failed to install prerequisite packages: ${prereqResult?.error ?? "Unknown error"}`;
11329
11700
  error(message);
11330
11701
  return { success: false, error: message };
11331
11702
  }
11332
- const repoContent = `[docker-ce-stable]
11333
- name=Docker CE Stable - $basearch
11334
- baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable
11335
- enabled=1
11336
- gpgcheck=1
11337
- gpgkey=https://download.docker.com/linux/centos/gpg`;
11338
- const repoResult = await runTask(
11339
- core_default.yum.add_repository({
11340
- content: repoContent,
11341
- name: "docker-ce"
11342
- })
11343
- );
11344
- if (!repoResult?.success) {
11345
- const message = `Failed to add Docker repository: ${repoResult?.error ?? "Unknown error"}`;
11703
+ let repoAdded = false;
11704
+ if (manager === "dnf") {
11705
+ info("Adding Docker CE repository via dnf config-manager...");
11706
+ const addResult = await exec(["dnf", "config-manager", "--add-repo", repoUrl], { sudo: true });
11707
+ repoAdded = addResult.exitCode === 0;
11708
+ } else {
11709
+ info("Adding Docker CE repository via yum-config-manager...");
11710
+ const addResult = await exec(["yum-config-manager", "--add-repo", repoUrl], { sudo: true });
11711
+ repoAdded = addResult.exitCode === 0;
11712
+ }
11713
+ if (!repoAdded) {
11714
+ info("Falling back to manual Docker repo file...");
11715
+ const repoResult = await runTask(
11716
+ core_default.yum.add_repository({
11717
+ content: repoFallbackContent(repoBase),
11718
+ name: "docker-ce"
11719
+ })
11720
+ );
11721
+ if (!repoResult?.success) {
11722
+ const message = `Failed to add Docker repository: ${repoResult?.error ?? "Unknown error"}`;
11723
+ error(message);
11724
+ return { success: false, error: message };
11725
+ }
11726
+ }
11727
+ info("Refreshing package metadata after adding Docker repository...");
11728
+ const refreshResult = await refreshPackageMetadata(exec, manager);
11729
+ if (!refreshResult.success) {
11730
+ const message = `Failed to refresh package metadata after adding Docker repository: ${refreshResult.error ?? "Unknown error"}`;
11346
11731
  error(message);
11347
11732
  return { success: false, error: message };
11348
11733
  }
11349
- const dockerResult = await runTask(
11350
- core_default.pkg.install({
11351
- package: ["docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin"]
11352
- })
11353
- );
11734
+ const packages = ["docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin"];
11735
+ if (installComposePlugin) {
11736
+ packages.push("docker-compose-plugin");
11737
+ }
11738
+ info(`Installing Docker Engine packages: ${packages.join(", ")}...`);
11739
+ const dockerResult = await runTask(core_default.pkg.install({ package: packages }));
11354
11740
  if (!dockerResult?.success) {
11355
- const message = `Failed to install Docker Engine: ${dockerResult?.error ?? "Unknown error"}`;
11741
+ const message = `Failed to install Docker Engine packages: ${dockerResult?.error ?? "Unknown error"}`;
11356
11742
  error(message);
11357
11743
  return { success: false, error: message };
11358
11744
  }
11359
- if (installComposePlugin) {
11360
- const composeResult = await runTask(core_default.pkg.install({ package: "docker-compose-plugin" }));
11361
- if (!composeResult?.success) {
11362
- const message = `Failed to install Docker Compose plugin: ${composeResult?.error ?? "Unknown error"}`;
11363
- error(message);
11364
- return { success: false, error: message };
11365
- }
11745
+ info("Configuring kernel modules and sysctl prerequisites for Docker networking...");
11746
+ await installKernelModulePackages(context, manager);
11747
+ await ensureDockerKernelPrereqs(context);
11748
+ info("Ensuring iptables utilities use the legacy backend...");
11749
+ const legacySelected = await ensureIptablesBackend(context, runTask, manager, "legacy");
11750
+ if (!legacySelected) {
11751
+ info("Continuing with nftables backend for iptables; ensuring nft nat tables exist.");
11752
+ await ensureNftNatTables(context);
11753
+ }
11754
+ await exec(["systemctl", "daemon-reload"], { sudo: true }).catch(() => {
11755
+ });
11756
+ info("Enabling docker service...");
11757
+ const enableResult = await runTask(core_default.systemd.enable({ service: "docker", sudo: true }));
11758
+ if (!enableResult?.success) {
11759
+ const message = `Failed to enable docker service: ${enableResult?.error ?? "Unknown error"}`;
11760
+ error(message);
11761
+ return { success: false, error: message };
11762
+ }
11763
+ info("Starting docker service...");
11764
+ const startResult = await runTask(core_default.systemd.start({ service: "docker", sudo: true }));
11765
+ if (!startResult?.success) {
11766
+ const message = `Failed to start docker service: ${startResult?.error ?? "Unknown error"}`;
11767
+ error(message);
11768
+ return { success: false, error: message };
11366
11769
  }
11367
- await runTask(core_default.systemd.enable({ service: "docker" }));
11368
- await runTask(core_default.systemd.start({ service: "docker" }));
11369
11770
  return { success: true };
11370
11771
  } catch (e) {
11371
11772
  const message = `An unexpected error occurred: ${e instanceof Error ? e.message : String(e)}`;
@@ -11474,20 +11875,37 @@ async function run91(context) {
11474
11875
  return { success: false, error: message };
11475
11876
  }
11476
11877
  const { os: os5, variant } = osDetails;
11878
+ const normalizedOs = (os5 ?? "").toLowerCase();
11879
+ const normalizedVariant = (variant ?? "").toLowerCase();
11477
11880
  info(`Detected OS: ${os5} (${variant})`);
11478
11881
  let engineInstallResult;
11479
- if (/debian|ubuntu/i.test(os5)) {
11882
+ if (/debian|ubuntu/.test(normalizedOs) || /debian|ubuntu/.test(normalizedVariant)) {
11480
11883
  engineInstallResult = await installForDebian(context, variant, installComposePlugin);
11481
- } else if (/fedora|rhel|centos/i.test(os5)) {
11482
- engineInstallResult = await installForFedora(context, installComposePlugin);
11884
+ } else if (/fedora|rhel|centos|rocky|alma|almalinux|ol|oracle/.test(`${normalizedOs} ${normalizedVariant}`)) {
11885
+ engineInstallResult = await installForFedora(context, variant, installComposePlugin);
11483
11886
  } else {
11484
11887
  const message = `Unsupported OS: ${os5}`;
11485
11888
  logError2(message);
11486
11889
  return { success: false, error: message };
11487
11890
  }
11488
11891
  if (!engineInstallResult?.success) {
11892
+ if (engineInstallResult?.error && /docker service/i.test(engineInstallResult.error)) {
11893
+ const diag = await collectDockerServiceDiagnostics(context);
11894
+ if (diag) {
11895
+ return {
11896
+ success: false,
11897
+ error: `${engineInstallResult.error}
11898
+ ${diag}`
11899
+ };
11900
+ }
11901
+ }
11489
11902
  return engineInstallResult ?? { success: false, error: "Failed to install Docker Engine" };
11490
11903
  }
11904
+ const daemonResult = await waitForDockerDaemon(context);
11905
+ if (!daemonResult.success) {
11906
+ logError2(daemonResult.error ?? "Docker daemon did not become ready.");
11907
+ return daemonResult;
11908
+ }
11491
11909
  info("Docker Engine installation successful.");
11492
11910
  if (installComposeStandalone) {
11493
11911
  info("Installing Docker Compose standalone binary...");
@@ -11513,10 +11931,392 @@ async function run91(context) {
11513
11931
  info("Docker installation workflow completed successfully.");
11514
11932
  return { success: true };
11515
11933
  }
11934
+ async function waitForDockerDaemon(context, { timeoutMs = 9e4, delayMs = 5e3 } = {}) {
11935
+ const { info, debug } = context;
11936
+ const start = Date.now();
11937
+ let attempt = 0;
11938
+ let activeSince;
11939
+ let stableIterations = 0;
11940
+ let lastInfoError;
11941
+ let lastSocketError;
11942
+ let lastServiceState;
11943
+ while (Date.now() - start < timeoutMs) {
11944
+ attempt += 1;
11945
+ let serviceActive = false;
11946
+ try {
11947
+ const status = await context.exec(["systemctl", "is-active", "docker"], { sudo: true });
11948
+ const rawState = status.stdout.trim() || status.stderr.trim();
11949
+ const normalizedState = sanitizeSystemctlState(rawState);
11950
+ lastServiceState = normalizedState || rawState || `exit ${status.exitCode}`;
11951
+ debug(`docker systemctl status attempt ${attempt}: ${lastServiceState}`);
11952
+ serviceActive = status.exitCode === 0 && normalizedState.startsWith("active");
11953
+ } catch (error) {
11954
+ debug(`Error checking docker daemon (attempt ${attempt}): ${error.message}`);
11955
+ }
11956
+ if (serviceActive) {
11957
+ if (!activeSince) {
11958
+ activeSince = Date.now();
11959
+ }
11960
+ const infoProbe = await dockerInfoAvailable(context);
11961
+ if (infoProbe.success) {
11962
+ info("Docker daemon is running.");
11963
+ return { success: true };
11964
+ }
11965
+ lastInfoError = infoProbe.error;
11966
+ const socketProbe = await dockerSocketAvailable(context);
11967
+ debug(`docker socket ready: ${socketProbe.success}`);
11968
+ if (socketProbe.success) {
11969
+ info("Docker daemon is running.");
11970
+ return { success: true };
11971
+ }
11972
+ lastSocketError = socketProbe.error;
11973
+ const socketUnitActive = await systemdSocketActive(context);
11974
+ if (socketUnitActive) {
11975
+ info("Docker socket unit is active and docker service is running.");
11976
+ return { success: true };
11977
+ }
11978
+ stableIterations += 1;
11979
+ if (activeSince && Date.now() - activeSince > 3e4 && stableIterations >= 3) {
11980
+ info("Docker service has been active for 30s without passing readiness probes; continuing anyway.");
11981
+ return { success: true };
11982
+ }
11983
+ } else {
11984
+ activeSince = void 0;
11985
+ stableIterations = 0;
11986
+ }
11987
+ await sleep(delayMs);
11988
+ }
11989
+ const details = await collectDockerServiceDiagnostics(context);
11990
+ const probeDetails = [lastInfoError, lastSocketError].filter(Boolean).join(" | ");
11991
+ const stateDetail = lastServiceState ? ` Last known systemctl state: ${lastServiceState}.` : "";
11992
+ return {
11993
+ success: false,
11994
+ error: `Docker daemon did not become ready before timeout.${probeDetails ? ` Last errors: ${probeDetails}.` : ""}${stateDetail}${details ? `
11995
+ ${details}` : ""}`
11996
+ };
11997
+ }
11998
+ async function dockerSocketAvailable(context) {
11999
+ const { debug } = context;
12000
+ const socketPaths = ["/run/docker.sock", "/var/run/docker.sock"];
12001
+ for (const socketPath of socketPaths) {
12002
+ try {
12003
+ const result = await context.exec(["test", "-S", socketPath], { sudo: true });
12004
+ if (result.exitCode === 0) {
12005
+ return { success: true };
12006
+ }
12007
+ const stderr = result.stderr?.trim() || result.stdout?.trim();
12008
+ if (stderr) {
12009
+ debug(`docker socket ${socketPath} not ready (exit ${result.exitCode}): ${stderr}`);
12010
+ }
12011
+ } catch (error) {
12012
+ debug(`error checking docker socket ${socketPath}: ${error.message}`);
12013
+ }
12014
+ }
12015
+ return { success: false, error: "unix socket not present" };
12016
+ }
12017
+ async function dockerInfoAvailable(context) {
12018
+ const { debug } = context;
12019
+ try {
12020
+ const infoResult = await context.exec(["docker", "info"], { sudo: true });
12021
+ if (infoResult.exitCode === 0) {
12022
+ return { success: true };
12023
+ }
12024
+ const message = infoResult.stderr?.trim() || infoResult.stdout?.trim();
12025
+ if (message) {
12026
+ debug(`docker info failed with exit ${infoResult.exitCode}: ${message}`);
12027
+ return { success: false, error: message };
12028
+ }
12029
+ debug(`docker info failed with exit ${infoResult.exitCode}.`);
12030
+ return { success: false, error: `exit ${infoResult.exitCode}` };
12031
+ } catch (error) {
12032
+ const message = error.message;
12033
+ debug(`docker info threw: ${message}`);
12034
+ return { success: false, error: message };
12035
+ }
12036
+ }
12037
+ async function systemdSocketActive(context) {
12038
+ try {
12039
+ const socketStatus = await context.exec(["systemctl", "is-active", "docker.socket"], { sudo: true });
12040
+ return socketStatus.exitCode === 0 && socketStatus.stdout.trim() === "active";
12041
+ } catch {
12042
+ return false;
12043
+ }
12044
+ }
12045
+ async function sleep(ms) {
12046
+ await new Promise((resolve) => setTimeout(resolve, ms));
12047
+ }
12048
+ async function collectDockerServiceDiagnostics(context) {
12049
+ const logs = [];
12050
+ try {
12051
+ const status = await context.exec(["systemctl", "status", "docker", "--no-pager"], { sudo: true });
12052
+ const text = status.stdout || status.stderr;
12053
+ if (text?.trim()) {
12054
+ logs.push("systemctl status docker:\n" + text.trim());
12055
+ }
12056
+ } catch {
12057
+ }
12058
+ try {
12059
+ const journal = await context.exec(["journalctl", "-xeu", "docker.service", "--no-pager", "-n", "50"], {
12060
+ sudo: true
12061
+ });
12062
+ const text = journal.stdout || journal.stderr;
12063
+ if (text?.trim()) {
12064
+ logs.push("journalctl -xeu docker.service:\n" + text.trim());
12065
+ }
12066
+ } catch {
12067
+ }
12068
+ await appendDiagnosticsCommand(context, logs, "iptables --version", ["iptables", "--version"]);
12069
+ await appendDiagnosticsCommand(context, logs, "iptables -t nat -S", ["iptables", "-t", "nat", "-S"]);
12070
+ await appendDiagnosticsCommand(context, logs, "nft list table ip nat", ["nft", "list", "table", "ip", "nat"]);
12071
+ await appendDiagnosticsCommand(context, logs, "nft list table ip6 nat", ["nft", "list", "table", "ip6", "nat"]);
12072
+ await appendDiagnosticsCommand(
12073
+ context,
12074
+ logs,
12075
+ "Loaded Docker networking modules",
12076
+ [
12077
+ "bash",
12078
+ "-lc",
12079
+ "lsmod | egrep 'overlay|br_netfilter|bridge|ip_tables|iptable_nat|nf_tables|xt_addrtype|xt_nat' || true"
12080
+ ]
12081
+ );
12082
+ await appendDiagnosticsCommand(
12083
+ context,
12084
+ logs,
12085
+ "Docker networking sysctls",
12086
+ [
12087
+ "bash",
12088
+ "-lc",
12089
+ "sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward 2>/dev/null"
12090
+ ]
12091
+ );
12092
+ if (logs.length === 0) {
12093
+ return void 0;
12094
+ }
12095
+ return logs.join("\n\n");
12096
+ }
12097
+ async function appendDiagnosticsCommand(context, logs, label, command) {
12098
+ try {
12099
+ const result = await context.exec(command, { sudo: true });
12100
+ const text = result.stdout || result.stderr;
12101
+ if (text?.trim()) {
12102
+ logs.push(`${label}:
12103
+ ${text.trim()}`);
12104
+ } else {
12105
+ logs.push(`${label}: (no output, exit ${result.exitCode})`);
12106
+ }
12107
+ } catch (error) {
12108
+ logs.push(`${label} (failed): ${error.message}`);
12109
+ }
12110
+ }
12111
+ function sanitizeSystemctlState(value) {
12112
+ if (!value) {
12113
+ return "";
12114
+ }
12115
+ return value.replace(/\u001b\][^\u001b]*\u001b\\/g, "").replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "").trim().toLowerCase();
12116
+ }
11516
12117
  var install_default6 = task(run91, {
11517
12118
  description: "Installs and configures Docker, Docker Compose, and group membership."
11518
12119
  });
11519
12120
 
12121
+ // src/core/docker/run-container.ts
12122
+ import crypto2 from "crypto";
12123
+
12124
+ // src/core/docker/run-helpers.ts
12125
+ import Shellwords2 from "shellwords-ts";
12126
+ function buildDockerRunCommand(params, options) {
12127
+ if (!params.image) {
12128
+ throw new Error("Docker image is required.");
12129
+ }
12130
+ const args = ["docker", "run"];
12131
+ if (options.detach) {
12132
+ args.push("-d");
12133
+ } else {
12134
+ if (options.remove !== false) {
12135
+ args.push("--rm");
12136
+ }
12137
+ }
12138
+ args.push("--cidfile", options.cidFilePath);
12139
+ if (params.pull) {
12140
+ args.push("--pull", params.pull);
12141
+ }
12142
+ if (params.name) {
12143
+ args.push("--name", params.name);
12144
+ }
12145
+ if (params.privileged) {
12146
+ args.push("--privileged");
12147
+ }
12148
+ if (params.user) {
12149
+ args.push("-u", params.user);
12150
+ }
12151
+ if (params.workdir) {
12152
+ args.push("-w", params.workdir);
12153
+ }
12154
+ if (params.entrypoint) {
12155
+ args.push("--entrypoint", params.entrypoint);
12156
+ }
12157
+ if (params.network) {
12158
+ args.push("--network", params.network);
12159
+ }
12160
+ if (params.restart) {
12161
+ args.push("--restart", params.restart);
12162
+ }
12163
+ if (params.gpus) {
12164
+ args.push("--gpus", params.gpus);
12165
+ }
12166
+ if (params.env) {
12167
+ for (const [key, value] of Object.entries(params.env)) {
12168
+ args.push("-e", `${key}=${value}`);
12169
+ }
12170
+ }
12171
+ if (params.volumes) {
12172
+ for (const volume of params.volumes) {
12173
+ args.push("-v", volume);
12174
+ }
12175
+ }
12176
+ if (params.ports) {
12177
+ for (const port of params.ports) {
12178
+ args.push("-p", port);
12179
+ }
12180
+ }
12181
+ if (params.labels) {
12182
+ for (const [key, value] of Object.entries(params.labels)) {
12183
+ args.push("--label", `${key}=${value}`);
12184
+ }
12185
+ }
12186
+ if (params.add_hosts) {
12187
+ for (const hostMapping of params.add_hosts) {
12188
+ args.push("--add-host", hostMapping);
12189
+ }
12190
+ }
12191
+ if (params.extra_args) {
12192
+ args.push(...params.extra_args);
12193
+ }
12194
+ args.push(params.image);
12195
+ const commandParts = normalizeCommand(params.command);
12196
+ if (commandParts.length) {
12197
+ args.push(...commandParts);
12198
+ }
12199
+ if (params.args?.length) {
12200
+ args.push(...params.args);
12201
+ }
12202
+ return args;
12203
+ }
12204
+ function normalizeCommand(command) {
12205
+ if (!command) return [];
12206
+ if (Array.isArray(command)) {
12207
+ return command.filter(Boolean);
12208
+ }
12209
+ return Shellwords2.split(command).filter(Boolean);
12210
+ }
12211
+ async function removeFileIfExists(context, path10, sudo) {
12212
+ try {
12213
+ await context.exec(["rm", "-f", path10], { sudo });
12214
+ } catch {
12215
+ }
12216
+ }
12217
+ async function readContainerId(context, path10, sudo) {
12218
+ try {
12219
+ const result = await context.exec(["cat", path10], { sudo });
12220
+ if (result.exitCode === 0) {
12221
+ return result.stdout.trim();
12222
+ }
12223
+ } catch {
12224
+ }
12225
+ return void 0;
12226
+ }
12227
+
12228
+ // src/core/docker/run-container.ts
12229
+ async function run92(context) {
12230
+ const { params, exec, info, error: logError2 } = context;
12231
+ if (!params.image) {
12232
+ const message = "Docker image is required.";
12233
+ logError2(message);
12234
+ return { success: false, exitCode: -1, stdout: "", stderr: "", error: message };
12235
+ }
12236
+ const runAsSudo = params.sudo ?? false;
12237
+ const cidFilePath = `/tmp/hostctl-docker-${crypto2.randomUUID()}.cid`;
12238
+ await removeFileIfExists(context, cidFilePath, runAsSudo);
12239
+ const dockerCommand = buildDockerRunCommand(params, {
12240
+ detach: false,
12241
+ cidFilePath,
12242
+ remove: params.remove ?? true
12243
+ });
12244
+ info(`Running docker container from image ${params.image}...`);
12245
+ const result = await exec(dockerCommand, { sudo: runAsSudo, cwd: params.cwd });
12246
+ const containerId = await readContainerId(context, cidFilePath, runAsSudo);
12247
+ await removeFileIfExists(context, cidFilePath, runAsSudo);
12248
+ if (result.exitCode !== 0) {
12249
+ const message = result.stderr || result.stdout || "Docker container exited with a non-zero status.";
12250
+ logError2(message);
12251
+ return {
12252
+ success: false,
12253
+ exitCode: result.exitCode,
12254
+ stdout: result.stdout,
12255
+ stderr: result.stderr,
12256
+ containerId,
12257
+ containerName: params.name,
12258
+ error: message
12259
+ };
12260
+ }
12261
+ return {
12262
+ success: true,
12263
+ exitCode: result.exitCode,
12264
+ stdout: result.stdout,
12265
+ stderr: result.stderr,
12266
+ containerId,
12267
+ containerName: params.name
12268
+ };
12269
+ }
12270
+ var run_container_default = task(run92, {
12271
+ description: "Runs a Docker container and returns its output (attached)."
12272
+ });
12273
+
12274
+ // src/core/docker/run-container-detached.ts
12275
+ import crypto3 from "crypto";
12276
+ async function run93(context) {
12277
+ const { params, exec, info, error: logError2 } = context;
12278
+ if (!params.image) {
12279
+ const message = "Docker image is required.";
12280
+ logError2(message);
12281
+ return { success: false, stdout: "", stderr: "", error: message };
12282
+ }
12283
+ const runAsSudo = params.sudo ?? false;
12284
+ const cidFilePath = `/tmp/hostctl-docker-${crypto3.randomUUID()}.cid`;
12285
+ await removeFileIfExists(context, cidFilePath, runAsSudo);
12286
+ const dockerCommand = buildDockerRunCommand(params, {
12287
+ detach: true,
12288
+ cidFilePath,
12289
+ remove: false
12290
+ });
12291
+ info(`Starting docker container in detached mode from image ${params.image}...`);
12292
+ const result = await exec(dockerCommand, { sudo: runAsSudo, cwd: params.cwd });
12293
+ const cidFromFile = await readContainerId(context, cidFilePath, runAsSudo);
12294
+ await removeFileIfExists(context, cidFilePath, runAsSudo);
12295
+ const containerId = cidFromFile || result.stdout.trim() || void 0;
12296
+ if (result.exitCode !== 0 || !containerId) {
12297
+ const message = result.stderr || result.stdout || "Failed to start Docker container.";
12298
+ logError2(message);
12299
+ return {
12300
+ success: false,
12301
+ stdout: result.stdout,
12302
+ stderr: result.stderr,
12303
+ containerId,
12304
+ containerName: params.name,
12305
+ error: message
12306
+ };
12307
+ }
12308
+ return {
12309
+ success: true,
12310
+ stdout: result.stdout,
12311
+ stderr: result.stderr,
12312
+ containerId,
12313
+ containerName: params.name
12314
+ };
12315
+ }
12316
+ var run_container_detached_default = task(run93, {
12317
+ description: "Runs a Docker container in detached mode and returns its metadata."
12318
+ });
12319
+
11520
12320
  // src/core/ssh/index.ts
11521
12321
  var ssh_exports = {};
11522
12322
  __export(ssh_exports, {
@@ -11527,7 +12327,7 @@ __export(ssh_exports, {
11527
12327
  import path6 from "path";
11528
12328
 
11529
12329
  // src/core/user/exists.ts
11530
- async function run92(context) {
12330
+ async function run94(context) {
11531
12331
  const { params, exec } = context;
11532
12332
  const { user } = params;
11533
12333
  const command = ["id", user].join(" ");
@@ -11536,10 +12336,10 @@ async function run92(context) {
11536
12336
  exists: exists2
11537
12337
  };
11538
12338
  }
11539
- var exists_default4 = task(run92, { name: "core.user.exists", description: "User exists." });
12339
+ var exists_default4 = task(run94, { name: "core.user.exists", description: "User exists." });
11540
12340
 
11541
12341
  // src/core/user/home_dir.ts
11542
- async function run93(context) {
12342
+ async function run95(context) {
11543
12343
  const { params, exec } = context;
11544
12344
  const { user } = params;
11545
12345
  const getentCommand = ["getent", "passwd", user].filter(Boolean).join(" ");
@@ -11560,10 +12360,10 @@ async function run93(context) {
11560
12360
  exists: exists2
11561
12361
  };
11562
12362
  }
11563
- var home_dir_default = task(run93, { name: "core.user.home_dir", description: "User home dir." });
12363
+ var home_dir_default = task(run95, { name: "core.user.home_dir", description: "User home dir." });
11564
12364
 
11565
12365
  // src/core/user/get_username.ts
11566
- async function run94(context) {
12366
+ async function run96(context) {
11567
12367
  const { exec } = context;
11568
12368
  const command = ["id", "-un"].filter(Boolean).join(" ");
11569
12369
  const { success, stdout: username } = await exec(command);
@@ -11572,10 +12372,10 @@ async function run94(context) {
11572
12372
  username: username.trim()
11573
12373
  };
11574
12374
  }
11575
- var get_username_default = task(run94, { name: "core.user.get_username", description: "User get username." });
12375
+ var get_username_default = task(run96, { name: "core.user.get_username", description: "User get username." });
11576
12376
 
11577
12377
  // src/core/ssh/copy_id.ts
11578
- async function run95(context) {
12378
+ async function run97(context) {
11579
12379
  const { params, run: runTask, exec, log, info, error } = context;
11580
12380
  let { public_key, user, sudo } = params;
11581
12381
  const publicKeyTrimmed = public_key.trim();
@@ -11655,7 +12455,7 @@ async function run95(context) {
11655
12455
  changed: true
11656
12456
  };
11657
12457
  }
11658
- var copy_id_default = task(run95, { name: "core.ssh.copy_id", description: "Ssh copy id." });
12458
+ var copy_id_default = task(run97, { name: "core.ssh.copy_id", description: "Ssh copy id." });
11659
12459
 
11660
12460
  // src/core/sudoers/index.ts
11661
12461
  var sudoers_exports = {};
@@ -11665,7 +12465,7 @@ __export(sudoers_exports, {
11665
12465
  });
11666
12466
 
11667
12467
  // src/core/sudoers/check.ts
11668
- async function run96(context) {
12468
+ async function run98(context) {
11669
12469
  const { params, exec, error } = context;
11670
12470
  const effectiveFile = params.file || "/etc/sudoers";
11671
12471
  try {
@@ -11686,10 +12486,10 @@ async function run96(context) {
11686
12486
  };
11687
12487
  }
11688
12488
  }
11689
- var check_default = task(run96, { name: "core.sudoers.check", description: "Sudoers check." });
12489
+ var check_default = task(run98, { name: "core.sudoers.check", description: "Sudoers check." });
11690
12490
 
11691
12491
  // src/core/sudoers/grant-nopasswd.ts
11692
- async function run97(context) {
12492
+ async function run99(context) {
11693
12493
  const { params, exec, error, info } = context;
11694
12494
  const { user } = params;
11695
12495
  if (!user) {
@@ -11773,7 +12573,7 @@ async function run97(context) {
11773
12573
  return { success: false, changed: false, filePath: "", error: e instanceof Error ? e.message : String(e) };
11774
12574
  }
11775
12575
  }
11776
- var grant_nopasswd_default = task(run97, {
12576
+ var grant_nopasswd_default = task(run99, {
11777
12577
  description: "Grants a user passwordless sudo privileges by creating a file in /etc/sudoers.d/."
11778
12578
  });
11779
12579
 
@@ -11791,7 +12591,7 @@ __export(process_exports, {
11791
12591
  });
11792
12592
 
11793
12593
  // src/core/process/list.ts
11794
- async function run98(context) {
12594
+ async function run100(context) {
11795
12595
  const { params, exec, debug, error } = context;
11796
12596
  const { user, command, limit, sort, reverse } = params;
11797
12597
  try {
@@ -11877,10 +12677,10 @@ async function run98(context) {
11877
12677
  return { success: false, error: errorMsg };
11878
12678
  }
11879
12679
  }
11880
- var list_default7 = task(run98, { description: "Lists processes on the system." });
12680
+ var list_default7 = task(run100, { description: "Lists processes on the system." });
11881
12681
 
11882
12682
  // src/core/process/search.ts
11883
- async function run99(context) {
12683
+ async function run101(context) {
11884
12684
  const { params, exec, debug, error } = context;
11885
12685
  const {
11886
12686
  name,
@@ -12004,10 +12804,10 @@ function filterProcesses(processes, filters) {
12004
12804
  return true;
12005
12805
  });
12006
12806
  }
12007
- var search_default6 = task(run99, { name: "core.process.search", description: "Search for processes matching specified criteria." });
12807
+ var search_default6 = task(run101, { name: "core.process.search", description: "Search for processes matching specified criteria." });
12008
12808
 
12009
12809
  // src/core/process/kill.ts
12010
- async function run100(context) {
12810
+ async function run102(context) {
12011
12811
  const { params, exec, debug, error } = context;
12012
12812
  const { pid, user, command, signal = "TERM", force = false, sudo = false } = params;
12013
12813
  try {
@@ -12095,10 +12895,10 @@ async function run100(context) {
12095
12895
  return { success: false, error: errorMsg };
12096
12896
  }
12097
12897
  }
12098
- var kill_default = task(run100, { description: "Kills processes matching specified criteria. Requires at least one filtering parameter (pid, user, or command) to prevent accidental killing of all processes." });
12898
+ var kill_default = task(run102, { description: "Kills processes matching specified criteria. Requires at least one filtering parameter (pid, user, or command) to prevent accidental killing of all processes." });
12099
12899
 
12100
12900
  // src/core/process/signal.ts
12101
- async function run101(context) {
12901
+ async function run103(context) {
12102
12902
  const { params, exec, debug, error } = context;
12103
12903
  const { pid, signal = "TERM", sudo = false } = params;
12104
12904
  if (!pid || pid <= 0) {
@@ -12121,10 +12921,10 @@ async function run101(context) {
12121
12921
  return { success: false, error: errorMsg };
12122
12922
  }
12123
12923
  }
12124
- var signal_default = task(run101, { description: "Sends a signal to a process." });
12924
+ var signal_default = task(run103, { description: "Sends a signal to a process." });
12125
12925
 
12126
12926
  // src/core/process/info.ts
12127
- async function run102(context) {
12927
+ async function run104(context) {
12128
12928
  const { params, exec, debug, error } = context;
12129
12929
  const { pid } = params;
12130
12930
  if (!pid || pid <= 0) {
@@ -12200,10 +13000,10 @@ async function run102(context) {
12200
13000
  return { success: false, error: errorMsg };
12201
13001
  }
12202
13002
  }
12203
- var info_default7 = task(run102, { description: "Gets detailed information about a specific process." });
13003
+ var info_default7 = task(run104, { description: "Gets detailed information about a specific process." });
12204
13004
 
12205
13005
  // src/core/process/top.ts
12206
- async function run103(context) {
13006
+ async function run105(context) {
12207
13007
  const { params, exec, debug, error } = context;
12208
13008
  const {
12209
13009
  limit = 10,
@@ -12362,10 +13162,10 @@ function sortProcesses(processes, sort) {
12362
13162
  }
12363
13163
  });
12364
13164
  }
12365
- var top_default = task(run103, { name: "core.process.top", description: "Get top processes with system information." });
13165
+ var top_default = task(run105, { name: "core.process.top", description: "Get top processes with system information." });
12366
13166
 
12367
13167
  // src/core/process/stats.ts
12368
- async function run104(context) {
13168
+ async function run106(context) {
12369
13169
  const { params, exec, debug, error } = context;
12370
13170
  const { includeUsers = true, includeStates = true, includeCommands = false, commandLimit = 10 } = params;
12371
13171
  debug(`Getting process statistics with params: ${JSON.stringify(params)}`);
@@ -12528,10 +13328,10 @@ function calculateCommandStats(processes, limit) {
12528
13328
  }
12529
13329
  return Array.from(commandMap.values()).sort((a, b) => b.cpu - a.cpu).slice(0, limit);
12530
13330
  }
12531
- var stats_default = task(run104, { name: "core.process.stats", description: "Get system-wide process statistics." });
13331
+ var stats_default = task(run106, { name: "core.process.stats", description: "Get system-wide process statistics." });
12532
13332
 
12533
13333
  // src/core/process/children.ts
12534
- async function run105(context) {
13334
+ async function run107(context) {
12535
13335
  const { params, exec, debug, error } = context;
12536
13336
  const { pid, recursive = false, maxDepth } = params;
12537
13337
  debug(`Getting children for process ${pid} with params: ${JSON.stringify(params)}`);
@@ -12608,7 +13408,7 @@ async function getDescendants(exec, parentPid, currentDepth, maxDepth) {
12608
13408
  }
12609
13409
  return allDescendants;
12610
13410
  }
12611
- var children_default = task(run105, { name: "core.process.children", description: "Get child processes of a given PID." });
13411
+ var children_default = task(run107, { name: "core.process.children", description: "Get child processes of a given PID." });
12612
13412
 
12613
13413
  // src/core/system/index.ts
12614
13414
  var system_exports = {};
@@ -12620,7 +13420,7 @@ __export(system_exports, {
12620
13420
  });
12621
13421
 
12622
13422
  // src/core/system/reboot.ts
12623
- async function run106(context) {
13423
+ async function run108(context) {
12624
13424
  const { params, info, warn, exec } = context;
12625
13425
  const time = params.time || "now";
12626
13426
  const sudo = params.sudo ?? true;
@@ -12653,12 +13453,12 @@ stderr: ${stderr}`
12653
13453
  };
12654
13454
  }
12655
13455
  }
12656
- var reboot_default = task(run106, {
13456
+ var reboot_default = task(run108, {
12657
13457
  description: "Reboots a system"
12658
13458
  });
12659
13459
 
12660
13460
  // src/core/system/shutdown.ts
12661
- async function run107(context) {
13461
+ async function run109(context) {
12662
13462
  const { params, info, warn, exec } = context;
12663
13463
  const time = params.time || "now";
12664
13464
  const sudo = params.sudo ?? true;
@@ -12690,10 +13490,10 @@ stderr: ${stderr}`
12690
13490
  };
12691
13491
  }
12692
13492
  }
12693
- var shutdown_default = task(run107);
13493
+ var shutdown_default = task(run109);
12694
13494
 
12695
13495
  // src/core/system/reboot_if_needed.ts
12696
- async function run108(context) {
13496
+ async function run110(context) {
12697
13497
  const { params, run: runTask, exec, error, info, warn } = context;
12698
13498
  const delayInSeconds = Math.max(1, params.delay ?? 1);
12699
13499
  const message = params.message ?? "Reboot is required. Initiating reboot sequence.";
@@ -12723,7 +13523,7 @@ ${stderr}`;
12723
13523
  }
12724
13524
  return { rebooting: true, success: true };
12725
13525
  }
12726
- var reboot_if_needed_default = task(run108, { name: "core.system.reboot_if_needed", description: "Reboot if needed." });
13526
+ var reboot_if_needed_default = task(run110, { name: "core.system.reboot_if_needed", description: "Reboot if needed." });
12727
13527
 
12728
13528
  // src/core/systemd/index.ts
12729
13529
  var systemd_exports = {};
@@ -12738,7 +13538,7 @@ __export(systemd_exports, {
12738
13538
  });
12739
13539
 
12740
13540
  // src/core/systemd/disable.ts
12741
- async function run109(context) {
13541
+ async function run111(context) {
12742
13542
  const { params, exec, error } = context;
12743
13543
  const { service, sudo = false } = params;
12744
13544
  if (!service) {
@@ -12761,10 +13561,10 @@ async function run109(context) {
12761
13561
  };
12762
13562
  }
12763
13563
  }
12764
- var disable_default = task(run109, { name: "core.systemd.disable", description: "Systemd disable." });
13564
+ var disable_default = task(run111, { name: "core.systemd.disable", description: "Systemd disable." });
12765
13565
 
12766
13566
  // src/core/systemd/enable.ts
12767
- async function run110(context) {
13567
+ async function run112(context) {
12768
13568
  const { params, exec, error } = context;
12769
13569
  const { service, sudo = false } = params;
12770
13570
  if (!service) {
@@ -12775,14 +13575,10 @@ async function run110(context) {
12775
13575
  };
12776
13576
  }
12777
13577
  try {
12778
- const commandArray = [];
12779
- if (sudo) {
12780
- commandArray.push("sudo");
12781
- }
12782
- commandArray.push("systemctl", "enable", service);
12783
- const { success } = await exec(commandArray);
13578
+ const result = await exec(["systemctl", "enable", service], { sudo });
12784
13579
  return {
12785
- success
13580
+ success: result.exitCode === 0,
13581
+ error: result.exitCode === 0 ? void 0 : result.stderr || result.stdout
12786
13582
  };
12787
13583
  } catch (err) {
12788
13584
  return {
@@ -12791,10 +13587,10 @@ async function run110(context) {
12791
13587
  };
12792
13588
  }
12793
13589
  }
12794
- var enable_default = task(run110, { name: "core.systemd.enable", description: "Systemd enable." });
13590
+ var enable_default = task(run112, { name: "core.systemd.enable", description: "Systemd enable." });
12795
13591
 
12796
13592
  // src/core/systemd/restart.ts
12797
- async function run111(context) {
13593
+ async function run113(context) {
12798
13594
  const { params, exec, error } = context;
12799
13595
  const { service, sudo = false } = params;
12800
13596
  if (!service) {
@@ -12821,10 +13617,10 @@ async function run111(context) {
12821
13617
  };
12822
13618
  }
12823
13619
  }
12824
- var restart_default = task(run111, { name: "core.systemd.restart", description: "Systemd restart." });
13620
+ var restart_default = task(run113, { name: "core.systemd.restart", description: "Systemd restart." });
12825
13621
 
12826
13622
  // src/core/systemd/start.ts
12827
- async function run112(context) {
13623
+ async function run114(context) {
12828
13624
  const { params, exec, error } = context;
12829
13625
  const { service, sudo = false } = params;
12830
13626
  if (!service) {
@@ -12835,14 +13631,10 @@ async function run112(context) {
12835
13631
  };
12836
13632
  }
12837
13633
  try {
12838
- const commandArray = [];
12839
- if (sudo) {
12840
- commandArray.push("sudo");
12841
- }
12842
- commandArray.push("systemctl", "start", service);
12843
- const { success } = await exec(commandArray);
13634
+ const result = await exec(["systemctl", "start", service], { sudo });
12844
13635
  return {
12845
- success
13636
+ success: result.exitCode === 0,
13637
+ error: result.exitCode === 0 ? void 0 : result.stderr || result.stdout
12846
13638
  };
12847
13639
  } catch (err) {
12848
13640
  return {
@@ -12851,10 +13643,10 @@ async function run112(context) {
12851
13643
  };
12852
13644
  }
12853
13645
  }
12854
- var start_default = task(run112, { name: "core.systemd.start", description: "Systemd start." });
13646
+ var start_default = task(run114, { name: "core.systemd.start", description: "Systemd start." });
12855
13647
 
12856
13648
  // src/core/systemd/stop.ts
12857
- async function run113(context) {
13649
+ async function run115(context) {
12858
13650
  const { params, exec, error } = context;
12859
13651
  const { service, sudo = false } = params;
12860
13652
  if (!service) {
@@ -12881,10 +13673,10 @@ async function run113(context) {
12881
13673
  };
12882
13674
  }
12883
13675
  }
12884
- var stop_default = task(run113, { name: "core.systemd.stop", description: "Systemd stop." });
13676
+ var stop_default = task(run115, { name: "core.systemd.stop", description: "Systemd stop." });
12885
13677
 
12886
13678
  // src/core/systemd/reload.ts
12887
- async function run114(context) {
13679
+ async function run116(context) {
12888
13680
  const { params, exec, error } = context;
12889
13681
  const { service, sudo = false } = params;
12890
13682
  if (!service) {
@@ -12905,13 +13697,13 @@ async function run114(context) {
12905
13697
  };
12906
13698
  }
12907
13699
  }
12908
- var reload_default = task(run114, {
13700
+ var reload_default = task(run116, {
12909
13701
  name: "core.systemd.reload",
12910
13702
  description: "Reloads a systemd service (e.g., re-reads configuration without full restart)."
12911
13703
  });
12912
13704
 
12913
13705
  // src/core/systemd/status.ts
12914
- async function run115(context) {
13706
+ async function run117(context) {
12915
13707
  const { params, exec, error } = context;
12916
13708
  const { service, sudo = false } = params;
12917
13709
  if (!service) {
@@ -12934,7 +13726,7 @@ async function run115(context) {
12934
13726
  };
12935
13727
  }
12936
13728
  }
12937
- var status_default = task(run115, {
13729
+ var status_default = task(run117, {
12938
13730
  name: "core.systemd.status",
12939
13731
  description: "Checks systemd service status."
12940
13732
  });
@@ -12949,7 +13741,7 @@ __export(template_exports, {
12949
13741
  import { promises as fs9 } from "fs";
12950
13742
  import path7 from "path";
12951
13743
  async function runFn3(context) {
12952
- const { params, warn, error, debug, run: run245 } = context;
13744
+ const { params, warn, error, debug, run: run247 } = context;
12953
13745
  const { template, template_file, variables, to, mode, owner, group, sudo } = params;
12954
13746
  let templateContent = template;
12955
13747
  if (template && template_file) {
@@ -12996,7 +13788,7 @@ async function runFn3(context) {
12996
13788
  debug(`Setting mode ${mode} for ${outputPath}`);
12997
13789
  try {
12998
13790
  const chmodParams = { path: outputPath, mode, sudo };
12999
- const chmodResult = await run245(chmod_default(chmodParams));
13791
+ const chmodResult = await run247(chmod_default(chmodParams));
13000
13792
  if (chmodResult instanceof Error) {
13001
13793
  error(`Error setting mode for ${outputPath}: ${chmodResult.message}`);
13002
13794
  overallSuccess = false;
@@ -13022,7 +13814,7 @@ async function runFn3(context) {
13022
13814
  if (group) {
13023
13815
  chownTaskParams.group = group;
13024
13816
  }
13025
- const chownResult = await run245(chown_default(chownTaskParams));
13817
+ const chownResult = await run247(chown_default(chownTaskParams));
13026
13818
  if (chownResult instanceof Error) {
13027
13819
  error(`Error setting owner/group for ${outputPath}: ${chownResult.message}`);
13028
13820
  overallSuccess = false;
@@ -13063,7 +13855,7 @@ __export(ufw_exports, {
13063
13855
  });
13064
13856
 
13065
13857
  // src/core/ufw/allow.ts
13066
- async function run116(context) {
13858
+ async function run118(context) {
13067
13859
  const { params, exec, info } = context;
13068
13860
  const { port, proto = "tcp", from } = params;
13069
13861
  if (!port) {
@@ -13094,10 +13886,10 @@ async function run116(context) {
13094
13886
  return { success: false, error };
13095
13887
  }
13096
13888
  }
13097
- var allow_default = task(run116, { description: "Allows a port through UFW firewall." });
13889
+ var allow_default = task(run118, { description: "Allows a port through UFW firewall." });
13098
13890
 
13099
13891
  // src/core/ufw/deny.ts
13100
- async function run117(context) {
13892
+ async function run119(context) {
13101
13893
  const { params, exec, error, info } = context;
13102
13894
  const { port, proto = "tcp", from } = params;
13103
13895
  if (!port) {
@@ -13128,10 +13920,10 @@ async function run117(context) {
13128
13920
  };
13129
13921
  }
13130
13922
  }
13131
- var deny_default = task(run117, { name: "core.ufw.deny", description: "Ufw deny." });
13923
+ var deny_default = task(run119, { name: "core.ufw.deny", description: "Ufw deny." });
13132
13924
 
13133
13925
  // src/core/ufw/delete.ts
13134
- async function run118(context) {
13926
+ async function run120(context) {
13135
13927
  const { params, exec, error } = context;
13136
13928
  const { rule_number } = params;
13137
13929
  if (!rule_number || rule_number <= 0) {
@@ -13153,10 +13945,10 @@ async function run118(context) {
13153
13945
  };
13154
13946
  }
13155
13947
  }
13156
- var delete_default3 = task(run118, { name: "core.ufw.delete", description: "Ufw delete." });
13948
+ var delete_default3 = task(run120, { name: "core.ufw.delete", description: "Ufw delete." });
13157
13949
 
13158
13950
  // src/core/ufw/disable.ts
13159
- async function run119(context) {
13951
+ async function run121(context) {
13160
13952
  const { exec, error } = context;
13161
13953
  try {
13162
13954
  const result = await exec(["ufw", "disable"], { sudo: true });
@@ -13172,10 +13964,10 @@ async function run119(context) {
13172
13964
  return { success: false, error: errorMsg };
13173
13965
  }
13174
13966
  }
13175
- var disable_default2 = task(run119, { description: "Disables UFW firewall." });
13967
+ var disable_default2 = task(run121, { description: "Disables UFW firewall." });
13176
13968
 
13177
13969
  // src/core/ufw/enable.ts
13178
- async function run120(context) {
13970
+ async function run122(context) {
13179
13971
  const { exec, error } = context;
13180
13972
  try {
13181
13973
  const result = await exec(["ufw", "--force", "enable"], { sudo: true });
@@ -13191,10 +13983,10 @@ async function run120(context) {
13191
13983
  return { success: false, error: errorMsg };
13192
13984
  }
13193
13985
  }
13194
- var enable_default2 = task(run120, { description: "Enables UFW firewall." });
13986
+ var enable_default2 = task(run122, { description: "Enables UFW firewall." });
13195
13987
 
13196
13988
  // src/core/ufw/install.ts
13197
- async function run121(context) {
13989
+ async function run123(context) {
13198
13990
  const { run: runTask, error } = context;
13199
13991
  try {
13200
13992
  const installResult = await runTask(install_default5({ package: "ufw", sudo: true }));
@@ -13213,10 +14005,10 @@ async function run121(context) {
13213
14005
  };
13214
14006
  }
13215
14007
  }
13216
- var install_default7 = task(run121, { name: "core.ufw.install", description: "Ufw install." });
14008
+ var install_default7 = task(run123, { name: "core.ufw.install", description: "Ufw install." });
13217
14009
 
13218
14010
  // src/core/ufw/logging.ts
13219
- async function run122(context) {
14011
+ async function run124(context) {
13220
14012
  const { params, exec, log } = context;
13221
14013
  const level = params.level || "on";
13222
14014
  try {
@@ -13233,10 +14025,10 @@ async function run122(context) {
13233
14025
  return { success: false, error };
13234
14026
  }
13235
14027
  }
13236
- var logging_default = task(run122, { description: "Configures UFW logging" });
14028
+ var logging_default = task(run124, { description: "Configures UFW logging" });
13237
14029
 
13238
14030
  // src/core/ufw/reload.ts
13239
- async function run123(context) {
14031
+ async function run125(context) {
13240
14032
  const { exec, error } = context;
13241
14033
  try {
13242
14034
  const { success } = await exec(["sudo", "ufw", "reload"], { sudo: true });
@@ -13248,10 +14040,10 @@ async function run123(context) {
13248
14040
  };
13249
14041
  }
13250
14042
  }
13251
- var reload_default2 = task(run123, { name: "core.ufw.reload", description: "Ufw reload." });
14043
+ var reload_default2 = task(run125, { name: "core.ufw.reload", description: "Ufw reload." });
13252
14044
 
13253
14045
  // src/core/ufw/reset.ts
13254
- async function run124(context) {
14046
+ async function run126(context) {
13255
14047
  const { exec, error, info } = context;
13256
14048
  try {
13257
14049
  const command = ["ufw", "--force", "reset"];
@@ -13272,10 +14064,10 @@ async function run124(context) {
13272
14064
  return { success: false, error: errorMsg };
13273
14065
  }
13274
14066
  }
13275
- var reset_default = task(run124, { name: "core.ufw.reset", description: "Resets UFW firewall to default state." });
14067
+ var reset_default = task(run126, { name: "core.ufw.reset", description: "Resets UFW firewall to default state." });
13276
14068
 
13277
14069
  // src/core/ufw/status.ts
13278
- async function run125(context) {
14070
+ async function run127(context) {
13279
14071
  const { exec, error } = context;
13280
14072
  try {
13281
14073
  const result = await exec(["ufw", "status", "numbered"], { sudo: true });
@@ -13330,7 +14122,7 @@ async function run125(context) {
13330
14122
  return { success: false, error: errorMsg };
13331
14123
  }
13332
14124
  }
13333
- var status_default2 = task(run125, { description: "Gets UFW firewall status with numbered rules." });
14125
+ var status_default2 = task(run127, { description: "Gets UFW firewall status with numbered rules." });
13334
14126
 
13335
14127
  // src/core/user/index.ts
13336
14128
  var user_exports = {};
@@ -13350,7 +14142,7 @@ __export(user_exports, {
13350
14142
  });
13351
14143
 
13352
14144
  // src/core/user/add_groups.ts
13353
- async function run126(context) {
14145
+ async function run128(context) {
13354
14146
  const { params, exec } = context;
13355
14147
  const { user, groups } = params;
13356
14148
  const normalizedGroups = Array.isArray(groups) ? groups : typeof groups === "string" ? groups.split(",").map((group) => group.trim()).filter(Boolean) : [];
@@ -13364,10 +14156,10 @@ async function run126(context) {
13364
14156
  success
13365
14157
  };
13366
14158
  }
13367
- var add_groups_default = task(run126, { name: "core.user.add_groups", description: "User add groups." });
14159
+ var add_groups_default = task(run128, { name: "core.user.add_groups", description: "User add groups." });
13368
14160
 
13369
14161
  // src/core/user/create.ts
13370
- async function run127(context) {
14162
+ async function run129(context) {
13371
14163
  const { params, exec, run: runTask, error } = context;
13372
14164
  const { user, create_home = true, create_group = true, system = false, sudo = true } = params;
13373
14165
  if (!user) {
@@ -13414,10 +14206,10 @@ async function run127(context) {
13414
14206
  };
13415
14207
  }
13416
14208
  }
13417
- var create_default3 = task(run127, { name: "core.user.create", description: "User create." });
14209
+ var create_default3 = task(run129, { name: "core.user.create", description: "User create." });
13418
14210
 
13419
14211
  // src/core/user/get_gid.ts
13420
- async function run128(context) {
14212
+ async function run130(context) {
13421
14213
  const { params, exec } = context;
13422
14214
  const { user } = params;
13423
14215
  const command = ["id", "-g", user].filter(Boolean).join(" ");
@@ -13427,10 +14219,10 @@ async function run128(context) {
13427
14219
  gid: gid.trim()
13428
14220
  };
13429
14221
  }
13430
- var get_gid_default = task(run128, { name: "core.user.get_gid", description: "User get gid." });
14222
+ var get_gid_default = task(run130, { name: "core.user.get_gid", description: "User get gid." });
13431
14223
 
13432
14224
  // src/core/user/get_groups.ts
13433
- async function run129(context) {
14225
+ async function run131(context) {
13434
14226
  const { params, exec } = context;
13435
14227
  const { user } = params;
13436
14228
  const command = ["groups", user].filter(Boolean).join(" ");
@@ -13447,10 +14239,10 @@ async function run129(context) {
13447
14239
  groups
13448
14240
  };
13449
14241
  }
13450
- var get_groups_default = task(run129, { name: "core.user.get_groups", description: "User get groups." });
14242
+ var get_groups_default = task(run131, { name: "core.user.get_groups", description: "User get groups." });
13451
14243
 
13452
14244
  // src/core/user/get_uid.ts
13453
- async function run130(context) {
14245
+ async function run132(context) {
13454
14246
  const { params, exec } = context;
13455
14247
  const { user } = params;
13456
14248
  const command = ["id", "-u", user].filter(Boolean).join(" ");
@@ -13460,10 +14252,10 @@ async function run130(context) {
13460
14252
  uid: uid.trim()
13461
14253
  };
13462
14254
  }
13463
- var get_uid_default = task(run130, { name: "core.user.get_uid", description: "User get uid." });
14255
+ var get_uid_default = task(run132, { name: "core.user.get_uid", description: "User get uid." });
13464
14256
 
13465
14257
  // src/core/user/set_groups.ts
13466
- async function run131(context) {
14258
+ async function run133(context) {
13467
14259
  const { params, exec } = context;
13468
14260
  const { user, groups } = params;
13469
14261
  const normalizedGroups = Array.isArray(groups) ? groups : typeof groups === "string" ? groups.split(",").map((group) => group.trim()).filter(Boolean) : [];
@@ -13477,10 +14269,10 @@ async function run131(context) {
13477
14269
  success
13478
14270
  };
13479
14271
  }
13480
- var set_groups_default = task(run131, { name: "core.user.set_groups", description: "User set groups." });
14272
+ var set_groups_default = task(run133, { name: "core.user.set_groups", description: "User set groups." });
13481
14273
 
13482
14274
  // src/core/user/set_shell.ts
13483
- async function run132(context) {
14275
+ async function run134(context) {
13484
14276
  const { params, exec } = context;
13485
14277
  const { user, shell } = params;
13486
14278
  const command = ["sudo", "usermod", "-s", shell, user].filter(Boolean).join(" ");
@@ -13489,11 +14281,11 @@ async function run132(context) {
13489
14281
  success
13490
14282
  };
13491
14283
  }
13492
- var set_shell_default = task(run132, { name: "core.user.set_shell", description: "User set shell." });
14284
+ var set_shell_default = task(run134, { name: "core.user.set_shell", description: "User set shell." });
13493
14285
 
13494
14286
  // src/core/user/delete.ts
13495
- async function run133(context) {
13496
- const { params, debug, exec, run: run245, error } = context;
14287
+ async function run135(context) {
14288
+ const { params, debug, exec, run: run247, error } = context;
13497
14289
  const { user, remove: remove4 = false, sudo = true } = params;
13498
14290
  if (!user) {
13499
14291
  error('Required parameter "user" is missing');
@@ -13503,7 +14295,7 @@ async function run133(context) {
13503
14295
  };
13504
14296
  }
13505
14297
  try {
13506
- const { exists: userExists } = await run245(exists_default4({ user }));
14298
+ const { exists: userExists } = await run247(exists_default4({ user }));
13507
14299
  if (!userExists) {
13508
14300
  debug(`User '${user}' does not exist, considering task successful (idempotent).`);
13509
14301
  return { success: true };
@@ -13531,12 +14323,12 @@ async function run133(context) {
13531
14323
  };
13532
14324
  }
13533
14325
  }
13534
- var delete_default4 = task(run133, {
14326
+ var delete_default4 = task(run135, {
13535
14327
  description: "Deletes a user from the system idempotently"
13536
14328
  });
13537
14329
 
13538
14330
  // src/core/user/modify.ts
13539
- async function run134(context) {
14331
+ async function run136(context) {
13540
14332
  const { params, exec, run: runTask, error } = context;
13541
14333
  const {
13542
14334
  user,
@@ -13595,7 +14387,7 @@ async function run134(context) {
13595
14387
  };
13596
14388
  }
13597
14389
  }
13598
- var modify_default2 = task(run134, { name: "core.user.modify", description: "Modify an existing user account." });
14390
+ var modify_default2 = task(run136, { name: "core.user.modify", description: "Modify an existing user account." });
13599
14391
 
13600
14392
  // src/core/xcpng/index.ts
13601
14393
  var xcpng_exports = {};
@@ -13852,7 +14644,7 @@ function coerceBoolean(value, defaultValue = false) {
13852
14644
  }
13853
14645
 
13854
14646
  // src/core/xcpng/attach-vdi.ts
13855
- async function run135(context) {
14647
+ async function run137(context) {
13856
14648
  const { params, error, debug } = context;
13857
14649
  const {
13858
14650
  vm_uuid,
@@ -13917,7 +14709,7 @@ async function run135(context) {
13917
14709
  plugged: true
13918
14710
  };
13919
14711
  }
13920
- var attach_vdi_default = task(run135, {
14712
+ var attach_vdi_default = task(run137, {
13921
14713
  description: "Attaches an existing virtual disk image to a VM and plugs it into the guest."
13922
14714
  });
13923
14715
 
@@ -13963,7 +14755,7 @@ function resolveSizeBytes(input, fieldLabel) {
13963
14755
  }
13964
14756
 
13965
14757
  // src/core/xcpng/create-vdi.ts
13966
- async function run136(context) {
14758
+ async function run138(context) {
13967
14759
  const { params, error } = context;
13968
14760
  const {
13969
14761
  name_label,
@@ -14029,12 +14821,12 @@ async function run136(context) {
14029
14821
  command: result.command
14030
14822
  };
14031
14823
  }
14032
- var create_vdi_default = task(run136, {
14824
+ var create_vdi_default = task(run138, {
14033
14825
  description: "Creates a new virtual disk image on the specified XCP-ng storage repository."
14034
14826
  });
14035
14827
 
14036
14828
  // src/core/xcpng/list-sr-params.ts
14037
- async function run137(context) {
14829
+ async function run139(context) {
14038
14830
  const filters = normalizeFilterArgs(context.params?.filters);
14039
14831
  const result = await runXeCommand(context, "sr-param-list", filters);
14040
14832
  if (!result.success) {
@@ -14048,12 +14840,12 @@ async function run137(context) {
14048
14840
  items: parseKeyValueOutput(result.stdout)
14049
14841
  };
14050
14842
  }
14051
- var list_sr_params_default = task(run137, {
14843
+ var list_sr_params_default = task(run139, {
14052
14844
  description: "Lists parameters for storage repositories (SRs) on an XCP-ng host."
14053
14845
  });
14054
14846
 
14055
14847
  // src/core/xcpng/list-storage-repositories.ts
14056
- async function run138(context) {
14848
+ async function run140(context) {
14057
14849
  const { params } = context;
14058
14850
  const filters = normalizeFilterArgs(params?.filters);
14059
14851
  const result = await runXeCommand(context, "sr-list", filters);
@@ -14104,12 +14896,12 @@ async function run138(context) {
14104
14896
  items: enrichedItems
14105
14897
  };
14106
14898
  }
14107
- var list_storage_repositories_default = task(run138, {
14899
+ var list_storage_repositories_default = task(run140, {
14108
14900
  description: "Lists storage repositories on an XCP-ng host."
14109
14901
  });
14110
14902
 
14111
14903
  // src/core/xcpng/find-storage-repository.ts
14112
- async function run139(context) {
14904
+ async function run141(context) {
14113
14905
  const params = context.params ?? {};
14114
14906
  const {
14115
14907
  name_label: nameLabel,
@@ -14229,12 +15021,12 @@ async function runListStorageRepositories(context, params) {
14229
15021
  })
14230
15022
  );
14231
15023
  }
14232
- var find_storage_repository_default = task(run139, {
15024
+ var find_storage_repository_default = task(run141, {
14233
15025
  description: "Finds a single storage repository on an XCP-ng host, optionally allowing multiple matches."
14234
15026
  });
14235
15027
 
14236
15028
  // src/core/xcpng/add-disk.ts
14237
- async function run140(context) {
15029
+ async function run142(context) {
14238
15030
  const { params, error } = context;
14239
15031
  const {
14240
15032
  vm_uuid: vmUuid,
@@ -14367,12 +15159,12 @@ async function destroyVdi(context, vdiUuid, appliedCommands) {
14367
15159
  context.warn(`Failed to clean up VDI ${vdiUuid}: ${xeErrorMessage(result, "unknown error")}`);
14368
15160
  }
14369
15161
  }
14370
- var add_disk_default = task(run140, {
15162
+ var add_disk_default = task(run142, {
14371
15163
  description: "Creates a VDI and attaches it to a VM on XCP-ng."
14372
15164
  });
14373
15165
 
14374
15166
  // src/core/xcpng/attach-iso.ts
14375
- async function run141(context) {
15167
+ async function run143(context) {
14376
15168
  const { params, error, debug } = context;
14377
15169
  const {
14378
15170
  vm_uuid,
@@ -14470,12 +15262,12 @@ async function run141(context) {
14470
15262
  plugged
14471
15263
  };
14472
15264
  }
14473
- var attach_iso_default = task(run141, {
15265
+ var attach_iso_default = task(run143, {
14474
15266
  description: "Attaches an ISO image to a VM by invoking xe vm-cd-insert, ejecting existing media if requested."
14475
15267
  });
14476
15268
 
14477
15269
  // src/core/xcpng/attach-network-interface.ts
14478
- async function run142(context) {
15270
+ async function run144(context) {
14479
15271
  const { params, error, debug } = context;
14480
15272
  const {
14481
15273
  vm_uuid,
@@ -14546,12 +15338,12 @@ async function run142(context) {
14546
15338
  plugged: true
14547
15339
  };
14548
15340
  }
14549
- var attach_network_interface_default = task(run142, {
15341
+ var attach_network_interface_default = task(run144, {
14550
15342
  description: "Creates and plugs a virtual network interface for a VM on XCP-ng."
14551
15343
  });
14552
15344
 
14553
15345
  // src/core/xcpng/list-template-params.ts
14554
- async function run143(context) {
15346
+ async function run145(context) {
14555
15347
  const filters = normalizeFilterArgs(context.params?.filters);
14556
15348
  const result = await runXeCommand(context, "template-param-list", filters);
14557
15349
  if (!result.success) {
@@ -14565,12 +15357,12 @@ async function run143(context) {
14565
15357
  items: parseKeyValueOutput(result.stdout)
14566
15358
  };
14567
15359
  }
14568
- var list_template_params_default = task(run143, {
15360
+ var list_template_params_default = task(run145, {
14569
15361
  description: "Lists parameters for templates on an XCP-ng host."
14570
15362
  });
14571
15363
 
14572
15364
  // src/core/xcpng/list-templates.ts
14573
- async function run144(context) {
15365
+ async function run146(context) {
14574
15366
  const filters = normalizeFilterArgs(context.params?.filters);
14575
15367
  const result = await runXeCommand(context, "template-list", filters);
14576
15368
  if (!result.success) {
@@ -14622,12 +15414,12 @@ async function run144(context) {
14622
15414
  items: enriched
14623
15415
  };
14624
15416
  }
14625
- var list_templates_default = task(run144, {
15417
+ var list_templates_default = task(run146, {
14626
15418
  description: "Lists VM templates available on the XCP-ng host."
14627
15419
  });
14628
15420
 
14629
15421
  // src/core/xcpng/find-template.ts
14630
- async function run145(context) {
15422
+ async function run147(context) {
14631
15423
  const params = context.params ?? {};
14632
15424
  const {
14633
15425
  name_label: nameLabel,
@@ -14725,12 +15517,12 @@ async function runListTemplates(context, params) {
14725
15517
  })
14726
15518
  );
14727
15519
  }
14728
- var find_template_default = task(run145, {
15520
+ var find_template_default = task(run147, {
14729
15521
  description: "Finds a single template on an XCP-ng host, optionally allowing multiple matches."
14730
15522
  });
14731
15523
 
14732
15524
  // src/core/xcpng/clone-template.ts
14733
- async function run146(context) {
15525
+ async function run148(context) {
14734
15526
  const { params, error } = context;
14735
15527
  const {
14736
15528
  source_template_uuid: sourceTemplateUuidParam,
@@ -14850,12 +15642,12 @@ async function run146(context) {
14850
15642
  appliedCommands
14851
15643
  };
14852
15644
  }
14853
- var clone_template_default = task(run146, {
15645
+ var clone_template_default = task(run148, {
14854
15646
  description: "Clones an existing XCP-ng template to a new template name."
14855
15647
  });
14856
15648
 
14857
15649
  // src/core/xcpng/list-hosts.ts
14858
- async function run147(context) {
15650
+ async function run149(context) {
14859
15651
  const filters = normalizeFilterArgs(context.params?.filters);
14860
15652
  const result = await runXeCommand(context, "host-list", filters);
14861
15653
  if (!result.success) {
@@ -14869,12 +15661,12 @@ async function run147(context) {
14869
15661
  items: parseKeyValueOutput(result.stdout)
14870
15662
  };
14871
15663
  }
14872
- var list_hosts_default = task(run147, {
15664
+ var list_hosts_default = task(run149, {
14873
15665
  description: "Lists hosts in an XCP-ng pool, returning parsed xe host-list output."
14874
15666
  });
14875
15667
 
14876
15668
  // src/core/xcpng/find-host.ts
14877
- async function run148(context) {
15669
+ async function run150(context) {
14878
15670
  const params = context.params ?? {};
14879
15671
  const {
14880
15672
  name_label: nameLabel,
@@ -14974,12 +15766,12 @@ async function runListHosts(context, params) {
14974
15766
  })
14975
15767
  );
14976
15768
  }
14977
- var find_host_default = task(run148, {
15769
+ var find_host_default = task(run150, {
14978
15770
  description: "Finds a single host on an XCP-ng pool, optionally allowing multiple matches."
14979
15771
  });
14980
15772
 
14981
15773
  // src/core/xcpng/list-network-params.ts
14982
- async function run149(context) {
15774
+ async function run151(context) {
14983
15775
  const filters = normalizeFilterArgs(context.params?.filters);
14984
15776
  const result = await runXeCommand(context, "network-param-list", filters);
14985
15777
  if (!result.success) {
@@ -14993,12 +15785,12 @@ async function run149(context) {
14993
15785
  items: parseKeyValueOutput(result.stdout)
14994
15786
  };
14995
15787
  }
14996
- var list_network_params_default = task(run149, {
15788
+ var list_network_params_default = task(run151, {
14997
15789
  description: "Lists parameters for networks on an XCP-ng host."
14998
15790
  });
14999
15791
 
15000
15792
  // src/core/xcpng/list-networks.ts
15001
- async function run150(context) {
15793
+ async function run152(context) {
15002
15794
  const { params } = context;
15003
15795
  const filters = normalizeFilterArgs(params?.filters);
15004
15796
  const result = await runXeCommand(context, "network-list", filters);
@@ -15049,12 +15841,12 @@ async function run150(context) {
15049
15841
  items: enrichedItems
15050
15842
  };
15051
15843
  }
15052
- var list_networks_default = task(run150, {
15844
+ var list_networks_default = task(run152, {
15053
15845
  description: "Lists networks on an XCP-ng host."
15054
15846
  });
15055
15847
 
15056
15848
  // src/core/xcpng/find-network.ts
15057
- async function run151(context) {
15849
+ async function run153(context) {
15058
15850
  const params = context.params ?? {};
15059
15851
  const {
15060
15852
  name_label: nameLabel,
@@ -15145,12 +15937,12 @@ function buildMultipleMessage4(nameLabel, uuid, count) {
15145
15937
  const detail = identifiers.length > 0 ? identifiers.join(", ") : "specified criteria";
15146
15938
  return `Multiple networks (${count}) matched ${detail}; refine filters or set allow_multiple:true.`;
15147
15939
  }
15148
- var find_network_default = task(run151, {
15940
+ var find_network_default = task(run153, {
15149
15941
  description: "Finds a single network on an XCP-ng host, optionally allowing multiple matches."
15150
15942
  });
15151
15943
 
15152
15944
  // src/core/xcpng/create-bond.ts
15153
- async function run152(context) {
15945
+ async function run154(context) {
15154
15946
  const { params, error } = context;
15155
15947
  const {
15156
15948
  host_uuid: hostUuidParam,
@@ -15272,12 +16064,12 @@ async function run152(context) {
15272
16064
  appliedCommands
15273
16065
  };
15274
16066
  }
15275
- var create_bond_default = task(run152, {
16067
+ var create_bond_default = task(run154, {
15276
16068
  description: "Creates a bonded interface on a host, wrapping xe bond-create."
15277
16069
  });
15278
16070
 
15279
16071
  // src/core/xcpng/list-pbd-params.ts
15280
- async function run153(context) {
16072
+ async function run155(context) {
15281
16073
  const filters = normalizeFilterArgs(context.params?.filters);
15282
16074
  const result = await runXeCommand(context, "pbd-param-list", filters);
15283
16075
  if (!result.success) {
@@ -15291,12 +16083,12 @@ async function run153(context) {
15291
16083
  items: parseKeyValueOutput(result.stdout)
15292
16084
  };
15293
16085
  }
15294
- var list_pbd_params_default = task(run153, {
16086
+ var list_pbd_params_default = task(run155, {
15295
16087
  description: "Lists parameters for PBDs on an XCP-ng host."
15296
16088
  });
15297
16089
 
15298
16090
  // src/core/xcpng/list-pbds.ts
15299
- async function run154(context) {
16091
+ async function run156(context) {
15300
16092
  const filters = normalizeFilterArgs(context.params?.filters);
15301
16093
  const result = await runXeCommand(context, "pbd-list", filters);
15302
16094
  if (!result.success) {
@@ -15346,12 +16138,12 @@ async function run154(context) {
15346
16138
  items: enrichedItems
15347
16139
  };
15348
16140
  }
15349
- var list_pbds_default = task(run154, {
16141
+ var list_pbds_default = task(run156, {
15350
16142
  description: "Lists storage bindings (PBDs) between hosts and storage repositories."
15351
16143
  });
15352
16144
 
15353
16145
  // src/core/xcpng/find-pbd.ts
15354
- async function run155(context) {
16146
+ async function run157(context) {
15355
16147
  const params = context.params ?? {};
15356
16148
  const {
15357
16149
  uuid,
@@ -15464,12 +16256,12 @@ async function runListPbds(context, params) {
15464
16256
  })
15465
16257
  );
15466
16258
  }
15467
- var find_pbd_default = task(run155, {
16259
+ var find_pbd_default = task(run157, {
15468
16260
  description: "Finds a single PBD (host \u2194 SR binding), optionally allowing multiple matches."
15469
16261
  });
15470
16262
 
15471
16263
  // src/core/xcpng/create-pbd.ts
15472
- async function run156(context) {
16264
+ async function run158(context) {
15473
16265
  const { params, error } = context;
15474
16266
  const {
15475
16267
  host_uuid: hostUuidParam,
@@ -15586,12 +16378,12 @@ async function run156(context) {
15586
16378
  appliedCommands
15587
16379
  };
15588
16380
  }
15589
- var create_pbd_default = task(run156, {
16381
+ var create_pbd_default = task(run158, {
15590
16382
  description: "Creates a host \u2194 storage repository binding (PBD)."
15591
16383
  });
15592
16384
 
15593
16385
  // src/core/xcpng/list-vm-params.ts
15594
- async function run157(context) {
16386
+ async function run159(context) {
15595
16387
  const filters = normalizeFilterArgs(context.params?.filters);
15596
16388
  const result = await runXeCommand(context, "vm-param-list", filters);
15597
16389
  if (!result.success) {
@@ -15605,12 +16397,12 @@ async function run157(context) {
15605
16397
  items: parseKeyValueOutput(result.stdout)
15606
16398
  };
15607
16399
  }
15608
- var list_vm_params_default = task(run157, {
16400
+ var list_vm_params_default = task(run159, {
15609
16401
  description: "Lists virtual machines (VMs) on an XCP-ng host."
15610
16402
  });
15611
16403
 
15612
16404
  // src/core/xcpng/list-vms.ts
15613
- async function run158(context) {
16405
+ async function run160(context) {
15614
16406
  const { params } = context;
15615
16407
  const filters = normalizeFilterArgs(params?.filters);
15616
16408
  const paramsArg = buildParamsArg(params?.params);
@@ -15665,7 +16457,7 @@ async function run158(context) {
15665
16457
  items: enrichedItems
15666
16458
  };
15667
16459
  }
15668
- var list_vms_default = task(run158, {
16460
+ var list_vms_default = task(run160, {
15669
16461
  description: "Lists VMs on an XCP-ng host and returns structured metadata."
15670
16462
  });
15671
16463
  var DEFAULT_VM_FIELDS = [
@@ -15699,7 +16491,7 @@ function buildParamsArg(params) {
15699
16491
  }
15700
16492
 
15701
16493
  // src/core/xcpng/find-vm.ts
15702
- async function run159(context) {
16494
+ async function run161(context) {
15703
16495
  const params = context.params ?? {};
15704
16496
  const {
15705
16497
  name_label: nameLabel,
@@ -15829,7 +16621,7 @@ async function runListVms(context, params) {
15829
16621
  })
15830
16622
  );
15831
16623
  }
15832
- var find_vm_default = task(run159, {
16624
+ var find_vm_default = task(run161, {
15833
16625
  description: "Finds a single VM on an XCP-ng host, optionally allowing multiple matches."
15834
16626
  });
15835
16627
 
@@ -15916,7 +16708,7 @@ async function waitForVmPowerState(context, vmUuid, desiredState, options = {})
15916
16708
  }
15917
16709
 
15918
16710
  // src/core/xcpng/create-template.ts
15919
- async function run160(context) {
16711
+ async function run162(context) {
15920
16712
  const { params, error } = context;
15921
16713
  const {
15922
16714
  source_vm_uuid: sourceVmUuidParam,
@@ -16024,7 +16816,7 @@ async function run160(context) {
16024
16816
  waitAttempts: ensureHalted.attempts
16025
16817
  };
16026
16818
  }
16027
- var create_template_default = task(run160, {
16819
+ var create_template_default = task(run162, {
16028
16820
  description: "Clones a VM and converts it into an XCP-ng template."
16029
16821
  });
16030
16822
 
@@ -16032,7 +16824,7 @@ var create_template_default = task(run160, {
16032
16824
  import { randomUUID } from "crypto";
16033
16825
 
16034
16826
  // src/core/xcpng/create-vm.ts
16035
- async function run161(context) {
16827
+ async function run163(context) {
16036
16828
  const { params, error } = context;
16037
16829
  const {
16038
16830
  name_label,
@@ -16158,12 +16950,12 @@ async function run161(context) {
16158
16950
  appliedCommands
16159
16951
  };
16160
16952
  }
16161
- var create_vm_default = task(run161, {
16953
+ var create_vm_default = task(run163, {
16162
16954
  description: "Creates a new VM on XCP-ng and optionally applies memory and CPU sizing."
16163
16955
  });
16164
16956
 
16165
16957
  // src/core/xcpng/list-vdi-params.ts
16166
- async function run162(context) {
16958
+ async function run164(context) {
16167
16959
  const filters = normalizeFilterArgs(context.params?.filters);
16168
16960
  const result = await runXeCommand(context, "vdi-param-list", filters);
16169
16961
  if (!result.success) {
@@ -16177,12 +16969,12 @@ async function run162(context) {
16177
16969
  items: parseKeyValueOutput(result.stdout)
16178
16970
  };
16179
16971
  }
16180
- var list_vdi_params_default = task(run162, {
16972
+ var list_vdi_params_default = task(run164, {
16181
16973
  description: "Lists virtual disk image parameters (VDI params) on an XCP-ng host."
16182
16974
  });
16183
16975
 
16184
16976
  // src/core/xcpng/list-vdis.ts
16185
- async function run163(context) {
16977
+ async function run165(context) {
16186
16978
  const { params } = context;
16187
16979
  const filters = normalizeFilterArgs(params?.filters);
16188
16980
  const result = await runXeCommand(context, "vdi-list", filters);
@@ -16235,12 +17027,12 @@ async function run163(context) {
16235
17027
  items: enrichedItems
16236
17028
  };
16237
17029
  }
16238
- var list_vdis_default = task(run163, {
17030
+ var list_vdis_default = task(run165, {
16239
17031
  description: "Lists VDIs on an XCP-ng host with optional filtering."
16240
17032
  });
16241
17033
 
16242
17034
  // src/core/xcpng/find-vdi.ts
16243
- async function run164(context) {
17035
+ async function run166(context) {
16244
17036
  const params = context.params ?? {};
16245
17037
  const {
16246
17038
  name_label: nameLabel,
@@ -16346,12 +17138,12 @@ function buildMultipleMessage7(nameLabel, uuid, srUuid, count) {
16346
17138
  const detail = identifiers.length > 0 ? identifiers.join(", ") : "specified criteria";
16347
17139
  return `Multiple VDIs (${count}) matched ${detail}; refine filters or set allow_multiple:true.`;
16348
17140
  }
16349
- var find_vdi_default = task(run164, {
17141
+ var find_vdi_default = task(run166, {
16350
17142
  description: "Finds a single VDI on an XCP-ng host, optionally allowing multiple matches."
16351
17143
  });
16352
17144
 
16353
17145
  // src/core/xcpng/list-vbd-params.ts
16354
- async function run165(context) {
17146
+ async function run167(context) {
16355
17147
  const filters = normalizeFilterArgs(context.params?.filters);
16356
17148
  const result = await runXeCommand(context, "vbd-param-list", filters);
16357
17149
  if (!result.success) {
@@ -16365,12 +17157,12 @@ async function run165(context) {
16365
17157
  items: parseKeyValueOutput(result.stdout)
16366
17158
  };
16367
17159
  }
16368
- var list_vbd_params_default = task(run165, {
17160
+ var list_vbd_params_default = task(run167, {
16369
17161
  description: "Lists virtual block devices (VBDs) on an XCP-ng host."
16370
17162
  });
16371
17163
 
16372
17164
  // src/core/xcpng/list-vbds.ts
16373
- async function run166(context) {
17165
+ async function run168(context) {
16374
17166
  const filters = normalizeFilterArgs(context.params?.filters);
16375
17167
  const result = await runXeCommand(context, "vbd-list", filters);
16376
17168
  if (!result.success) {
@@ -16422,12 +17214,12 @@ async function run166(context) {
16422
17214
  items: enrichedItems
16423
17215
  };
16424
17216
  }
16425
- var list_vbds_default = task(run166, {
17217
+ var list_vbds_default = task(run168, {
16426
17218
  description: "Lists virtual block devices (VBDs) on an XCP-ng host."
16427
17219
  });
16428
17220
 
16429
17221
  // src/core/xcpng/list-attached-disks.ts
16430
- async function run167(context) {
17222
+ async function run169(context) {
16431
17223
  const { params, error } = context;
16432
17224
  const { vm_uuid: vmUuid, include_readonly: rawIncludeReadonly } = params ?? {};
16433
17225
  if (!vmUuid) {
@@ -16523,12 +17315,12 @@ async function run167(context) {
16523
17315
  disks
16524
17316
  };
16525
17317
  }
16526
- var list_attached_disks_default = task(run167, {
17318
+ var list_attached_disks_default = task(run169, {
16527
17319
  description: "Lists VBDs attached to a VM and enriches them with VDI metadata so disks vs CD drives can be distinguished."
16528
17320
  });
16529
17321
 
16530
17322
  // src/core/xcpng/remove-disk.ts
16531
- async function run168(context) {
17323
+ async function run170(context) {
16532
17324
  const { params, error } = context;
16533
17325
  const {
16534
17326
  vbd_uuid: vbdUuidParam,
@@ -16716,12 +17508,12 @@ async function waitForVdiRemoval(context, vdiUuid, timeoutMs) {
16716
17508
  await new Promise((resolve) => setTimeout(resolve, 1e3));
16717
17509
  }
16718
17510
  }
16719
- var remove_disk_default = task(run168, {
17511
+ var remove_disk_default = task(run170, {
16720
17512
  description: "Detaches a VDI from a VM and optionally destroys the backing disk on XCP-ng."
16721
17513
  });
16722
17514
 
16723
17515
  // src/core/xcpng/set-boot-order.ts
16724
- async function run169(context) {
17516
+ async function run171(context) {
16725
17517
  const { params, error } = context;
16726
17518
  const { vm_uuid, boot_order, firmware } = params;
16727
17519
  if (!vm_uuid) {
@@ -16785,7 +17577,7 @@ async function run169(context) {
16785
17577
  appliedCommands
16786
17578
  };
16787
17579
  }
16788
- var set_boot_order_default = task(run169, {
17580
+ var set_boot_order_default = task(run171, {
16789
17581
  description: "Configures VM boot order and optional firmware mode via xe vm-param-set."
16790
17582
  });
16791
17583
 
@@ -16799,7 +17591,7 @@ var OTHER_CONFIG_KEYS_TO_REMOVE = [
16799
17591
  "cloud-init-hostname",
16800
17592
  "cloud-init-instance-id"
16801
17593
  ];
16802
- async function run170(context) {
17594
+ async function run172(context) {
16803
17595
  if (!context.host) {
16804
17596
  const message = "core.xcpng.create-template-from-vdi must run against a remote XCP-ng host.";
16805
17597
  return {
@@ -17332,7 +18124,7 @@ async function run170(context) {
17332
18124
  steps
17333
18125
  };
17334
18126
  }
17335
- var create_template_from_vdi_default = task(run170, {
18127
+ var create_template_from_vdi_default = task(run172, {
17336
18128
  description: "Creates an XCP-ng template from an existing VDI by staging a VM and converting it."
17337
18129
  });
17338
18130
  function parseKeyValueList(input) {
@@ -17432,7 +18224,7 @@ function buildOtherConfigUpdates(baseOtherConfig, macSeed) {
17432
18224
  }
17433
18225
 
17434
18226
  // src/core/xcpng/create-network.ts
17435
- async function run171(context) {
18227
+ async function run173(context) {
17436
18228
  const { params, error } = context;
17437
18229
  const {
17438
18230
  name_label: nameLabel,
@@ -17504,7 +18296,7 @@ async function run171(context) {
17504
18296
  appliedCommands
17505
18297
  };
17506
18298
  }
17507
- var create_network_default = task(run171, {
18299
+ var create_network_default = task(run173, {
17508
18300
  description: "Creates a new network on an XCP-ng host (bridge, MTU, and tags optional)."
17509
18301
  });
17510
18302
 
@@ -17515,7 +18307,7 @@ import { posix as pathPosix } from "path";
17515
18307
 
17516
18308
  // src/core/xcpng/find-or-create-iso-sr.ts
17517
18309
  var DEFAULT_ISO_SR_PATH = "/var/opt/xen/iso-sr";
17518
- async function run172(context) {
18310
+ async function run174(context) {
17519
18311
  const { params, debug, error: logError2 } = context;
17520
18312
  const {
17521
18313
  name_label: nameLabel,
@@ -17667,7 +18459,7 @@ async function runDirCreate(context, params) {
17667
18459
  })
17668
18460
  );
17669
18461
  }
17670
- var find_or_create_iso_sr_default = task(run172, {
18462
+ var find_or_create_iso_sr_default = task(run174, {
17671
18463
  description: "Finds an ISO storage repository by name, creating it if missing using xe sr-create."
17672
18464
  });
17673
18465
 
@@ -17675,7 +18467,7 @@ var find_or_create_iso_sr_default = task(run172, {
17675
18467
  var DEFAULT_SR_NAME = "hostctl-config-drives";
17676
18468
  var DEFAULT_SR_LOCATION = "/var/opt/xen/hostctl-config-drives";
17677
18469
  var DEFAULT_VOLUME_ID = "CIDATA";
17678
- async function run173(context) {
18470
+ async function run175(context) {
17679
18471
  if (!context.host) {
17680
18472
  return {
17681
18473
  success: false,
@@ -18208,12 +19000,12 @@ function decodeBase64Field(field, value) {
18208
19000
  };
18209
19001
  }
18210
19002
  }
18211
- var create_config_drive_default = task(run173, {
19003
+ var create_config_drive_default = task(run175, {
18212
19004
  description: "Generates a NoCloud config-drive ISO, stores it in an ISO SR, and returns the associated VDI."
18213
19005
  });
18214
19006
 
18215
19007
  // src/core/xcpng/convert-template-to-vm.ts
18216
- async function run174(context) {
19008
+ async function run176(context) {
18217
19009
  const { params, error } = context;
18218
19010
  const {
18219
19011
  template_uuid: templateUuidParam,
@@ -18312,12 +19104,12 @@ async function run174(context) {
18312
19104
  alreadyVm
18313
19105
  };
18314
19106
  }
18315
- var convert_template_to_vm_default = task(run174, {
19107
+ var convert_template_to_vm_default = task(run176, {
18316
19108
  description: "Converts an XCP-ng template into a VM by clearing the template flag and optionally renaming it."
18317
19109
  });
18318
19110
 
18319
19111
  // src/core/xcpng/destroy-iso-sr.ts
18320
- async function run175(context) {
19112
+ async function run177(context) {
18321
19113
  const { params, error } = context;
18322
19114
  const {
18323
19115
  sr_uuid: srUuidParam,
@@ -18488,12 +19280,12 @@ async function detachSrPbds(context, srUuid, allowMissing) {
18488
19280
  }
18489
19281
  return { commands };
18490
19282
  }
18491
- var destroy_iso_sr_default = task(run175, {
19283
+ var destroy_iso_sr_default = task(run177, {
18492
19284
  description: "Destroys an ISO storage repository and optionally removes its backing directory."
18493
19285
  });
18494
19286
 
18495
19287
  // src/core/xcpng/destroy-bond.ts
18496
- async function run176(context) {
19288
+ async function run178(context) {
18497
19289
  const { params, error } = context;
18498
19290
  const {
18499
19291
  bond_uuid: bondUuidParam,
@@ -18534,12 +19326,12 @@ async function run176(context) {
18534
19326
  appliedCommands
18535
19327
  };
18536
19328
  }
18537
- var destroy_bond_default = task(run176, {
19329
+ var destroy_bond_default = task(run178, {
18538
19330
  description: "Destroys a bonded interface, wrapping xe bond-destroy."
18539
19331
  });
18540
19332
 
18541
19333
  // src/core/xcpng/create-sr.ts
18542
- async function run177(context) {
19334
+ async function run179(context) {
18543
19335
  const { params, error } = context;
18544
19336
  const {
18545
19337
  name_label: nameLabel,
@@ -18614,12 +19406,12 @@ async function run177(context) {
18614
19406
  appliedCommands
18615
19407
  };
18616
19408
  }
18617
- var create_sr_default = task(run177, {
19409
+ var create_sr_default = task(run179, {
18618
19410
  description: "Creates a new storage repository (SR) with the specified device configuration."
18619
19411
  });
18620
19412
 
18621
19413
  // src/core/xcpng/destroy-sr.ts
18622
- async function run178(context) {
19414
+ async function run180(context) {
18623
19415
  const { params, error } = context;
18624
19416
  const {
18625
19417
  sr_uuid: srUuidParam,
@@ -18688,12 +19480,12 @@ async function run178(context) {
18688
19480
  appliedCommands
18689
19481
  };
18690
19482
  }
18691
- var destroy_sr_default = task(run178, {
19483
+ var destroy_sr_default = task(run180, {
18692
19484
  description: "Destroys a storage repository by UUID or name-label (optionally forcing)."
18693
19485
  });
18694
19486
 
18695
19487
  // src/core/xcpng/destroy-network.ts
18696
- async function run179(context) {
19488
+ async function run181(context) {
18697
19489
  const { params, error } = context;
18698
19490
  const {
18699
19491
  network_uuid: networkUuidParam,
@@ -18760,12 +19552,12 @@ async function run179(context) {
18760
19552
  appliedCommands
18761
19553
  };
18762
19554
  }
18763
- var destroy_network_default = task(run179, {
19555
+ var destroy_network_default = task(run181, {
18764
19556
  description: "Destroys an XCP-ng network by UUID or name-label."
18765
19557
  });
18766
19558
 
18767
19559
  // src/core/xcpng/destroy-pbd.ts
18768
- async function run180(context) {
19560
+ async function run182(context) {
18769
19561
  const { params, error } = context;
18770
19562
  const {
18771
19563
  pbd_uuid: pbdUuidParam,
@@ -18874,12 +19666,12 @@ async function run180(context) {
18874
19666
  appliedCommands
18875
19667
  };
18876
19668
  }
18877
- var destroy_pbd_default = task(run180, {
19669
+ var destroy_pbd_default = task(run182, {
18878
19670
  description: "Destroys a host \u2194 storage repository binding (PBD)."
18879
19671
  });
18880
19672
 
18881
19673
  // src/core/xcpng/destroy-snapshot.ts
18882
- async function run181(context) {
19674
+ async function run183(context) {
18883
19675
  const { params, error } = context;
18884
19676
  const { snapshot_uuid: snapshotUuid } = params ?? {};
18885
19677
  if (!snapshotUuid) {
@@ -18902,12 +19694,12 @@ async function run181(context) {
18902
19694
  command: result.command
18903
19695
  };
18904
19696
  }
18905
- var destroy_snapshot_default = task(run181, {
19697
+ var destroy_snapshot_default = task(run183, {
18906
19698
  description: "Destroys an XCP-ng VM snapshot."
18907
19699
  });
18908
19700
 
18909
19701
  // src/core/xcpng/introduce-sr.ts
18910
- async function run182(context) {
19702
+ async function run184(context) {
18911
19703
  const { params, error } = context;
18912
19704
  const {
18913
19705
  sr_uuid: srUuid,
@@ -18954,12 +19746,12 @@ async function run182(context) {
18954
19746
  appliedCommands
18955
19747
  };
18956
19748
  }
18957
- var introduce_sr_default = task(run182, {
19749
+ var introduce_sr_default = task(run184, {
18958
19750
  description: "Introduces an existing storage repository into the pool."
18959
19751
  });
18960
19752
 
18961
19753
  // src/core/xcpng/forget-sr.ts
18962
- async function run183(context) {
19754
+ async function run185(context) {
18963
19755
  const { params, error } = context;
18964
19756
  const {
18965
19757
  sr_uuid: srUuidParam,
@@ -19026,12 +19818,12 @@ async function run183(context) {
19026
19818
  appliedCommands
19027
19819
  };
19028
19820
  }
19029
- var forget_sr_default = task(run183, {
19821
+ var forget_sr_default = task(run185, {
19030
19822
  description: "Forgets an SR from the pool metadata without destroying the underlying storage."
19031
19823
  });
19032
19824
 
19033
19825
  // src/core/xcpng/list-snapshots.ts
19034
- async function run184(context) {
19826
+ async function run186(context) {
19035
19827
  const filters = normalizeFilterArgs(context.params?.filters);
19036
19828
  const result = await runXeCommand(context, "snapshot-list", filters);
19037
19829
  if (!result.success) {
@@ -19045,12 +19837,12 @@ async function run184(context) {
19045
19837
  items: parseKeyValueOutput(result.stdout)
19046
19838
  };
19047
19839
  }
19048
- var list_snapshots_default = task(run184, {
19840
+ var list_snapshots_default = task(run186, {
19049
19841
  description: "Lists VM snapshots available on the host."
19050
19842
  });
19051
19843
 
19052
19844
  // src/core/xcpng/list-messages.ts
19053
- async function run185(context) {
19845
+ async function run187(context) {
19054
19846
  const filters = normalizeFilterArgs(context.params?.filters);
19055
19847
  const result = await runXeCommand(context, "message-list", filters);
19056
19848
  if (!result.success) {
@@ -19064,12 +19856,12 @@ async function run185(context) {
19064
19856
  items: parseKeyValueOutput(result.stdout)
19065
19857
  };
19066
19858
  }
19067
- var list_messages_default = task(run185, {
19859
+ var list_messages_default = task(run187, {
19068
19860
  description: "Lists messages emitted by the XCP-ng pool."
19069
19861
  });
19070
19862
 
19071
19863
  // src/core/xcpng/clear-messages.ts
19072
- async function run186(context) {
19864
+ async function run188(context) {
19073
19865
  const { params, error } = context;
19074
19866
  const {
19075
19867
  uuid,
@@ -19134,12 +19926,12 @@ async function run186(context) {
19134
19926
  commands
19135
19927
  };
19136
19928
  }
19137
- var clear_messages_default = task(run186, {
19929
+ var clear_messages_default = task(run188, {
19138
19930
  description: "Clears messages (all, by UUID, or UUID prefix)."
19139
19931
  });
19140
19932
 
19141
19933
  // src/core/xcpng/destroy-template.ts
19142
- async function run187(context) {
19934
+ async function run189(context) {
19143
19935
  const { params, error } = context;
19144
19936
  const {
19145
19937
  template_uuid: templateUuidParam,
@@ -19214,12 +20006,12 @@ async function run187(context) {
19214
20006
  command: commandResult.command
19215
20007
  };
19216
20008
  }
19217
- var destroy_template_default = task(run187, {
20009
+ var destroy_template_default = task(run189, {
19218
20010
  description: "Destroys an XCP-ng template by UUID or name-label."
19219
20011
  });
19220
20012
 
19221
20013
  // src/core/xcpng/destroy-vdi.ts
19222
- async function run188(context) {
20014
+ async function run190(context) {
19223
20015
  const { params, error } = context;
19224
20016
  const {
19225
20017
  vdi_uuid: vdiUuidParam,
@@ -19284,12 +20076,12 @@ async function run188(context) {
19284
20076
  command: result.command
19285
20077
  };
19286
20078
  }
19287
- var destroy_vdi_default = task(run188, {
20079
+ var destroy_vdi_default = task(run190, {
19288
20080
  description: "Destroys an XCP-ng VDI by UUID (optionally resolving by name-label)."
19289
20081
  });
19290
20082
 
19291
20083
  // src/core/xcpng/destroy-vm.ts
19292
- async function run189(context) {
20084
+ async function run191(context) {
19293
20085
  const { params, error } = context;
19294
20086
  const {
19295
20087
  vm_uuid: vmUuidParam,
@@ -19454,12 +20246,12 @@ async function run189(context) {
19454
20246
  destroyedVdiUuids
19455
20247
  };
19456
20248
  }
19457
- var destroy_vm_default = task(run189, {
20249
+ var destroy_vm_default = task(run191, {
19458
20250
  description: "Destroys an XCP-ng VM, optionally forcing and pruning snapshots."
19459
20251
  });
19460
20252
 
19461
20253
  // src/core/xcpng/copy-vdi.ts
19462
- async function run190(context) {
20254
+ async function run192(context) {
19463
20255
  const { params, error } = context;
19464
20256
  const {
19465
20257
  source_vdi_uuid: sourceVdiUuidParam,
@@ -19604,12 +20396,12 @@ async function run190(context) {
19604
20396
  appliedCommands
19605
20397
  };
19606
20398
  }
19607
- var copy_vdi_default = task(run190, {
20399
+ var copy_vdi_default = task(run192, {
19608
20400
  description: "Copies an XCP-ng VDI to a destination storage repository and optionally updates its metadata."
19609
20401
  });
19610
20402
 
19611
20403
  // src/core/xcpng/detach-iso.ts
19612
- async function run191(context) {
20404
+ async function run193(context) {
19613
20405
  const { params, error } = context;
19614
20406
  const { vm_uuid: vmUuid, allow_missing: rawAllowMissing } = params;
19615
20407
  if (!vmUuid) {
@@ -19641,12 +20433,12 @@ async function run191(context) {
19641
20433
  error: message
19642
20434
  };
19643
20435
  }
19644
- var detach_iso_default = task(run191, {
20436
+ var detach_iso_default = task(run193, {
19645
20437
  description: "Ejects ISO media from a VM, tolerating empty drives when allow_missing:true."
19646
20438
  });
19647
20439
 
19648
20440
  // src/core/xcpng/detach-vdi.ts
19649
- async function run192(context) {
20441
+ async function run194(context) {
19650
20442
  const { params } = context;
19651
20443
  const {
19652
20444
  vbd_uuid,
@@ -19683,12 +20475,12 @@ async function run192(context) {
19683
20475
  error: result.error
19684
20476
  };
19685
20477
  }
19686
- var detach_vdi_default = task(run192, {
20478
+ var detach_vdi_default = task(run194, {
19687
20479
  description: "Detaches a VDI from a VM by unplugging and optionally destroying the VBD, leaving the VDI intact by default."
19688
20480
  });
19689
20481
 
19690
20482
  // src/core/xcpng/detach-network-interface.ts
19691
- async function run193(context) {
20483
+ async function run195(context) {
19692
20484
  const { params, error } = context;
19693
20485
  const {
19694
20486
  vif_uuid: vifUuidParam,
@@ -19782,12 +20574,12 @@ async function run193(context) {
19782
20574
  appliedCommands
19783
20575
  };
19784
20576
  }
19785
- var detach_network_interface_default = task(run193, {
20577
+ var detach_network_interface_default = task(run195, {
19786
20578
  description: "Unplugs (and optionally destroys) a virtual network interface from an XCP-ng VM."
19787
20579
  });
19788
20580
 
19789
20581
  // src/core/xcpng/enable-host.ts
19790
- async function run194(context) {
20582
+ async function run196(context) {
19791
20583
  const { params, error } = context;
19792
20584
  const {
19793
20585
  host_uuid: hostUuidParam,
@@ -19855,12 +20647,12 @@ async function run194(context) {
19855
20647
  appliedCommands
19856
20648
  };
19857
20649
  }
19858
- var enable_host_default = task(run194, {
20650
+ var enable_host_default = task(run196, {
19859
20651
  description: "Enables maintenance-disabled hosts so they rejoin scheduling."
19860
20652
  });
19861
20653
 
19862
20654
  // src/core/xcpng/disable-host.ts
19863
- async function run195(context) {
20655
+ async function run197(context) {
19864
20656
  const { params, error } = context;
19865
20657
  const {
19866
20658
  host_uuid: hostUuidParam,
@@ -19945,12 +20737,12 @@ async function run195(context) {
19945
20737
  evacuated: evacuate
19946
20738
  };
19947
20739
  }
19948
- var disable_host_default = task(run195, {
20740
+ var disable_host_default = task(run197, {
19949
20741
  description: "Disables a host (optionally evacuating resident VMs first)."
19950
20742
  });
19951
20743
 
19952
20744
  // src/core/xcpng/plug-pbd.ts
19953
- async function run196(context) {
20745
+ async function run198(context) {
19954
20746
  const { params, error } = context;
19955
20747
  const {
19956
20748
  pbd_uuid: pbdUuidParam,
@@ -20019,12 +20811,12 @@ async function run196(context) {
20019
20811
  appliedCommands
20020
20812
  };
20021
20813
  }
20022
- var plug_pbd_default = task(run196, {
20814
+ var plug_pbd_default = task(run198, {
20023
20815
  description: "Plugs a PBD so the host reattaches the storage repository."
20024
20816
  });
20025
20817
 
20026
20818
  // src/core/xcpng/unplug-pbd.ts
20027
- async function run197(context) {
20819
+ async function run199(context) {
20028
20820
  const { params, error } = context;
20029
20821
  const {
20030
20822
  pbd_uuid: pbdUuidParam,
@@ -20093,12 +20885,12 @@ async function run197(context) {
20093
20885
  appliedCommands
20094
20886
  };
20095
20887
  }
20096
- var unplug_pbd_default = task(run197, {
20888
+ var unplug_pbd_default = task(run199, {
20097
20889
  description: "Unplugs a PBD so the host detaches the storage repository."
20098
20890
  });
20099
20891
 
20100
20892
  // src/core/xcpng/list-pools.ts
20101
- async function run198(context) {
20893
+ async function run200(context) {
20102
20894
  const filters = normalizeFilterArgs(context.params?.filters);
20103
20895
  const result = await runXeCommand(context, "pool-list", filters);
20104
20896
  if (!result.success) {
@@ -20112,12 +20904,12 @@ async function run198(context) {
20112
20904
  items: parseKeyValueOutput(result.stdout)
20113
20905
  };
20114
20906
  }
20115
- var list_pools_default = task(run198, {
20907
+ var list_pools_default = task(run200, {
20116
20908
  description: "Lists pools available to the current host."
20117
20909
  });
20118
20910
 
20119
20911
  // src/core/xcpng/find-pool.ts
20120
- async function run199(context) {
20912
+ async function run201(context) {
20121
20913
  const params = context.params ?? {};
20122
20914
  const {
20123
20915
  uuid,
@@ -20217,12 +21009,12 @@ async function runListPools(context, params) {
20217
21009
  })
20218
21010
  );
20219
21011
  }
20220
- var find_pool_default = task(run199, {
21012
+ var find_pool_default = task(run201, {
20221
21013
  description: "Finds a single pool by UUID or name-label, optionally allowing multiple matches."
20222
21014
  });
20223
21015
 
20224
21016
  // src/core/xcpng/set-pool-param.ts
20225
- async function run200(context) {
21017
+ async function run202(context) {
20226
21018
  const { params, error } = context;
20227
21019
  const {
20228
21020
  pool_uuid: poolUuidParam,
@@ -20288,12 +21080,12 @@ async function run200(context) {
20288
21080
  appliedCommands
20289
21081
  };
20290
21082
  }
20291
- var set_pool_param_default = task(run200, {
21083
+ var set_pool_param_default = task(run202, {
20292
21084
  description: "Updates a pool parameter (wraps xe pool-param-set)."
20293
21085
  });
20294
21086
 
20295
21087
  // src/core/xcpng/reboot-host.ts
20296
- async function run201(context) {
21088
+ async function run203(context) {
20297
21089
  const { params, error } = context;
20298
21090
  const {
20299
21091
  host_uuid: hostUuidParam,
@@ -20354,12 +21146,12 @@ async function run201(context) {
20354
21146
  command: commandResult.command
20355
21147
  };
20356
21148
  }
20357
- var reboot_host_default = task(run201, {
21149
+ var reboot_host_default = task(run203, {
20358
21150
  description: "Reboots an XCP-ng host (optionally forcing)."
20359
21151
  });
20360
21152
 
20361
21153
  // src/core/xcpng/shutdown-host.ts
20362
- async function run202(context) {
21154
+ async function run204(context) {
20363
21155
  const { params, error } = context;
20364
21156
  const {
20365
21157
  host_uuid: hostUuidParam,
@@ -20418,12 +21210,12 @@ async function run202(context) {
20418
21210
  command: commandResult.command
20419
21211
  };
20420
21212
  }
20421
- var shutdown_host_default = task(run202, {
21213
+ var shutdown_host_default = task(run204, {
20422
21214
  description: "Shuts down an XCP-ng host (optionally forcing)."
20423
21215
  });
20424
21216
 
20425
21217
  // src/core/xcpng/evacuate-host.ts
20426
- async function run203(context) {
21218
+ async function run205(context) {
20427
21219
  const { params, error } = context;
20428
21220
  const {
20429
21221
  host_uuid: hostUuidParam,
@@ -20480,12 +21272,12 @@ async function run203(context) {
20480
21272
  command: commandResult.command
20481
21273
  };
20482
21274
  }
20483
- var evacuate_host_default = task(run203, {
21275
+ var evacuate_host_default = task(run205, {
20484
21276
  description: "Evacuates all VMs from a host."
20485
21277
  });
20486
21278
 
20487
21279
  // src/core/xcpng/plug-pif.ts
20488
- async function run204(context) {
21280
+ async function run206(context) {
20489
21281
  const { params, error } = context;
20490
21282
  const {
20491
21283
  pif_uuid: pifUuidParam,
@@ -20582,12 +21374,12 @@ async function run204(context) {
20582
21374
  appliedCommands
20583
21375
  };
20584
21376
  }
20585
- var plug_pif_default = task(run204, {
21377
+ var plug_pif_default = task(run206, {
20586
21378
  description: "Plugs a physical interface (PIF) on the specified host."
20587
21379
  });
20588
21380
 
20589
21381
  // src/core/xcpng/pif-scan.ts
20590
- async function run205(context) {
21382
+ async function run207(context) {
20591
21383
  const { params, error } = context;
20592
21384
  const {
20593
21385
  host_uuid: hostUuidParam,
@@ -20656,12 +21448,12 @@ async function run205(context) {
20656
21448
  appliedCommands
20657
21449
  };
20658
21450
  }
20659
- var pif_scan_default = task(run205, {
21451
+ var pif_scan_default = task(run207, {
20660
21452
  description: "Rescans physical interfaces (PIFs) on a host to discover changes."
20661
21453
  });
20662
21454
 
20663
21455
  // src/core/xcpng/unplug-pif.ts
20664
- async function run206(context) {
21456
+ async function run208(context) {
20665
21457
  const { params, error } = context;
20666
21458
  const {
20667
21459
  pif_uuid: pifUuidParam,
@@ -20758,12 +21550,12 @@ async function run206(context) {
20758
21550
  appliedCommands
20759
21551
  };
20760
21552
  }
20761
- var unplug_pif_default = task(run206, {
21553
+ var unplug_pif_default = task(run208, {
20762
21554
  description: "Unplugs a physical interface (PIF) on the specified host."
20763
21555
  });
20764
21556
 
20765
21557
  // src/core/xcpng/set-pif-param.ts
20766
- async function run207(context) {
21558
+ async function run209(context) {
20767
21559
  const { params, error } = context;
20768
21560
  const { pif_uuid: pifUuid, key, value } = params ?? {};
20769
21561
  if (!pifUuid) {
@@ -20801,12 +21593,12 @@ async function run207(context) {
20801
21593
  command: commandResult.command
20802
21594
  };
20803
21595
  }
20804
- var set_pif_param_default = task(run207, {
21596
+ var set_pif_param_default = task(run209, {
20805
21597
  description: "Updates a PIF parameter (wraps `xe pif-param-set`)."
20806
21598
  });
20807
21599
 
20808
21600
  // src/core/xcpng/unplug-vbd.ts
20809
- async function run208(context) {
21601
+ async function run210(context) {
20810
21602
  const { params, error } = context;
20811
21603
  const { vbd_uuid: vbdUuid, allow_missing: rawAllowMissing } = params;
20812
21604
  if (!vbdUuid) {
@@ -20836,12 +21628,12 @@ async function run208(context) {
20836
21628
  error: message
20837
21629
  };
20838
21630
  }
20839
- var unplug_vbd_default = task(run208, {
21631
+ var unplug_vbd_default = task(run210, {
20840
21632
  description: "Unplugs a VBD from an XCP-ng VM, tolerating already-detached devices when allow_missing:true."
20841
21633
  });
20842
21634
 
20843
21635
  // src/core/xcpng/suspend-vm.ts
20844
- async function run209(context) {
21636
+ async function run211(context) {
20845
21637
  const { params, error } = context;
20846
21638
  const { vm_uuid: vmUuid, allow_running: rawAllowRunning } = params;
20847
21639
  if (!vmUuid) {
@@ -20902,12 +21694,12 @@ async function run209(context) {
20902
21694
  waitAttempts: waitResult.attempts
20903
21695
  };
20904
21696
  }
20905
- var suspend_vm_default = task(run209, {
21697
+ var suspend_vm_default = task(run211, {
20906
21698
  description: "Suspends an XCP-ng VM, waiting until the VM reports the suspended power state."
20907
21699
  });
20908
21700
 
20909
21701
  // src/core/xcpng/resume-vm.ts
20910
- async function run210(context) {
21702
+ async function run212(context) {
20911
21703
  const { params, error } = context;
20912
21704
  const { vm_uuid: vmUuid, start_paused: rawStartPaused, host_uuid: hostUuid } = params;
20913
21705
  if (!vmUuid) {
@@ -20972,12 +21764,12 @@ async function run210(context) {
20972
21764
  waitAttempts: waitResult.attempts
20973
21765
  };
20974
21766
  }
20975
- var resume_vm_default = task(run210, {
21767
+ var resume_vm_default = task(run212, {
20976
21768
  description: "Resumes a suspended XCP-ng VM, optionally starting it in a paused state or on a specific host."
20977
21769
  });
20978
21770
 
20979
21771
  // src/core/xcpng/list-vif-params.ts
20980
- async function run211(context) {
21772
+ async function run213(context) {
20981
21773
  const filters = normalizeFilterArgs(context.params?.filters);
20982
21774
  const result = await runXeCommand(context, "vif-param-list", filters);
20983
21775
  if (!result.success) {
@@ -20991,12 +21783,12 @@ async function run211(context) {
20991
21783
  items: parseKeyValueOutput(result.stdout)
20992
21784
  };
20993
21785
  }
20994
- var list_vif_params_default = task(run211, {
21786
+ var list_vif_params_default = task(run213, {
20995
21787
  description: "Lists parameters for virtual interfaces (VIFs) on an XCP-ng host."
20996
21788
  });
20997
21789
 
20998
21790
  // src/core/xcpng/list-vifs.ts
20999
- async function run212(context) {
21791
+ async function run214(context) {
21000
21792
  const filters = normalizeFilterArgs(context.params?.filters);
21001
21793
  const result = await runXeCommand(context, "vif-list", filters);
21002
21794
  if (!result.success) {
@@ -21046,12 +21838,12 @@ async function run212(context) {
21046
21838
  items: enrichedItems
21047
21839
  };
21048
21840
  }
21049
- var list_vifs_default = task(run212, {
21841
+ var list_vifs_default = task(run214, {
21050
21842
  description: "Lists VIFs (virtual interfaces) attached to VMs."
21051
21843
  });
21052
21844
 
21053
21845
  // src/core/xcpng/list-pif-params.ts
21054
- async function run213(context) {
21846
+ async function run215(context) {
21055
21847
  const filters = normalizeFilterArgs(context.params?.filters);
21056
21848
  const result = await runXeCommand(context, "pif-param-list", filters);
21057
21849
  if (!result.success) {
@@ -21065,12 +21857,12 @@ async function run213(context) {
21065
21857
  items: parseKeyValueOutput(result.stdout)
21066
21858
  };
21067
21859
  }
21068
- var list_pif_params_default = task(run213, {
21860
+ var list_pif_params_default = task(run215, {
21069
21861
  description: "Lists parameters for PIFs on an XCP-ng host."
21070
21862
  });
21071
21863
 
21072
21864
  // src/core/xcpng/list-pifs.ts
21073
- async function run214(context) {
21865
+ async function run216(context) {
21074
21866
  const filters = normalizeFilterArgs(context.params?.filters);
21075
21867
  const result = await runXeCommand(context, "pif-list", filters);
21076
21868
  if (!result.success) {
@@ -21120,12 +21912,12 @@ async function run214(context) {
21120
21912
  items: enrichedItems
21121
21913
  };
21122
21914
  }
21123
- var list_pifs_default = task(run214, {
21915
+ var list_pifs_default = task(run216, {
21124
21916
  description: "Lists PIFs (physical interfaces) available on the XCP-ng host."
21125
21917
  });
21126
21918
 
21127
21919
  // src/core/xcpng/reboot-vm.ts
21128
- async function run215(context) {
21920
+ async function run217(context) {
21129
21921
  const { params, error } = context;
21130
21922
  const { vm_uuid: vmUuidParam, vm_name_label: vmNameLabel, force: rawForce } = params ?? {};
21131
21923
  const force = coerceBoolean(rawForce, false);
@@ -21186,12 +21978,12 @@ async function run215(context) {
21186
21978
  waitAttempts: waitResult.attempts
21187
21979
  };
21188
21980
  }
21189
- var reboot_vm_default = task(run215, {
21981
+ var reboot_vm_default = task(run217, {
21190
21982
  description: "Reboots an XCP-ng VM using `xe vm-reboot`."
21191
21983
  });
21192
21984
 
21193
21985
  // src/core/xcpng/set-network-param.ts
21194
- async function run216(context) {
21986
+ async function run218(context) {
21195
21987
  const { params, error } = context;
21196
21988
  const {
21197
21989
  network_uuid: networkUuidParam,
@@ -21257,12 +22049,12 @@ async function run216(context) {
21257
22049
  appliedCommands
21258
22050
  };
21259
22051
  }
21260
- var set_network_param_default = task(run216, {
22052
+ var set_network_param_default = task(run218, {
21261
22053
  description: "Updates a network parameter (wraps xe network-param-set)."
21262
22054
  });
21263
22055
 
21264
22056
  // src/core/xcpng/resize-vdi.ts
21265
- async function run217(context) {
22057
+ async function run219(context) {
21266
22058
  const { params, error } = context;
21267
22059
  const {
21268
22060
  vdi_uuid: vdiUuidParam,
@@ -21336,12 +22128,12 @@ async function run217(context) {
21336
22128
  newSizeBytes: sizeBytes
21337
22129
  };
21338
22130
  }
21339
- var resize_vdi_default = task(run217, {
22131
+ var resize_vdi_default = task(run219, {
21340
22132
  description: "Resizes an existing VDI on XCP-ng using `xe vdi-resize`/`vdi-resize-online`."
21341
22133
  });
21342
22134
 
21343
22135
  // src/core/xcpng/set-vm-resources.ts
21344
- async function run218(context) {
22136
+ async function run220(context) {
21345
22137
  const { params, error } = context;
21346
22138
  const {
21347
22139
  vm_uuid: vmUuidParam,
@@ -21644,12 +22436,12 @@ function ensurePositiveMib(value, fieldName) {
21644
22436
  bytes: mibToBytes2(value)
21645
22437
  };
21646
22438
  }
21647
- var set_vm_resources_default = task(run218, {
22439
+ var set_vm_resources_default = task(run220, {
21648
22440
  description: "Updates VM memory and vCPU settings on an XCP-ng host."
21649
22441
  });
21650
22442
 
21651
22443
  // src/core/xcpng/resize-vm-cpus.ts
21652
- async function run219(context) {
22444
+ async function run221(context) {
21653
22445
  const { params, error } = context;
21654
22446
  const {
21655
22447
  vm_uuid: vmUuid,
@@ -21698,12 +22490,12 @@ async function run219(context) {
21698
22490
  waitAttempts: result.waitAttempts
21699
22491
  };
21700
22492
  }
21701
- var resize_vm_cpus_default = task(run219, {
22493
+ var resize_vm_cpus_default = task(run221, {
21702
22494
  description: "Resizes an XCP-ng VM\u2019s vCPU configuration."
21703
22495
  });
21704
22496
 
21705
22497
  // src/core/xcpng/resize-vm-memory.ts
21706
- async function run220(context) {
22498
+ async function run222(context) {
21707
22499
  const { params, error } = context;
21708
22500
  const { vm_uuid: vmUuid, vm_name_label: vmNameLabel, memory_mib: memoryMib } = params ?? {};
21709
22501
  if (!memoryMib || !Number.isFinite(memoryMib) || memoryMib <= 0) {
@@ -21742,12 +22534,12 @@ async function run220(context) {
21742
22534
  waitAttempts: result.waitAttempts
21743
22535
  };
21744
22536
  }
21745
- var resize_vm_memory_default = task(run220, {
22537
+ var resize_vm_memory_default = task(run222, {
21746
22538
  description: "Resizes an XCP-ng VM\u2019s memory allocation (static/dynamic bounds)."
21747
22539
  });
21748
22540
 
21749
22541
  // src/core/xcpng/revert-snapshot.ts
21750
- async function run221(context) {
22542
+ async function run223(context) {
21751
22543
  const { params, error } = context;
21752
22544
  const { snapshot_uuid: snapshotUuid } = params ?? {};
21753
22545
  if (!snapshotUuid) {
@@ -21836,12 +22628,12 @@ async function run221(context) {
21836
22628
  waitAttempts
21837
22629
  };
21838
22630
  }
21839
- var revert_snapshot_default = task(run221, {
22631
+ var revert_snapshot_default = task(run223, {
21840
22632
  description: "Reverts an XCP-ng VM to a specified snapshot."
21841
22633
  });
21842
22634
 
21843
22635
  // src/core/xcpng/set-snapshot-param.ts
21844
- async function run222(context) {
22636
+ async function run224(context) {
21845
22637
  const { params, error } = context;
21846
22638
  const { snapshot_uuid: snapshotUuid, key, value } = params ?? {};
21847
22639
  if (!snapshotUuid) {
@@ -21879,12 +22671,12 @@ async function run222(context) {
21879
22671
  command: commandResult.command
21880
22672
  };
21881
22673
  }
21882
- var set_snapshot_param_default = task(run222, {
22674
+ var set_snapshot_param_default = task(run224, {
21883
22675
  description: "Updates a snapshot parameter (wraps xe snapshot-param-set)."
21884
22676
  });
21885
22677
 
21886
22678
  // src/core/xcpng/set-sr-param.ts
21887
- async function run223(context) {
22679
+ async function run225(context) {
21888
22680
  const { params, error } = context;
21889
22681
  const {
21890
22682
  sr_uuid: srUuidParam,
@@ -21950,12 +22742,12 @@ async function run223(context) {
21950
22742
  appliedCommands
21951
22743
  };
21952
22744
  }
21953
- var set_sr_param_default = task(run223, {
22745
+ var set_sr_param_default = task(run225, {
21954
22746
  description: "Updates a storage repository parameter (wraps xe sr-param-set)."
21955
22747
  });
21956
22748
 
21957
22749
  // src/core/xcpng/start-vm.ts
21958
- async function run224(context) {
22750
+ async function run226(context) {
21959
22751
  const { params, error } = context;
21960
22752
  const { vm_uuid, start_paused: rawStartPaused, force: rawForce } = params;
21961
22753
  const startPaused = coerceBoolean(rawStartPaused, false);
@@ -22022,12 +22814,12 @@ async function run224(context) {
22022
22814
  waitAttempts: waitResult.attempts
22023
22815
  };
22024
22816
  }
22025
- var start_vm_default = task(run224, {
22817
+ var start_vm_default = task(run226, {
22026
22818
  description: "Starts an XCP-ng virtual machine with optional paused or forced modes."
22027
22819
  });
22028
22820
 
22029
22821
  // src/core/xcpng/stop-vm.ts
22030
- async function run225(context) {
22822
+ async function run227(context) {
22031
22823
  const { params, error } = context;
22032
22824
  const { vm_uuid, force: rawForce, timeout_seconds: rawTimeout } = params;
22033
22825
  const force = coerceBoolean(rawForce, false);
@@ -22102,14 +22894,14 @@ async function run225(context) {
22102
22894
  waitAttempts: waitResult.attempts
22103
22895
  };
22104
22896
  }
22105
- var stop_vm_default = task(run225, {
22897
+ var stop_vm_default = task(run227, {
22106
22898
  description: "Stops an XCP-ng virtual machine gracefully or forcefully."
22107
22899
  });
22108
22900
 
22109
22901
  // src/core/xcpng/import-iso.ts
22110
22902
  import { posix as pathPosix2 } from "path";
22111
22903
  var DEFAULT_ISO_SR_PATH2 = "/var/opt/xen/iso-sr";
22112
- async function run226(context) {
22904
+ async function run228(context) {
22113
22905
  if (!context.host) {
22114
22906
  return {
22115
22907
  success: false,
@@ -22315,7 +23107,7 @@ async function findIsoVdi2(context, srUuid, isoFileName) {
22315
23107
  }
22316
23108
  return { vdi };
22317
23109
  }
22318
- var import_iso_default = task(run226, {
23110
+ var import_iso_default = task(run228, {
22319
23111
  description: "Ensures an ISO file is represented as a VDI in an ISO SR by rescanning and importing when necessary."
22320
23112
  });
22321
23113
 
@@ -22323,7 +23115,7 @@ var import_iso_default = task(run226, {
22323
23115
  import { basename, posix as pathPosix3 } from "path";
22324
23116
  import { createReadStream, promises as fs10 } from "fs";
22325
23117
  var DEFAULT_ISO_SR_PATH3 = "/var/opt/xen/iso-sr";
22326
- async function run227(context) {
23118
+ async function run229(context) {
22327
23119
  if (context.host) {
22328
23120
  return {
22329
23121
  success: false,
@@ -22376,10 +23168,10 @@ async function run227(context) {
22376
23168
  }
22377
23169
  let overallSuccess = true;
22378
23170
  const uploads = await context.ssh([], async (remoteContext) => {
22379
- const { run: run245 } = remoteContext;
23171
+ const { run: run247 } = remoteContext;
22380
23172
  const remotePath = pathPosix3.join(resolvedLocation, remoteFileName);
22381
23173
  try {
22382
- const srResult = await run245(find_or_create_iso_sr_default({
23174
+ const srResult = await run247(find_or_create_iso_sr_default({
22383
23175
  name_label: isoSrName,
22384
23176
  location: resolvedLocation,
22385
23177
  location_owner: locationOwner,
@@ -22394,7 +23186,7 @@ async function run227(context) {
22394
23186
  error: srResult.error ?? "Failed to ensure ISO SR exists."
22395
23187
  };
22396
23188
  }
22397
- const fileExistsResult = await run245(exists_default2({ path: remotePath }));
23189
+ const fileExistsResult = await run247(exists_default2({ path: remotePath }));
22398
23190
  if (fileExistsResult.exists) {
22399
23191
  return {
22400
23192
  success: true,
@@ -22460,7 +23252,7 @@ function resolveChunkSizeBytes(chunkSizeMb) {
22460
23252
  const bounded = Math.min(Math.max(safeSize, MIN_CHUNK_SIZE_MB), MAX_CHUNK_SIZE_MB);
22461
23253
  return bounded * 1024 * 1024;
22462
23254
  }
22463
- var upload_iso_default = task(run227, {
23255
+ var upload_iso_default = task(run229, {
22464
23256
  description: "Uploads a local ISO to the remote XCP-ng hypervisor, ensuring the target ISO SR exists beforehand."
22465
23257
  });
22466
23258
 
@@ -22479,7 +23271,7 @@ function parseMapValue(raw) {
22479
23271
  return acc;
22480
23272
  }, {});
22481
23273
  }
22482
- async function run228(context) {
23274
+ async function run230(context) {
22483
23275
  const { params, error } = context;
22484
23276
  const {
22485
23277
  vm_uuid: vmUuidParam,
@@ -22617,12 +23409,12 @@ async function run228(context) {
22617
23409
  }
22618
23410
  return result;
22619
23411
  }
22620
- var get_vm_info_default = task(run228, {
23412
+ var get_vm_info_default = task(run230, {
22621
23413
  description: "Returns structured VM details (platform, boot configuration, memory/CPU sizing, and optional VBD/VIF inventory)."
22622
23414
  });
22623
23415
 
22624
23416
  // src/core/xcpng/export-vdi.ts
22625
- async function run229(context) {
23417
+ async function run231(context) {
22626
23418
  const { params, error } = context;
22627
23419
  const {
22628
23420
  vdi_uuid: vdiUuidParam,
@@ -22702,12 +23494,12 @@ async function run229(context) {
22702
23494
  appliedCommands
22703
23495
  };
22704
23496
  }
22705
- var export_vdi_default = task(run229, {
23497
+ var export_vdi_default = task(run231, {
22706
23498
  description: "Exports a VDI to the hypervisor filesystem via xe vdi-export."
22707
23499
  });
22708
23500
 
22709
23501
  // src/core/xcpng/provision-vm-from-iso.ts
22710
- async function run230(context) {
23502
+ async function run232(context) {
22711
23503
  if (!context.host) {
22712
23504
  return {
22713
23505
  success: false,
@@ -23034,7 +23826,7 @@ async function run230(context) {
23034
23826
  steps
23035
23827
  };
23036
23828
  }
23037
- var provision_vm_from_iso_default = task(run230, {
23829
+ var provision_vm_from_iso_default = task(run232, {
23038
23830
  description: "Creates a VM from a template, attaches storage, network, and ISO media, and optionally boots it for installation."
23039
23831
  });
23040
23832
 
@@ -24007,7 +24799,7 @@ function resolveMemoryMib(input) {
24007
24799
  }
24008
24800
  return { value: Math.floor(value) };
24009
24801
  }
24010
- async function run231(context) {
24802
+ async function run233(context) {
24011
24803
  if (!context.host) {
24012
24804
  return runLocal(context);
24013
24805
  }
@@ -24236,7 +25028,7 @@ function buildLocalFailure(step, message) {
24236
25028
  error: message
24237
25029
  };
24238
25030
  }
24239
- var provision_vm_default = task(run231, {
25031
+ var provision_vm_default = task(run233, {
24240
25032
  description: "Provisions a VM from an XCP-ng template by cloning its root disk, configuring cloud-init metadata, and attaching network resources."
24241
25033
  });
24242
25034
  function delay(ms) {
@@ -24286,7 +25078,7 @@ function parseNumber2(value) {
24286
25078
  }
24287
25079
 
24288
25080
  // src/core/xcpng/snapshot-vm.ts
24289
- async function run232(context) {
25081
+ async function run234(context) {
24290
25082
  const { params, error } = context;
24291
25083
  const {
24292
25084
  vm_uuid: vmUuidParam,
@@ -24356,13 +25148,13 @@ async function run232(context) {
24356
25148
  command: snapshotResult.command
24357
25149
  };
24358
25150
  }
24359
- var snapshot_vm_default = task(run232, {
25151
+ var snapshot_vm_default = task(run234, {
24360
25152
  description: "Creates a snapshot of an XCP-ng VM (optionally with quiesce)."
24361
25153
  });
24362
25154
 
24363
25155
  // src/core/xcpng/import-vdi.ts
24364
25156
  import path8 from "path";
24365
- async function run233(context) {
25157
+ async function run235(context) {
24366
25158
  const { params, error } = context;
24367
25159
  const {
24368
25160
  sr_uuid: srUuidParam,
@@ -24484,7 +25276,7 @@ async function run233(context) {
24484
25276
  appliedCommands
24485
25277
  };
24486
25278
  }
24487
- var import_vdi_default = task(run233, {
25279
+ var import_vdi_default = task(run235, {
24488
25280
  description: "Imports a VDI file into a storage repository via xe vdi-import."
24489
25281
  });
24490
25282
  async function resolveVirtualSize(context, options) {
@@ -24563,7 +25355,7 @@ function parseOriginalSizeFromVhdTool(output) {
24563
25355
  }
24564
25356
 
24565
25357
  // src/core/xcpng/vm-migrate.ts
24566
- async function run234(context) {
25358
+ async function run236(context) {
24567
25359
  const { params, error } = context;
24568
25360
  const {
24569
25361
  vm_uuid: vmUuidParam,
@@ -24687,12 +25479,12 @@ async function run234(context) {
24687
25479
  appliedCommands
24688
25480
  };
24689
25481
  }
24690
- var vm_migrate_default = task(run234, {
25482
+ var vm_migrate_default = task(run236, {
24691
25483
  description: "Migrates a VM to another host (and optionally storage repository) via xe vm-migrate."
24692
25484
  });
24693
25485
 
24694
25486
  // src/core/xcpng/vm-export.ts
24695
- async function run235(context) {
25487
+ async function run237(context) {
24696
25488
  const { params, error } = context;
24697
25489
  const {
24698
25490
  vm_uuid: vmUuidParam,
@@ -24781,12 +25573,12 @@ async function run235(context) {
24781
25573
  appliedCommands
24782
25574
  };
24783
25575
  }
24784
- var vm_export_default = task(run235, {
25576
+ var vm_export_default = task(run237, {
24785
25577
  description: "Exports a VM to an XVA file via xe vm-export."
24786
25578
  });
24787
25579
 
24788
25580
  // src/core/xcpng/vm-import.ts
24789
- async function run236(context) {
25581
+ async function run238(context) {
24790
25582
  const { params, error } = context;
24791
25583
  const {
24792
25584
  filename,
@@ -24855,12 +25647,12 @@ async function run236(context) {
24855
25647
  appliedCommands
24856
25648
  };
24857
25649
  }
24858
- var vm_import_default = task(run236, {
25650
+ var vm_import_default = task(run238, {
24859
25651
  description: "Imports a VM image from an XVA file via xe vm-import."
24860
25652
  });
24861
25653
 
24862
25654
  // src/core/xcpng/vm-copy.ts
24863
- async function run237(context) {
25655
+ async function run239(context) {
24864
25656
  const { params, error } = context;
24865
25657
  const {
24866
25658
  vm_uuid: vmUuidParam,
@@ -24987,12 +25779,12 @@ async function run237(context) {
24987
25779
  appliedCommands
24988
25780
  };
24989
25781
  }
24990
- var vm_copy_default = task(run237, {
25782
+ var vm_copy_default = task(run239, {
24991
25783
  description: "Creates a full copy of a VM, optionally targeting a different SR."
24992
25784
  });
24993
25785
 
24994
25786
  // src/core/xcpng/detach-cd-media.ts
24995
- async function run238(context) {
25787
+ async function run240(context) {
24996
25788
  if (!context.host) {
24997
25789
  return {
24998
25790
  success: false,
@@ -25136,12 +25928,12 @@ function filterCdDisks(disks) {
25136
25928
  }
25137
25929
  return results;
25138
25930
  }
25139
- var detach_cd_media_default = task(run238, {
25931
+ var detach_cd_media_default = task(run240, {
25140
25932
  description: "Detaches CD/DVD virtual media from a VM by unplugging and destroying associated VBDs."
25141
25933
  });
25142
25934
 
25143
25935
  // src/core/xcpng/cleanup-config-drive.ts
25144
- async function run239(context) {
25936
+ async function run241(context) {
25145
25937
  if (!context.host) {
25146
25938
  return {
25147
25939
  success: false,
@@ -25341,7 +26133,7 @@ async function run239(context) {
25341
26133
  steps
25342
26134
  };
25343
26135
  }
25344
- var cleanup_config_drive_default = task(run239, {
26136
+ var cleanup_config_drive_default = task(run241, {
25345
26137
  description: "Detaches an attached config-drive ISO from a VM and removes the associated VDI once the guest is halted."
25346
26138
  });
25347
26139
 
@@ -25453,7 +26245,7 @@ __export(yum_exports2, {
25453
26245
 
25454
26246
  // src/core/yum/add_repository.ts
25455
26247
  import path9 from "path";
25456
- async function run240(context) {
26248
+ async function run242(context) {
25457
26249
  const { params, exec, info, error } = context;
25458
26250
  const { content, name, sudo = true } = params;
25459
26251
  if (!content) {
@@ -25468,9 +26260,11 @@ async function run240(context) {
25468
26260
  }
25469
26261
  const repoFilePath = path9.join("/etc/yum.repos.d", `${name}.repo`);
25470
26262
  try {
25471
- const cmd = `echo "${content}" > ${repoFilePath}`;
25472
- info(`Executing: ${cmd}`);
25473
- const result = await exec(cmd, { sudo });
26263
+ const heredoc = `cat <<'EOF' > ${repoFilePath}
26264
+ ${content}
26265
+ EOF`;
26266
+ info(`Writing repository definition to ${repoFilePath}`);
26267
+ const result = await exec(["bash", "-lc", heredoc], { sudo });
25474
26268
  if (result.exitCode !== 0) {
25475
26269
  const errorMsg = `Failed to add repository: ${result.stderr}`;
25476
26270
  error(errorMsg);
@@ -25483,7 +26277,7 @@ async function run240(context) {
25483
26277
  return { success: false, error: errorMsg };
25484
26278
  }
25485
26279
  }
25486
- var add_repository_default2 = task(run240, { description: "Adds a YUM repository." });
26280
+ var add_repository_default2 = task(run242, { description: "Adds a YUM repository." });
25487
26281
 
25488
26282
  // src/core/net/index.ts
25489
26283
  var net_exports = {};
@@ -25493,7 +26287,7 @@ __export(net_exports, {
25493
26287
  });
25494
26288
 
25495
26289
  // src/core/net/download.ts
25496
- async function run241(context) {
26290
+ async function run243(context) {
25497
26291
  const { params, info, error, exec } = context;
25498
26292
  const { url, dest, mode, sudo = false } = params;
25499
26293
  if (!url || !dest) {
@@ -25538,10 +26332,10 @@ async function run241(context) {
25538
26332
  return { success: false, error: errorMsg };
25539
26333
  }
25540
26334
  }
25541
- var download_default = task(run241, { description: "Downloads a file from a URL using curl or wget." });
26335
+ var download_default = task(run243, { description: "Downloads a file from a URL using curl or wget." });
25542
26336
 
25543
26337
  // src/core/net/interfaces.ts
25544
- async function run242(context) {
26338
+ async function run244(context) {
25545
26339
  const { params, info, error, exec } = context;
25546
26340
  const { sudo = false } = params;
25547
26341
  try {
@@ -25552,8 +26346,9 @@ async function run242(context) {
25552
26346
  return { success: false, error: errorMsg };
25553
26347
  }
25554
26348
  let interfaces = [];
26349
+ const sanitizedOutput = stripAnsiSequences(ipResult.stdout);
25555
26350
  try {
25556
- const ipData = JSON.parse(ipResult.stdout);
26351
+ const ipData = sanitizedOutput ? JSON.parse(sanitizedOutput) : [];
25557
26352
  for (const iface of ipData) {
25558
26353
  const interfaceInfo = {
25559
26354
  name: iface.ifname,
@@ -25599,7 +26394,7 @@ async function run242(context) {
25599
26394
  }
25600
26395
  } catch (parseError) {
25601
26396
  info("JSON parsing failed, falling back to manual parsing");
25602
- const lines = ipResult.stdout.split("\n");
26397
+ const lines = sanitizedOutput.split("\n");
25603
26398
  let currentInterface = null;
25604
26399
  for (const line of lines) {
25605
26400
  const trimmed = line.trim();
@@ -25668,7 +26463,7 @@ async function run242(context) {
25668
26463
  return { success: false, error: errorMsg };
25669
26464
  }
25670
26465
  }
25671
- var interfaces_default = task(run242, { description: "Lists network interfaces with their properties." });
26466
+ var interfaces_default = task(run244, { description: "Lists network interfaces with their properties." });
25672
26467
 
25673
26468
  // src/core/nftables/index.ts
25674
26469
  var nftables_exports = {};
@@ -25677,7 +26472,7 @@ __export(nftables_exports, {
25677
26472
  });
25678
26473
 
25679
26474
  // src/core/nftables/apply.ts
25680
- async function run243(context) {
26475
+ async function run245(context) {
25681
26476
  const { params, exec, info } = context;
25682
26477
  const { config } = params;
25683
26478
  if (!config) {
@@ -25701,7 +26496,7 @@ async function run243(context) {
25701
26496
  return { success: false, error };
25702
26497
  }
25703
26498
  }
25704
- var apply_default = task(run243, { description: "Applies an nftables configuration." });
26499
+ var apply_default = task(run245, { description: "Applies an nftables configuration." });
25705
26500
 
25706
26501
  // src/core/nftables/index.ts
25707
26502
  var nftables_default = {
@@ -25715,7 +26510,7 @@ __export(firewalld_exports, {
25715
26510
  });
25716
26511
 
25717
26512
  // src/core/firewalld/disable.ts
25718
- async function run244(context) {
26513
+ async function run246(context) {
25719
26514
  const { run: runTask, debug, error, info } = context;
25720
26515
  const statusResult = await runTask(status_default({ service: "firewalld" }));
25721
26516
  if (!statusResult.success && (statusResult.error?.includes("Could not find") || statusResult.error?.includes("not-found"))) {
@@ -25739,7 +26534,7 @@ async function run244(context) {
25739
26534
  info("firewalld service disabled successfully.");
25740
26535
  return { success: true };
25741
26536
  }
25742
- var disable_default3 = task(run244, { description: "Disables and stops the firewalld service." });
26537
+ var disable_default3 = task(run246, { description: "Disables and stops the firewalld service." });
25743
26538
 
25744
26539
  // src/core/firewalld/index.ts
25745
26540
  var firewalld_default = {