Files
api/scripts/staging-edge-gateway-smoke.mjs

161 lines
4.3 KiB
JavaScript

import process from "node:process";
import path from "node:path";
import { pathToFileURL } from "node:url";
export const DEFAULT_STAGING_BASE_URL = "https://api.truckwash.io:4433";
export const INSTALLER_SCRIPT_REQUIRED_SNIPPETS = [
"/edge-agent/install-token/status",
"report_install_status",
'begin_install_phase "VERIFY_TOKEN"',
'begin_install_phase "WAIT_FOR_CLAIM"',
'report_install_status "FAILED"',
];
export function normalizeBaseUrl(url) {
return String(url || "").trim().replace(/\/+$/, "");
}
export function parseArgs(argv = process.argv.slice(2)) {
const options = {
baseUrl: DEFAULT_STAGING_BASE_URL,
installToken: "",
help: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
const next = argv[index + 1];
switch (arg) {
case "--base-url":
options.baseUrl = String(next || "").trim() || DEFAULT_STAGING_BASE_URL;
index += 1;
break;
case "--install-token":
options.installToken = String(next || "").trim();
index += 1;
break;
case "--help":
case "-h":
options.help = true;
break;
default:
throw new Error(`Unknown argument: ${arg}`);
}
}
return options;
}
export function buildChecks(baseUrl, installToken) {
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
return [
{
name: "Ping",
url: `${normalizedBaseUrl}/ping`,
},
{
name: "Agent PHP artifact",
url: `${normalizedBaseUrl}/edge-agent/artifacts/agent.php`,
},
{
name: "Service unit artifact",
url: `${normalizedBaseUrl}/edge-agent/artifacts/truckwash-edge-agent.service`,
},
{
name: "Installer script",
url: `${normalizedBaseUrl}/edge-agent/install.sh?token=${encodeURIComponent(installToken)}`,
},
];
}
export function validateInstallerScriptBody(body) {
const source = String(body || "");
const missingSnippets = INSTALLER_SCRIPT_REQUIRED_SNIPPETS.filter((snippet) => !source.includes(snippet));
if (missingSnippets.length) {
throw new Error(`Installer script is missing required status wiring: ${missingSnippets.join(", ")}`);
}
return INSTALLER_SCRIPT_REQUIRED_SNIPPETS;
}
function printUsage() {
process.stdout.write(`Usage:
node scripts/staging-edge-gateway-smoke.mjs --install-token <token> [--base-url <url>]
Options:
--install-token <token> Real edge-gateway install token used to validate install.sh.
--base-url <url> Public staging base URL. Default: ${DEFAULT_STAGING_BASE_URL}
--help Show this help text.
`);
}
function previewBody(body, limit = 200) {
const normalized = String(body || "").replace(/\s+/g, " ").trim();
if (normalized.length <= limit) {
return normalized;
}
return `${normalized.slice(0, limit)}...`;
}
export async function runSmoke({ baseUrl, installToken }) {
if (String(installToken || "").trim() === "") {
throw new Error("Missing required --install-token value.");
}
const checks = buildChecks(baseUrl, installToken);
const results = [];
for (const check of checks) {
process.stdout.write(`[staging-smoke] GET ${check.url}\n`);
const response = await fetch(check.url);
const body = await response.text();
const result = {
...check,
status: response.status,
ok: response.ok,
bodyPreview: previewBody(body),
};
results.push(result);
if (!response.ok) {
throw new Error(
`${check.name} failed with HTTP ${response.status} at ${check.url}. ` +
`Body preview: ${result.bodyPreview || "<empty>"}`
);
}
if (check.name === "Installer script") {
result.verifiedSnippets = validateInstallerScriptBody(body);
}
}
return results;
}
async function main() {
const options = parseArgs();
if (options.help) {
printUsage();
return;
}
const results = await runSmoke(options);
for (const result of results) {
process.stdout.write(`[staging-smoke] OK ${result.status} ${result.name}\n`);
}
}
const isDirectExecution = process.argv[1]
&& import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
if (isDirectExecution) {
main().catch((error) => {
process.stderr.write(`[staging-smoke] ERROR: ${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
});
}