Merge pull request #1655 from pikasTech/fix/1653-node-status-target
Pipelines as Code CI / hwlab-web-probe-sentinel-nc01- Success
Pipelines as Code CI / unidesk-host- Success

修复 HWLAB node status 的 target override 假失败
This commit is contained in:
Lyon
2026-07-10 11:52:27 +08:00
committed by GitHub
2 changed files with 22 additions and 19 deletions
+7 -16
View File
@@ -14,7 +14,7 @@ import { runCommand, type CommandResult } from "../command";
import { startJob } from "../jobs";
import { classifySshTcpPoolFailure } from "../ssh";
import { HWLAB_NODE_CONTROL_PLANE_CONFIG_PATH, hwlabNodeControlPlaneInfraHelp, runHwlabNodeControlPlaneInfra } from "../hwlab-node-control-plane";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, hwlabRuntimeLaneSpecForNode, hwlabRuntimeNodeIds, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeObservabilityRecordingRuleSpec, type HwlabRuntimeObservabilitySpec, type HwlabRuntimeObservabilityWarningAlertSpec, type HwlabRuntimePublicExposureSpec, type HwlabRuntimeWebProbeAlertThresholdsSpec, type HwlabRuntimeWebProbeProjectManagementSpec } from "../hwlab-node-lanes";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpecForNode, hwlabRuntimeNodeIds, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeObservabilityRecordingRuleSpec, type HwlabRuntimeObservabilitySpec, type HwlabRuntimeObservabilityWarningAlertSpec, type HwlabRuntimePublicExposureSpec, type HwlabRuntimeWebProbeAlertThresholdsSpec, type HwlabRuntimeWebProbeProjectManagementSpec } from "../hwlab-node-lanes";
import { nodeWebProbeScriptRunnerSource } from "../hwlab-node-web-probe-runner-source";
import { nodeWebObserveAnalyzerSource } from "../hwlab-node-web-observe-analyzer-source";
import { nodeWebObserveRunnerSource } from "../hwlab-node-web-observe-runner-source";
@@ -26,7 +26,7 @@ import { runWebProbeSentinelCommand, type WebProbeSentinelOptions } from "../hwl
import { hwlabNodeHelp, hwlabNodeObservabilityHelp, hwlabNodeWebProbeHelp } from "../hwlab-node-help";
import { compactWebProbeResult, compactWebProbeScriptResult } from "../hwlab-node-web-probe-summary";
import { nodeObservabilityRecordingRuleExpression, nodeObservabilityRecordingRuleSummaries, nodeObservabilityWarningAlertExpression, nodeObservabilityWarningAlertSummaries } from "../hwlab-node-observability-promql";
import { runDelegatedHwlabNodeCommand, type DelegatedNodeDomain } from "../hwlab-node-transport";
import type { DelegatedNodeDomain } from "../hwlab-node-transport";
import { runHwlabFakeModelProviderCommand } from "../hwlab-fake-model-provider";
import type { RenderedCliResult } from "../output";
@@ -41,9 +41,9 @@ import { nodeRuntimeUnsupportedAction } from "./runtime-common";
import { runNodeEndpointBridge } from "./secret-scripts";
import { nodeRuntimeSourceWorkspaceCommand } from "./source-workspace";
import { nodeRuntimeGitMirrorRun, nodeRuntimeGitMirrorStatus, nodeScopedFullOutput, withNodeRuntimeGitMirrorRendered } from "./status";
import { assertNodeId, positiveIntegerOption, requiredOption, stripOption } from "./utils";
import { assertNodeId, positiveIntegerOption, requiredOption } from "./utils";
import { legacyHwlabNodeWebProbeUnsupported } from "../web-probe";
import { rewriteDelegatedNodeResult, startNodeDelegatedJob } from "./web-probe";
import { startNodeDelegatedJob } from "./web-probe";
import { assertKnownOptions } from "./web-probe-observe";
export { hwlabNodeHelp, hwlabNodeWebProbeHelp, hwlabNodeObservabilityHelp } from "../hwlab-node-help";
@@ -590,7 +590,6 @@ export function parseNodeObservabilityOptions(args: string[]): NodeObservability
export async function runNodeDelegatedDomain(config: Config, domain: DelegatedNodeDomain, args: string[]): Promise<Record<string, unknown> | RenderedCliResult> {
const scoped = parseNodeScopedDelegatedOptions(domain, args);
const defaultSpec = hwlabRuntimeLaneSpec(scoped.lane);
if (domain === "control-plane" && scoped.action === "public-exposure") {
return runNodePublicExposure({
action: "public-exposure",
@@ -615,7 +614,7 @@ export async function runNodeDelegatedDomain(config: Config, domain: DelegatedNo
if (domain === "control-plane" && scoped.action === "allow-endpoint-bridge") {
return runNodeEndpointBridge(scoped);
}
if (domain === "control-plane" && scoped.node !== defaultSpec.nodeId) {
if (domain === "control-plane") {
if (scoped.action === "status") {
const result = nodeRuntimeControlPlaneStatus(scoped);
if (scoped.originalArgs.includes("--raw")) return result;
@@ -628,7 +627,7 @@ export async function runNodeDelegatedDomain(config: Config, domain: DelegatedNo
}
return nodeRuntimeUnsupportedAction(scoped);
}
if (domain === "git-mirror" && scoped.node !== defaultSpec.nodeId) {
if (domain === "git-mirror") {
if (scoped.action === "status") {
const result = nodeRuntimeGitMirrorStatus(scoped);
return nodeScopedFullOutput(scoped) ? result : withNodeRuntimeGitMirrorRendered(result, scoped);
@@ -640,13 +639,5 @@ export async function runNodeDelegatedDomain(config: Config, domain: DelegatedNo
}
return nodeRuntimeUnsupportedAction(scoped);
}
if (domain === "control-plane" && scoped.action === "trigger-current" && scoped.confirm && !scoped.dryRun && !scoped.wait) {
return startNodeDelegatedJob(scoped);
}
if (domain === "git-mirror" && (scoped.action === "sync" || scoped.action === "flush") && scoped.confirm && !scoped.dryRun && !scoped.wait) {
return startNodeDelegatedJob(scoped);
}
const delegatedArgs = stripOption(args, "--node");
const result = await runDelegatedHwlabNodeCommand(config, domain, delegatedArgs);
return rewriteDelegatedNodeResult(result, scoped);
return nodeRuntimeUnsupportedAction(scoped);
}
+15 -3
View File
@@ -742,7 +742,7 @@ export function withNodeRuntimeControlPlaneStatusRendered(result: Record<string,
const publicProbe = record(result.publicProbe);
const gitMirror = record(result.gitMirror);
const next = record(result.next);
const diagnostic = record(publicProbe.diagnostic);
const publicProbeDetail = nodeRuntimePublicProbeDetail(publicProbe);
const notReadyWorkloads = Array.isArray(runtime.notReadyWorkloads) ? runtime.notReadyWorkloads.map((item) => webObserveText(item)).filter(Boolean) : [];
const runtimeDetail = [
`workloads=${webObserveText(runtime.workloadReady)}`,
@@ -781,7 +781,7 @@ export function withNodeRuntimeControlPlaneStatusRendered(result: Record<string,
["pipeline", pipelineRun.ready === true ? "ok" : pipelineRun.exists === true ? webObserveText(pipelineRun.status) : "missing", pipelineDetail],
["argo", argo.ready === true ? "ok" : "failed", `${webObserveText(argo.syncStatus)}/${webObserveText(argo.health)} rev=${shortValue(argo.syncRevision)} target=${shortValue(argo.targetGitopsRevision)} op=${webObserveText(argoOperation.phase)}`],
["runtime", runtime.ready === true ? "ok" : "failed", runtimeDetail],
["public", publicProbe.ready === true ? "ok" : "failed", webObserveShort(webObserveText(diagnostic.kind ?? diagnostic.message), 80)],
["public", publicProbe.ready === true ? "ok" : "failed", publicProbeDetail],
["git-mirror", gitMirror.ready === true ? "ok" : "failed", `snapshot=${webObserveText(gitMirror.sourceSnapshotReady)} pending=${webObserveText(gitMirror.pendingFlush)} inSync=${webObserveText(gitMirror.githubInSync)}`],
],
),
@@ -824,6 +824,7 @@ export function withNodeRuntimeControlPlaneStatusFullRendered(result: Record<str
const argoEvents = arrayRecords(argoDiagnostics.events);
const runtimeSummary = record(summary.runtime);
const publicProbe = record(summary.publicProbe);
const publicProbeDetail = nodeRuntimePublicProbeDetail(publicProbe);
const gitMirror = record(summary.gitMirror);
const runtime = record(result.runtime);
const bridge = record(runtime.externalPostgresBridge);
@@ -875,7 +876,7 @@ export function withNodeRuntimeControlPlaneStatusFullRendered(result: Record<str
["pipeline", pipelineRun.ready === true ? "ok" : pipelineRun.exists === true ? webObserveText(pipelineRun.status) : "missing", webObserveShort(webObserveText(pipelineRun.reason ?? pipelineRun.message), 80)],
["argo", argo.ready === true ? "ok" : "failed", `${webObserveText(argo.syncStatus)}/${webObserveText(argo.health)} rev=${shortValue(argo.syncRevision)} target=${shortValue(argo.targetGitopsRevision)}`],
["runtime", runtimeSummary.ready === true ? "ok" : "failed", `namespace=${webObserveText(runtimeSummary.namespace)} workloads=${webObserveText(runtimeSummary.workloadReady)} pg=${webObserveText(runtimeSummary.externalPostgresReady ?? runtimeSummary.localPostgresReady)}`],
["public", publicProbe.ready === true ? "ok" : "failed", webObserveShort(webObserveText(record(publicProbe.diagnostic).kind ?? record(publicProbe.diagnostic).message), 80)],
["public", publicProbe.ready === true ? "ok" : "failed", publicProbeDetail],
["git-mirror", gitMirror.ready === true ? "ok" : "failed", `pending=${webObserveText(gitMirror.pendingFlush)} inSync=${webObserveText(gitMirror.githubInSync)}`],
],
),
@@ -970,6 +971,17 @@ export function withNodeRuntimeControlPlaneStatusFullRendered(result: Record<str
return { ...result, renderedText, contentType: "text/plain" };
}
function nodeRuntimePublicProbeDetail(publicProbe: Record<string, unknown>): string {
const web = record(publicProbe.web);
const apiHealth = record(publicProbe.apiHealth);
const diagnostic = record(publicProbe.diagnostic);
return [
`web=${webObserveShort(webObserveText(web.url), 80)}(${webObserveText(web.httpStatus)})`,
`api=${webObserveShort(webObserveText(apiHealth.url), 80)}(${webObserveText(apiHealth.httpStatus)})`,
webObserveShort(webObserveText(diagnostic.kind ?? diagnostic.message), 80),
].filter((item) => item !== "-").join(" ");
}
function arrayRecords(value: unknown): Record<string, unknown>[] {
return Array.isArray(value)
? value.filter((item): item is Record<string, unknown> => typeof item === "object" && item !== null && !Array.isArray(item))