@forgezero/agent 0.1.12 → 0.1.13
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/fz-agent.js +37 -4
- package/dist/fz.js +1 -1
- package/dist/metal-helper-socket.js +36 -3
- package/dist/metal-provision.d.ts +2 -1
- package/dist/metal-provision.js +36 -3
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/fz-agent.js
CHANGED
|
@@ -2045,15 +2045,48 @@ async function provisionMetalGuest(profile, claim, exec) {
|
|
|
2045
2045
|
save();
|
|
2046
2046
|
return { guestAddress: address };
|
|
2047
2047
|
}
|
|
2048
|
+
function legacyPlatformManifest(profile, claim, name) {
|
|
2049
|
+
if (claim.bootstrap?.kind !== "platform-genesis" || claim.computeKey !== `platform:${name}` || claim.spec.reference !== `platform:${name}` || claim.spec.guestAddress === undefined)
|
|
2050
|
+
return;
|
|
2051
|
+
const legacyDir = profile.legacyStateDir ?? "/etc/forgezero/guests";
|
|
2052
|
+
const legacyPath = join2(legacyDir, `${name}.conf`);
|
|
2053
|
+
if (!existsSync5(legacyPath))
|
|
2054
|
+
return;
|
|
2055
|
+
const values = new Map;
|
|
2056
|
+
for (const line of readFileSync3(legacyPath, "utf8").split(/\r?\n/)) {
|
|
2057
|
+
if (!line || line.startsWith("#"))
|
|
2058
|
+
continue;
|
|
2059
|
+
const match = /^([A-Z][A-Z0-9_]*)=([^\s'"`$;|&<>]+)$/.exec(line);
|
|
2060
|
+
if (!match)
|
|
2061
|
+
throw new MetalProvisionError("legacy guest inventory contains unsafe syntax");
|
|
2062
|
+
values.set(match[1], match[2]);
|
|
2063
|
+
}
|
|
2064
|
+
const disk = `/dev/${profile.volumeGroup}/${name}`;
|
|
2065
|
+
if (values.get("NAME") !== name || values.get("DISK") !== disk || values.get("IP") !== claim.spec.guestAddress)
|
|
2066
|
+
throw new MetalProvisionError("legacy guest inventory does not match the platform claim");
|
|
2067
|
+
return {
|
|
2068
|
+
computeKey: claim.computeKey,
|
|
2069
|
+
reference: claim.spec.reference,
|
|
2070
|
+
name,
|
|
2071
|
+
address: claim.spec.guestAddress,
|
|
2072
|
+
mac: values.get("MAC") ?? "",
|
|
2073
|
+
cpuPoolKey: claim.spec.cpuPoolKey ?? "",
|
|
2074
|
+
allowedCpus: values.get("CPUSET") ?? "",
|
|
2075
|
+
allowedMemoryNodes: values.get("NUMA"),
|
|
2076
|
+
phase: "running",
|
|
2077
|
+
disk,
|
|
2078
|
+
unit: `forgezero-guest@${name}.service`
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2048
2081
|
async function removeMetalGuest(profile, claim, exec) {
|
|
2049
2082
|
validateMetalProfile(profile);
|
|
2050
2083
|
if (claim.action !== "delete")
|
|
2051
2084
|
throw new MetalProvisionError("create claim cannot remove a guest");
|
|
2052
2085
|
const name = claim.spec.guestName ?? guestNameFor(claim.computeKey);
|
|
2053
2086
|
const manifestPath = join2(profile.stateDir, `${name}.json`);
|
|
2054
|
-
|
|
2087
|
+
const manifest = existsSync5(manifestPath) ? JSON.parse(readFileSync3(manifestPath, "utf8")) : legacyPlatformManifest(profile, claim, name);
|
|
2088
|
+
if (!manifest)
|
|
2055
2089
|
return {};
|
|
2056
|
-
const manifest = JSON.parse(readFileSync3(manifestPath, "utf8"));
|
|
2057
2090
|
const currentIdentity = manifest.computeKey === claim.computeKey && manifest.reference === claim.spec.reference && manifest.name === name;
|
|
2058
2091
|
const legacyPlatformIdentity = claim.bootstrap?.kind === "platform-genesis" && claim.computeKey === `platform:${name}` && claim.spec.reference === `platform:${name}` && manifest.name === name && manifest.disk === `/dev/${profile.volumeGroup}/${name}` && manifest.address === claim.spec.guestAddress && (manifest.unit === `fz-guest@${name}.service` || manifest.unit === `forgezero-guest@${name}.service`);
|
|
2059
2092
|
if (!currentIdentity && !legacyPlatformIdentity) {
|
|
@@ -2082,7 +2115,7 @@ async function removeMetalGuest(profile, claim, exec) {
|
|
|
2082
2115
|
if (existsSync5(path))
|
|
2083
2116
|
unlinkSync4(path);
|
|
2084
2117
|
if (legacyPlatformIdentity) {
|
|
2085
|
-
const legacyConfig =
|
|
2118
|
+
const legacyConfig = join2(profile.legacyStateDir ?? "/etc/forgezero/guests", `${name}.conf`);
|
|
2086
2119
|
const legacyDropIn = join2(profile.unitDir, `${service}.d`);
|
|
2087
2120
|
if (existsSync5(legacyConfig))
|
|
2088
2121
|
unlinkSync4(legacyConfig);
|
|
@@ -2679,7 +2712,7 @@ async function applyMetalIsolation(profile, exec = defaultExec) {
|
|
|
2679
2712
|
}
|
|
2680
2713
|
|
|
2681
2714
|
// src/version.ts
|
|
2682
|
-
var VERSION = "0.1.
|
|
2715
|
+
var VERSION = "0.1.13";
|
|
2683
2716
|
|
|
2684
2717
|
// src/index.ts
|
|
2685
2718
|
function loadOrCreateSeed(path) {
|
package/dist/fz.js
CHANGED
|
@@ -1041,15 +1041,48 @@ async function provisionMetalGuest(profile, claim, exec) {
|
|
|
1041
1041
|
save();
|
|
1042
1042
|
return { guestAddress: address };
|
|
1043
1043
|
}
|
|
1044
|
+
function legacyPlatformManifest(profile, claim, name) {
|
|
1045
|
+
if (claim.bootstrap?.kind !== "platform-genesis" || claim.computeKey !== `platform:${name}` || claim.spec.reference !== `platform:${name}` || claim.spec.guestAddress === undefined)
|
|
1046
|
+
return;
|
|
1047
|
+
const legacyDir = profile.legacyStateDir ?? "/etc/forgezero/guests";
|
|
1048
|
+
const legacyPath = join(legacyDir, `${name}.conf`);
|
|
1049
|
+
if (!existsSync(legacyPath))
|
|
1050
|
+
return;
|
|
1051
|
+
const values = new Map;
|
|
1052
|
+
for (const line of readFileSync(legacyPath, "utf8").split(/\r?\n/)) {
|
|
1053
|
+
if (!line || line.startsWith("#"))
|
|
1054
|
+
continue;
|
|
1055
|
+
const match = /^([A-Z][A-Z0-9_]*)=([^\s'"`$;|&<>]+)$/.exec(line);
|
|
1056
|
+
if (!match)
|
|
1057
|
+
throw new MetalProvisionError("legacy guest inventory contains unsafe syntax");
|
|
1058
|
+
values.set(match[1], match[2]);
|
|
1059
|
+
}
|
|
1060
|
+
const disk = `/dev/${profile.volumeGroup}/${name}`;
|
|
1061
|
+
if (values.get("NAME") !== name || values.get("DISK") !== disk || values.get("IP") !== claim.spec.guestAddress)
|
|
1062
|
+
throw new MetalProvisionError("legacy guest inventory does not match the platform claim");
|
|
1063
|
+
return {
|
|
1064
|
+
computeKey: claim.computeKey,
|
|
1065
|
+
reference: claim.spec.reference,
|
|
1066
|
+
name,
|
|
1067
|
+
address: claim.spec.guestAddress,
|
|
1068
|
+
mac: values.get("MAC") ?? "",
|
|
1069
|
+
cpuPoolKey: claim.spec.cpuPoolKey ?? "",
|
|
1070
|
+
allowedCpus: values.get("CPUSET") ?? "",
|
|
1071
|
+
allowedMemoryNodes: values.get("NUMA"),
|
|
1072
|
+
phase: "running",
|
|
1073
|
+
disk,
|
|
1074
|
+
unit: `forgezero-guest@${name}.service`
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1044
1077
|
async function removeMetalGuest(profile, claim, exec) {
|
|
1045
1078
|
validateMetalProfile(profile);
|
|
1046
1079
|
if (claim.action !== "delete")
|
|
1047
1080
|
throw new MetalProvisionError("create claim cannot remove a guest");
|
|
1048
1081
|
const name = claim.spec.guestName ?? guestNameFor(claim.computeKey);
|
|
1049
1082
|
const manifestPath = join(profile.stateDir, `${name}.json`);
|
|
1050
|
-
|
|
1083
|
+
const manifest = existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, "utf8")) : legacyPlatformManifest(profile, claim, name);
|
|
1084
|
+
if (!manifest)
|
|
1051
1085
|
return {};
|
|
1052
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
1053
1086
|
const currentIdentity = manifest.computeKey === claim.computeKey && manifest.reference === claim.spec.reference && manifest.name === name;
|
|
1054
1087
|
const legacyPlatformIdentity = claim.bootstrap?.kind === "platform-genesis" && claim.computeKey === `platform:${name}` && claim.spec.reference === `platform:${name}` && manifest.name === name && manifest.disk === `/dev/${profile.volumeGroup}/${name}` && manifest.address === claim.spec.guestAddress && (manifest.unit === `fz-guest@${name}.service` || manifest.unit === `forgezero-guest@${name}.service`);
|
|
1055
1088
|
if (!currentIdentity && !legacyPlatformIdentity) {
|
|
@@ -1078,7 +1111,7 @@ async function removeMetalGuest(profile, claim, exec) {
|
|
|
1078
1111
|
if (existsSync(path))
|
|
1079
1112
|
unlinkSync(path);
|
|
1080
1113
|
if (legacyPlatformIdentity) {
|
|
1081
|
-
const legacyConfig =
|
|
1114
|
+
const legacyConfig = join(profile.legacyStateDir ?? "/etc/forgezero/guests", `${name}.conf`);
|
|
1082
1115
|
const legacyDropIn = join(profile.unitDir, `${service}.d`);
|
|
1083
1116
|
if (existsSync(legacyConfig))
|
|
1084
1117
|
unlinkSync(legacyConfig);
|
|
@@ -24,6 +24,8 @@ export interface MetalProvisionProfile {
|
|
|
24
24
|
stateDir: string;
|
|
25
25
|
seedDir: string;
|
|
26
26
|
unitDir: string;
|
|
27
|
+
/** One-time compatibility source for pre-Agent platform guests. */
|
|
28
|
+
legacyStateDir?: string;
|
|
27
29
|
apiUrl: string;
|
|
28
30
|
images: Record<string, MetalImage>;
|
|
29
31
|
/** Explicit host-observed pools. No pool means no dynamic guest authority. */
|
|
@@ -81,5 +83,4 @@ export declare function cloudInit(profile: MetalProvisionProfile, claim: CreateR
|
|
|
81
83
|
};
|
|
82
84
|
/** The only root operation the metal agent may request. */
|
|
83
85
|
export declare function provisionMetalGuest(profile: MetalProvisionProfile, claim: CreateRemoteProvisionClaim, exec: MetalExec): Promise<ProvisionResult>;
|
|
84
|
-
/** Idempotently remove every host-owned artifact before capacity is returned. */
|
|
85
86
|
export declare function removeMetalGuest(profile: MetalProvisionProfile, claim: RemoteProvisionClaim, exec: MetalExec): Promise<ProvisionResult>;
|
package/dist/metal-provision.js
CHANGED
|
@@ -1041,15 +1041,48 @@ async function provisionMetalGuest(profile, claim, exec) {
|
|
|
1041
1041
|
save();
|
|
1042
1042
|
return { guestAddress: address };
|
|
1043
1043
|
}
|
|
1044
|
+
function legacyPlatformManifest(profile, claim, name) {
|
|
1045
|
+
if (claim.bootstrap?.kind !== "platform-genesis" || claim.computeKey !== `platform:${name}` || claim.spec.reference !== `platform:${name}` || claim.spec.guestAddress === undefined)
|
|
1046
|
+
return;
|
|
1047
|
+
const legacyDir = profile.legacyStateDir ?? "/etc/forgezero/guests";
|
|
1048
|
+
const legacyPath = join(legacyDir, `${name}.conf`);
|
|
1049
|
+
if (!existsSync(legacyPath))
|
|
1050
|
+
return;
|
|
1051
|
+
const values = new Map;
|
|
1052
|
+
for (const line of readFileSync(legacyPath, "utf8").split(/\r?\n/)) {
|
|
1053
|
+
if (!line || line.startsWith("#"))
|
|
1054
|
+
continue;
|
|
1055
|
+
const match = /^([A-Z][A-Z0-9_]*)=([^\s'"`$;|&<>]+)$/.exec(line);
|
|
1056
|
+
if (!match)
|
|
1057
|
+
throw new MetalProvisionError("legacy guest inventory contains unsafe syntax");
|
|
1058
|
+
values.set(match[1], match[2]);
|
|
1059
|
+
}
|
|
1060
|
+
const disk = `/dev/${profile.volumeGroup}/${name}`;
|
|
1061
|
+
if (values.get("NAME") !== name || values.get("DISK") !== disk || values.get("IP") !== claim.spec.guestAddress)
|
|
1062
|
+
throw new MetalProvisionError("legacy guest inventory does not match the platform claim");
|
|
1063
|
+
return {
|
|
1064
|
+
computeKey: claim.computeKey,
|
|
1065
|
+
reference: claim.spec.reference,
|
|
1066
|
+
name,
|
|
1067
|
+
address: claim.spec.guestAddress,
|
|
1068
|
+
mac: values.get("MAC") ?? "",
|
|
1069
|
+
cpuPoolKey: claim.spec.cpuPoolKey ?? "",
|
|
1070
|
+
allowedCpus: values.get("CPUSET") ?? "",
|
|
1071
|
+
allowedMemoryNodes: values.get("NUMA"),
|
|
1072
|
+
phase: "running",
|
|
1073
|
+
disk,
|
|
1074
|
+
unit: `forgezero-guest@${name}.service`
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1044
1077
|
async function removeMetalGuest(profile, claim, exec) {
|
|
1045
1078
|
validateMetalProfile(profile);
|
|
1046
1079
|
if (claim.action !== "delete")
|
|
1047
1080
|
throw new MetalProvisionError("create claim cannot remove a guest");
|
|
1048
1081
|
const name = claim.spec.guestName ?? guestNameFor(claim.computeKey);
|
|
1049
1082
|
const manifestPath = join(profile.stateDir, `${name}.json`);
|
|
1050
|
-
|
|
1083
|
+
const manifest = existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, "utf8")) : legacyPlatformManifest(profile, claim, name);
|
|
1084
|
+
if (!manifest)
|
|
1051
1085
|
return {};
|
|
1052
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
1053
1086
|
const currentIdentity = manifest.computeKey === claim.computeKey && manifest.reference === claim.spec.reference && manifest.name === name;
|
|
1054
1087
|
const legacyPlatformIdentity = claim.bootstrap?.kind === "platform-genesis" && claim.computeKey === `platform:${name}` && claim.spec.reference === `platform:${name}` && manifest.name === name && manifest.disk === `/dev/${profile.volumeGroup}/${name}` && manifest.address === claim.spec.guestAddress && (manifest.unit === `fz-guest@${name}.service` || manifest.unit === `forgezero-guest@${name}.service`);
|
|
1055
1088
|
if (!currentIdentity && !legacyPlatformIdentity) {
|
|
@@ -1078,7 +1111,7 @@ async function removeMetalGuest(profile, claim, exec) {
|
|
|
1078
1111
|
if (existsSync(path))
|
|
1079
1112
|
unlinkSync(path);
|
|
1080
1113
|
if (legacyPlatformIdentity) {
|
|
1081
|
-
const legacyConfig =
|
|
1114
|
+
const legacyConfig = join(profile.legacyStateDir ?? "/etc/forgezero/guests", `${name}.conf`);
|
|
1082
1115
|
const legacyDropIn = join(profile.unitDir, `${service}.d`);
|
|
1083
1116
|
if (existsSync(legacyConfig))
|
|
1084
1117
|
unlinkSync(legacyConfig);
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** One package version shared by both public binaries. Pinned to package.json by tests. */
|
|
2
|
-
export declare const VERSION = "0.1.
|
|
2
|
+
export declare const VERSION = "0.1.13";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"//": "Publishing happens from an operator's machine, not CI \u2014 CLAUDE.md records that the absence of CI is deliberate. npm's `provenance` attests a tarball was built by a recognised CI provider from a named commit, so it cannot be produced here: it was set, and the first publish failed with `Automatic provenance generation not supported for provider: null`. A setting that can never be satisfied is worse than none, because it reads as a guarantee nobody is getting. Restore it the day this publishes from CI, and not before.",
|
|
3
3
|
"name": "@forgezero/agent",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.13",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"check": "tsc --noEmit",
|