fix: migrate JD01 registry to k3s workload
This commit is contained in:
@@ -5,6 +5,7 @@ import { runCommand, type CommandResult } from "./command";
|
||||
import { egressBenchmarkCompactResult, egressBenchmarkDryRun, egressBenchmarkStartScript, egressBenchmarkStatusScript, type EgressBenchmarkSpec } from "./egress-proxy-benchmark";
|
||||
import { resolveEgressProxySourceRef } from "./egress-proxy-sources";
|
||||
import { hwlabRuntimeLaneSpecForNode, isHwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "./hwlab-node-lanes";
|
||||
import { registryInfraManifest } from "./hwlab-node-control-plane-registry";
|
||||
import {
|
||||
HWLAB_NODE_CONTROL_PLANE_CONFIG_PATH,
|
||||
type ArgoOptions,
|
||||
@@ -21,6 +22,7 @@ import {
|
||||
type ControlPlaneK3sNodeSpec,
|
||||
type ControlPlaneK8sServiceEgressProxySpec,
|
||||
type ControlPlaneNodeSpec,
|
||||
type ControlPlaneRegistrySpec,
|
||||
type ControlPlaneRuntimeProxySpec,
|
||||
type ControlPlaneTargetSpec,
|
||||
type ControlPlaneTektonArgoObserverRbacSpec,
|
||||
@@ -1523,11 +1525,50 @@ function nodeSpec(id: string, raw: Record<string, unknown>): ControlPlaneNodeSpe
|
||||
route: stringField(raw, "route", `nodes.${id}`),
|
||||
kubeRoute: stringField(raw, "kubeRoute", `nodes.${id}`),
|
||||
k3s,
|
||||
registry: { endpoint: stringField(registry, "endpoint", `nodes.${id}.registry`) },
|
||||
registry: registrySpec(registry, `nodes.${id}.registry`),
|
||||
egressProxy,
|
||||
};
|
||||
}
|
||||
|
||||
function registrySpec(raw: Record<string, unknown>, path: string): ControlPlaneRegistrySpec {
|
||||
const mode = stringField(raw, "mode", path);
|
||||
const endpoint = stringField(raw, "endpoint", path);
|
||||
if (mode === "host-docker") return { mode, endpoint };
|
||||
if (mode !== "k8s-workload") throw new Error(`${path}.mode must be host-docker or k8s-workload`);
|
||||
const imagePullPolicy = optionalStringField(raw, "imagePullPolicy", path) ?? "IfNotPresent";
|
||||
if (imagePullPolicy !== "Always" && imagePullPolicy !== "IfNotPresent" && imagePullPolicy !== "Never") {
|
||||
throw new Error(`${path}.imagePullPolicy must be Always, IfNotPresent, or Never`);
|
||||
}
|
||||
const namespace = stringField(raw, "namespace", path);
|
||||
const deploymentName = stringField(raw, "deploymentName", path);
|
||||
const serviceName = stringField(raw, "serviceName", path);
|
||||
const pvcName = stringField(raw, "pvcName", path);
|
||||
validateKubernetesName(namespace, `${path}.namespace`);
|
||||
validateKubernetesName(deploymentName, `${path}.deploymentName`);
|
||||
validateKubernetesName(serviceName, `${path}.serviceName`);
|
||||
validateKubernetesName(pvcName, `${path}.pvcName`);
|
||||
const image = stringField(raw, "image", path);
|
||||
validatePublicBaseImage(image, `${path}.image`);
|
||||
const hostNetwork = booleanField(raw, "hostNetwork", path);
|
||||
const listenHost = stringField(raw, "listenHost", path);
|
||||
if (listenHost !== "127.0.0.1" && listenHost !== "0.0.0.0") throw new Error(`${path}.listenHost must be 127.0.0.1 or 0.0.0.0`);
|
||||
return {
|
||||
mode,
|
||||
endpoint,
|
||||
namespace,
|
||||
deploymentName,
|
||||
serviceName,
|
||||
pvcName,
|
||||
storage: stringField(raw, "storage", path),
|
||||
image,
|
||||
imagePullPolicy,
|
||||
containerPort: numberField(raw, "containerPort", path),
|
||||
listenHost,
|
||||
listenPort: numberField(raw, "listenPort", path),
|
||||
hostNetwork,
|
||||
};
|
||||
}
|
||||
|
||||
function k3sNodeSpec(raw: Record<string, unknown>, path: string): ControlPlaneK3sNodeSpec {
|
||||
const kubelet = asRecord(raw.kubelet, `${path}.kubelet`);
|
||||
const serviceName = stringField(raw, "serviceName", path);
|
||||
@@ -1872,7 +1913,7 @@ function targetSpec(raw: Record<string, unknown>, index: number): ControlPlaneTa
|
||||
serviceWriteName,
|
||||
cachePvcName: stringField(gitMirror, "cachePvcName", `${path}.gitMirror`),
|
||||
cachePvcStorage: stringField(gitMirror, "cachePvcStorage", `${path}.gitMirror`),
|
||||
cacheHostPath: optionalStringField(gitMirror, "cacheHostPath", `${path}.gitMirror`) ?? null,
|
||||
cacheHostPath: nullableStringField(gitMirror, "cacheHostPath", `${path}.gitMirror`),
|
||||
servicePort: numberField(gitMirror, "servicePort", `${path}.gitMirror`),
|
||||
readContainerPort: numberField(gitMirror, "readContainerPort", `${path}.gitMirror`),
|
||||
writeContainerPort: numberField(gitMirror, "writeContainerPort", `${path}.gitMirror`),
|
||||
@@ -1923,6 +1964,8 @@ function renderInfraManifest(_node: ControlPlaneNodeSpec, target: ControlPlaneTa
|
||||
addNamespace(target.ciNamespace);
|
||||
addNamespace(target.runtimeNamespace);
|
||||
addNamespace(target.gitMirror.namespace);
|
||||
if (_node.registry.mode === "k8s-workload") addNamespace(_node.registry.namespace);
|
||||
manifests.push(...registryInfraManifest(_node.registry, labels));
|
||||
manifests.push(
|
||||
{ apiVersion: "v1", kind: "ServiceAccount", metadata: { name: target.tekton.serviceAccountName, namespace: target.ciNamespace, labels } },
|
||||
tektonRuntimeObserverRole(target, labels),
|
||||
@@ -2791,6 +2834,13 @@ function optionalStringField(obj: Record<string, unknown>, key: string, path: st
|
||||
return value;
|
||||
}
|
||||
|
||||
function nullableStringField(obj: Record<string, unknown>, key: string, path: string): string | null {
|
||||
const value = obj[key];
|
||||
if (value === undefined || value === null) return null;
|
||||
if (typeof value !== "string" || value.length === 0) throw new Error(`${path}.${key} must be a non-empty string when set`);
|
||||
return value;
|
||||
}
|
||||
|
||||
function absoluteConfigPathField(obj: Record<string, unknown>, key: string, path: string): string {
|
||||
const value = stringField(obj, key, path);
|
||||
if (!value.startsWith("/") || value.includes("\0") || value.includes("..")) throw new Error(`${path}.${key} must be an absolute path without '..'`);
|
||||
|
||||
Reference in New Issue
Block a user