fix(hwlab): expose d518 code agent runtime config
This commit is contained in:
@@ -94,6 +94,21 @@ export function nodeRuntimeRenderOverlay(spec: HwlabRuntimeLaneSpec): Record<str
|
||||
stepEnv: spec.stepEnv,
|
||||
observability: spec.observability,
|
||||
runtimeStore: spec.runtimeStore,
|
||||
codeAgentRuntime: spec.codeAgentRuntime === undefined ? undefined : {
|
||||
enabled: spec.codeAgentRuntime.enabled,
|
||||
adapter: spec.codeAgentRuntime.adapter,
|
||||
managerUrl: spec.codeAgentRuntime.managerUrl,
|
||||
apiKeySecretName: spec.codeAgentRuntime.apiKeySecretName,
|
||||
apiKeySecretKey: spec.codeAgentRuntime.apiKeySecretKey,
|
||||
runnerNamespace: spec.codeAgentRuntime.runnerNamespace,
|
||||
secretNamespace: spec.codeAgentRuntime.secretNamespace,
|
||||
repoUrlFrom: spec.codeAgentRuntime.repoUrlFrom,
|
||||
repoUrl: spec.gitReadUrl,
|
||||
providerIdFrom: spec.codeAgentRuntime.providerIdFrom,
|
||||
providerId: spec.nodeId,
|
||||
defaultProviderProfile: spec.codeAgentRuntime.defaultProviderProfile,
|
||||
valuesPrinted: false,
|
||||
},
|
||||
runtimeImageRewrites: spec.runtimeImageRewrites,
|
||||
runtimeImageBuilds: spec.runtimeImageBuilds,
|
||||
registryPrefix: spec.registryPrefix,
|
||||
@@ -1286,6 +1301,165 @@ export function isLocalPostgresObject(name: string, spec: HwlabRuntimeLaneSpec):
|
||||
return true;
|
||||
}
|
||||
|
||||
export function nodeRuntimeCodeAgentRuntimeStatus(spec: HwlabRuntimeLaneSpec, namespaceExists: boolean): Record<string, unknown> {
|
||||
const runtime = spec.codeAgentRuntime;
|
||||
if (runtime === undefined || runtime.enabled === false) return { required: false, ready: true, enabled: runtime?.enabled ?? false };
|
||||
if (!namespaceExists) return { required: true, ready: false, enabled: true, degradedReason: "runtime-namespace-missing" };
|
||||
const managerTarget = nodeRuntimeCodeAgentManagerTarget(runtime.managerUrl, runtime.runnerNamespace);
|
||||
const runnerNamespace = runNodeK3sArgs(spec, ["kubectl", "get", "ns", runtime.runnerNamespace, "-o", "name"], 60);
|
||||
const secretNamespace = runNodeK3sArgs(spec, ["kubectl", "get", "ns", runtime.secretNamespace, "-o", "name"], 60);
|
||||
const managerNamespace = runNodeK3sArgs(spec, ["kubectl", "get", "ns", managerTarget.namespace, "-o", "name"], 60);
|
||||
const managerService = runNodeK3sArgs(spec, ["kubectl", "-n", managerTarget.namespace, "get", "service", managerTarget.serviceName, "-o", "name"], 60);
|
||||
const managerDeployment = runNodeK3sArgs(spec, ["kubectl", "-n", managerTarget.namespace, "get", "deployment", managerTarget.serviceName, "-o", "jsonpath={.status.readyReplicas}{\"\\n\"}{.spec.replicas}{\"\\n\"}"], 60);
|
||||
const [managerReadyReplicasRaw = "", managerDesiredReplicasRaw = ""] = managerDeployment.stdout.split(/\r?\n/u);
|
||||
const managerReadyReplicas = numericField(managerReadyReplicasRaw);
|
||||
const managerDesiredReplicas = numericField(managerDesiredReplicasRaw);
|
||||
const managerDeploymentReady = managerDeployment.exitCode === 0 && (managerReadyReplicas ?? 0) >= Math.max(1, managerDesiredReplicas ?? 1);
|
||||
const apiKey = secretKeyStatus(spec, runtime.apiKeySecretName, runtime.apiKeySecretKey);
|
||||
const cloudApiEnv = nodeRuntimeCodeAgentCloudApiEnvStatus(spec, runtime);
|
||||
const ready = runnerNamespace.exitCode === 0
|
||||
&& secretNamespace.exitCode === 0
|
||||
&& managerNamespace.exitCode === 0
|
||||
&& managerService.exitCode === 0
|
||||
&& managerDeploymentReady
|
||||
&& apiKey.present === true
|
||||
&& cloudApiEnv.ready === true;
|
||||
const degradedReason = ready
|
||||
? undefined
|
||||
: runnerNamespace.exitCode !== 0
|
||||
? "agentrun-runner-namespace-missing"
|
||||
: secretNamespace.exitCode !== 0
|
||||
? "agentrun-secret-namespace-missing"
|
||||
: managerNamespace.exitCode !== 0
|
||||
? "agentrun-manager-namespace-missing"
|
||||
: managerService.exitCode !== 0
|
||||
? "agentrun-manager-service-missing"
|
||||
: !managerDeploymentReady
|
||||
? "agentrun-manager-deployment-not-ready"
|
||||
: apiKey.present !== true
|
||||
? "agentrun-api-key-secret-missing"
|
||||
: "hwlab-cloud-api-code-agent-env-mismatch";
|
||||
return {
|
||||
required: true,
|
||||
enabled: true,
|
||||
ready,
|
||||
degradedReason,
|
||||
adapter: runtime.adapter,
|
||||
managerUrl: runtime.managerUrl,
|
||||
manager: {
|
||||
namespace: managerTarget.namespace,
|
||||
serviceName: managerTarget.serviceName,
|
||||
serviceExists: managerService.exitCode === 0,
|
||||
deploymentReady: managerDeploymentReady,
|
||||
readyReplicas: managerReadyReplicas,
|
||||
desiredReplicas: managerDesiredReplicas,
|
||||
namespaceResult: compactRuntimeCommand(managerNamespace),
|
||||
serviceResult: compactRuntimeCommand(managerService),
|
||||
deploymentResult: compactRuntimeCommand(managerDeployment),
|
||||
},
|
||||
runnerNamespace: {
|
||||
name: runtime.runnerNamespace,
|
||||
exists: runnerNamespace.exitCode === 0,
|
||||
result: compactRuntimeCommand(runnerNamespace),
|
||||
},
|
||||
secretNamespace: {
|
||||
name: runtime.secretNamespace,
|
||||
exists: secretNamespace.exitCode === 0,
|
||||
result: compactRuntimeCommand(secretNamespace),
|
||||
},
|
||||
apiKey,
|
||||
cloudApiEnv,
|
||||
repoUrlFrom: runtime.repoUrlFrom,
|
||||
providerIdFrom: runtime.providerIdFrom,
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function nodeRuntimeCodeAgentManagerTarget(managerUrl: string, fallbackNamespace: string): { namespace: string; serviceName: string } {
|
||||
let parsed: URL | null = null;
|
||||
try {
|
||||
parsed = new URL(managerUrl);
|
||||
} catch {
|
||||
parsed = null;
|
||||
}
|
||||
const host = parsed?.hostname ?? "";
|
||||
const parts = host.split(".").filter(Boolean);
|
||||
if (parts.length >= 3 && parts[2] === "svc") return { serviceName: parts[0], namespace: parts[1] };
|
||||
return { serviceName: parts[0] || "agentrun-mgr", namespace: parts[1] || fallbackNamespace };
|
||||
}
|
||||
|
||||
function nodeRuntimeCodeAgentCloudApiEnvStatus(spec: HwlabRuntimeLaneSpec, runtime: NonNullable<HwlabRuntimeLaneSpec["codeAgentRuntime"]>): Record<string, unknown> {
|
||||
const deployment = runNodeK3sArgs(spec, ["kubectl", "-n", spec.runtimeNamespace, "get", "deployment", "hwlab-cloud-api", "-o", "json"], 60);
|
||||
if (deployment.exitCode !== 0) {
|
||||
return {
|
||||
ready: false,
|
||||
deploymentExists: false,
|
||||
mismatches: [{ name: "hwlab-cloud-api", reason: "deployment-missing" }],
|
||||
result: compactCodeAgentDeploymentProbeResult(deployment),
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(deployment.stdout) as unknown;
|
||||
} catch (error) {
|
||||
return {
|
||||
ready: false,
|
||||
deploymentExists: true,
|
||||
mismatches: [{ name: "hwlab-cloud-api", reason: "deployment-json-invalid", message: error instanceof Error ? error.message : String(error) }],
|
||||
result: compactCodeAgentDeploymentProbeResult(deployment),
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
const deploy = record(parsed);
|
||||
const specRecord = record(record(record(deploy.spec).template).spec);
|
||||
const containers = Array.isArray(specRecord.containers) ? specRecord.containers.map(record) : [];
|
||||
const container = containers.find((item) => item.name === "hwlab-cloud-api") ?? containers[0];
|
||||
const env = Array.isArray(container?.env) ? container.env.map(record) : [];
|
||||
const envByName = new Map(env.map((item) => [String(item.name || ""), item]));
|
||||
const mismatches: Array<Record<string, unknown>> = [];
|
||||
const expectValue = (name: string, expected: string): void => {
|
||||
const item = envByName.get(name);
|
||||
const value = typeof item?.value === "string" ? item.value : null;
|
||||
if (value !== expected) mismatches.push({ name, expected, value, kind: "value" });
|
||||
};
|
||||
const expectSecret = (name: string, expectedSecret: string, expectedKey: string): void => {
|
||||
const item = envByName.get(name);
|
||||
const secretRef = record(record(item?.valueFrom).secretKeyRef);
|
||||
if (secretRef.name !== expectedSecret || secretRef.key !== expectedKey) {
|
||||
mismatches.push({ name, expectedSecret, expectedKey, secret: secretRef.name ?? null, key: secretRef.key ?? null, kind: "secretKeyRef" });
|
||||
}
|
||||
};
|
||||
expectValue("HWLAB_CODE_AGENT_ADAPTER", runtime.adapter);
|
||||
expectValue("AGENTRUN_MGR_URL", runtime.managerUrl);
|
||||
expectSecret("AGENTRUN_API_KEY", runtime.apiKeySecretName, runtime.apiKeySecretKey);
|
||||
expectValue("HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE", runtime.runnerNamespace);
|
||||
expectValue("HWLAB_CODE_AGENT_AGENTRUN_SECRET_NAMESPACE", runtime.secretNamespace);
|
||||
expectValue("HWLAB_CODE_AGENT_AGENTRUN_REPO_URL", spec.gitReadUrl);
|
||||
expectValue("HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID", spec.nodeId);
|
||||
expectValue("HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE", runtime.defaultProviderProfile);
|
||||
return {
|
||||
ready: mismatches.length === 0,
|
||||
deploymentExists: true,
|
||||
deploymentName: "hwlab-cloud-api",
|
||||
containerName: container?.name ?? null,
|
||||
checkedEnvCount: 8,
|
||||
mismatches,
|
||||
result: compactCodeAgentDeploymentProbeResult(deployment),
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function compactCodeAgentDeploymentProbeResult(result: CommandResult): Record<string, unknown> {
|
||||
return {
|
||||
exitCode: result.exitCode,
|
||||
stdoutBytes: Buffer.byteLength(result.stdout, "utf8"),
|
||||
stderrBytes: Buffer.byteLength(result.stderr, "utf8"),
|
||||
stderrTail: result.stderr.slice(-600),
|
||||
timedOut: result.timedOut === true,
|
||||
};
|
||||
}
|
||||
|
||||
export function externalPostgresBridgeStatus(spec: HwlabRuntimeLaneSpec, namespaceExists: boolean): Record<string, unknown> {
|
||||
const pg = hwlabRuntimeActiveExternalPostgres(spec);
|
||||
if (pg === undefined) return { required: false, ready: true };
|
||||
|
||||
Reference in New Issue
Block a user