Ctrl K
ComunidadGuías…

scripts/local-vm.test.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from "node:assert/strict";
import { mkdtempSync, writeFileSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import test from "node:test";

function invoke(command, initial, owned = true, network = true) {
  const dir = mkdtempSync(join(tmpdir(), "devpush-vm-cli-"));
  try {
    const state = join(dir, "state"),
      calls = join(dir, "calls");
    writeFileSync(state, initial);
    writeFileSync(calls, "");
    // Exercise the macOS-only setup on Linux CI without weakening its host guard.
    writeFileSync(join(dir, "uname"), "#!/bin/sh\necho Darwin\n", { mode: 0o755 });
    writeFileSync(
      join(dir, "limactl"),
      `#!${process.execPath}
const fs = require('node:fs'); const a = process.argv.slice(2);
fs.appendFileSync(process.env.CALLS, JSON.stringify(a)+'\\n');
if(a[0]==='list') {
 const s=fs.readFileSync(process.env.STATE,'utf8');
 if(s) console.log(a.includes('--json') ? JSON.stringify({name:'devpush-test',vmType:'vz',config:{networks:process.env.NETWORK==='1'?[{vzNAT:true}]:[]}}) : 'devpush-test '+s);
}
if(a[0]==='create') fs.writeFileSync(process.env.STATE,'Stopped');
if(a[0]==='start') fs.writeFileSync(process.env.STATE,'Running');
if(a[0]==='shell' && a.includes('/etc/devpush-test-vm') && process.env.OWNED==='0') process.exit(1);
`,
      { mode: 0o755 },
    );
    const result = spawnSync(
      "bash",
      [resolve("scripts/local-vm.sh"), command],
      {
        encoding: "utf8",
        env: {
          ...process.env,
          PATH: `${dir}:${process.env.PATH}`,
          STATE: state,
          CALLS: calls,
          OWNED: owned ? "1" : "0",
          NETWORK: network ? "1" : "0",
        },
      },
    );
    return {
      status: result.status,
      stderr: result.stderr,
      calls: readFileSync(calls, "utf8").trim().split("\n").map(JSON.parse),
    };
  } finally {
    rmSync(dir, { recursive: true, force: true });
  }
}

test("setup creates a missing VM; reuses an already running VM", () => {
  const first = invoke("setup", "");
  assert.equal(first.status, 0, first.stderr);
  assert.deepEqual(
    first.calls
      .filter((a) => ["create", "start"].includes(a[0]))
      .map((a) => a[0]),
    ["create", "start"],
  );
  const repeat = invoke("setup", "Running");
  assert.equal(repeat.status, 0);
  assert.equal(
    repeat.calls.some((a) => ["create", "start", "delete"].includes(a[0])),
    false,
  );
});

test("destroy verifies ownership before stopping or deleting the dedicated VM", () => {
  const refused = invoke("destroy", "Running", false);
  assert.notEqual(refused.status, 0);
  assert.equal(
    refused.calls.some((a) => ["stop", "delete"].includes(a[0])),
    false,
  );
  const allowed = invoke("destroy", "Running");
  assert.equal(allowed.status, 0);
  assert.deepEqual(
    allowed.calls
      .filter((a) => ["stop", "delete"].includes(a[0]))
      .map((a) => a[0]),
    ["stop", "delete"],
  );
  assert.deepEqual(allowed.calls.at(-1), [
    "delete",
    "--tty=false",
    "devpush-test",
  ]);
});

test("stopping preserves the disk; destroying an absent VM creates nothing", () => {
  const stopped = invoke("stop", "Running");
  assert.equal(stopped.status, 0);
  assert.deepEqual(stopped.calls.at(-1), ["stop", "devpush-test"]);
  const absent = invoke("destroy", "");
  assert.equal(absent.status, 0);
  assert.equal(
    absent.calls.some((a) => ["create", "start", "delete"].includes(a[0])),
    false,
  );
});

test("setup upgrades owned VM networking; never edits an unowned VM", () => {
  const upgrade = invoke("setup", "Running", true, false);
  assert.equal(upgrade.status, 0, upgrade.stderr);
  assert.deepEqual(
    upgrade.calls.filter((a) => ["stop", "edit", "start"].includes(a[0])),
    [
      ["stop", "devpush-test"],
      ["edit", "--tty=false", "--network=vzNAT", "devpush-test"],
      ["start", "--tty=false", "devpush-test"],
    ],
  );
  const refused = invoke("setup", "Running", false, false);
  assert.notEqual(refused.status, 0);
  assert.equal(
    refused.calls.some((a) => ["stop", "edit", "delete"].includes(a[0])),
    false,
  );
});

test("VM enrollment downloads the installer before invoking it with the routing address", async () => {
  const { createServer } = await import("node:http");
  const { spawn } = await import("node:child_process");
  const dir = mkdtempSync(join(tmpdir(), "devpush-vm-install-"));
  const body = "#!/bin/sh\n# downloaded installer fixture\n";
  const server = createServer((_request, response) => response.end(body));
  await new Promise((done) => server.listen(0, "127.0.0.1", done));
  try {
    writeFileSync(
      join(dir, "sudo"),
      `#!/bin/sh\ncat "$2" > "$RECEIVED"\nprintf '%s' "$3 $4" > "$ARGUMENTS"\nprintf '%s' "$2" > "$TEMP_SCRIPT"\n`,
      { mode: 0o755 },
    );
    const source = readFileSync(resolve("scripts/local-vm.sh"), "utf8");
    const guestScript = source.match(/<<'INSTALL'\n([\s\S]*?)\nINSTALL/)?.[1];
    assert.ok(guestScript);
    const child = spawn(
      "bash",
      [
        "-s",
        "--",
        `http://127.0.0.1:${server.address().port}/installer`,
        "192.168.64.5",
      ],
      {
        env: {
          ...process.env,
          PATH: `${dir}:${process.env.PATH}`,
          RECEIVED: join(dir, "received"),
          ARGUMENTS: join(dir, "arguments"),
          TEMP_SCRIPT: join(dir, "temp-script"),
        },
        stdio: ["pipe", "ignore", "pipe"],
      },
    );
    let errors = "";
    child.stderr.on("data", (chunk) => {
      errors += chunk;
    });
    child.stdin.end(guestScript);
    const status = await new Promise((done) => child.on("exit", done));
    assert.equal(status, 0, errors);
    assert.equal(readFileSync(join(dir, "received"), "utf8"), body);
    assert.equal(
      readFileSync(join(dir, "arguments"), "utf8"),
      "--address 192.168.64.5",
    );
    const { existsSync } = await import("node:fs");
    assert.equal(
      existsSync(readFileSync(join(dir, "temp-script"), "utf8")),
      false,
    );
  } finally {
    await new Promise((done) => server.close(done));
    rmSync(dir, { recursive: true, force: true });
  }
});