import { describe, expect, test } from "bun:test"; import { spawnSync } from "node:child_process"; import { rootPath } from "./config"; import { isRenderedCliResult } from "./output"; import { runPlatformObservabilityCommand } from "./platform-infra-observability"; import { resolveTarget } from "./platform-infra-observability/actions"; import { isKubernetesLabelValue, isKubernetesQualifiedName, readObservabilityConfig } from "./platform-infra-observability/config"; import { renderObservabilityPlanFailure } from "./platform-infra-observability/plan-render"; import { prometheusMetaLabel, re2Literal } from "./platform-infra-observability/prometheus"; import { statusScript } from "./platform-infra-observability/search-script"; import { renderManifest } from "./platform-infra-observability/trace-script"; describe("platform-infra observability progressive disclosure", () => { test("default plan is a bounded table while full and raw preserve the complete plan", async () => { const compact = await runPlatformObservabilityCommand({} as never, ["plan", "--target", "NC01"]); expect(isRenderedCliResult(compact)).toBe(true); if (!isRenderedCliResult(compact)) throw new Error("expected rendered plan"); expect(Buffer.byteLength(compact.renderedText, "utf8")).toBeLessThan(10_240); expect(compact.renderedText).toContain("serviceConnections=8"); expect(compact.renderedText).toContain("configRefs=6/6 missing=0"); expect(compact.renderedText).toContain("prometheus=enabled service=prometheus targets=NC01"); expect(compact.renderedText).toContain("scrapeSelector=unidesk.ai/metrics=true"); expect(compact.renderedText).toContain("--full"); expect(compact.renderedText).toContain("--raw"); for (const mode of ["--full", "--raw"]) { const expanded = await runPlatformObservabilityCommand({} as never, ["plan", "--target", "NC01", mode]); expect(isRenderedCliResult(expanded)).toBe(false); expect(expanded).toMatchObject({ action: "platform-infra-observability-plan", mutation: false, renderPlan: { target: { id: "NC01", route: "NC01:k3s", namespace: "platform-infra" } }, }); expect((expanded as Record).renderPlan.instrumentation).toHaveLength(8); expect((expanded as Record).config.metricsBackend).toMatchObject({ type: "prometheus", enabled: true }); } }); test("real outer CLI keeps plan below the stdout dump threshold", () => { const result = cli(["platform-infra", "observability", "plan", "--target", "NC01"]); expect(result.status).toBe(0); expect(Buffer.byteLength(result.stdout, "utf8")).toBeLessThan(10_240); expect(result.stdout).toContain("platform-infra observability plan (ok)"); expect(result.stdout).toContain("configRefs=6/6 missing=0"); expect(result.stdout).not.toContain("outputTruncated"); expect(result.stdout).not.toContain("/tmp/unidesk-cli-output"); }); test("Prometheus manifests and runtime access only apply to YAML-selected targets", async () => { const observability = readObservabilityConfig(); const nc01 = resolveTarget(observability, "NC01"); const d518 = resolveTarget(observability, "D518"); const jd01 = resolveTarget(observability, "JD01"); const nc01Manifest = renderManifest(observability, nc01); for (const target of [d518, jd01]) { const manifest = renderManifest(observability, target); expect(manifest).not.toContain("kind: ClusterRole\nmetadata:\n name: platform-infra-prometheus"); expect(manifest).not.toContain("kind: PersistentVolumeClaim\nmetadata:\n name: prometheus-data"); expect(manifest).not.toContain("app.kubernetes.io/component: metrics-backend"); const plan = await runPlatformObservabilityCommand({} as never, ["plan", "--target", target.id]); expect(isRenderedCliResult(plan)).toBe(true); if (!isRenderedCliResult(plan)) throw new Error("expected rendered plan"); expect(plan.renderedText).toContain("prometheus=disabled-for-target"); expect(plan.renderedText).toContain("objects=8"); const script = statusScript(observability, target, false); expect(script).not.toContain("capture_json metrics_deployments"); expect(script).not.toContain("prometheus-ready"); const query = await runPlatformObservabilityCommand({} as never, ["metrics-query", "--target", target.id, "--query", "up", "--full"]); expect(query).toMatchObject({ metrics: { enabled: false, disposition: "disabled-for-target", targetIds: ["NC01"] } }); } expect(nc01Manifest).toContain("kind: ClusterRole\nmetadata:\n name: platform-infra-prometheus"); expect(nc01Manifest).toContain("kind: PersistentVolumeClaim\nmetadata:\n name: prometheus-data"); }); test("Prometheus relabel rules prefer an explicit path and only default when absent", () => { const observability = readObservabilityConfig(); const manifest = renderManifest(observability, resolveTarget(observability, "NC01")); const explicitPath = "source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]\n action: replace\n target_label: __metrics_path__\n regex: (/.+)"; const defaultPath = "source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]\n action: replace\n target_label: __metrics_path__\n regex: ^$\n replacement: /metrics"; expect(manifest).toContain("source_labels: [__meta_kubernetes_pod_label_unidesk_ai_metrics]"); expect(manifest).toContain("regex: '^true$'"); expect(manifest).toContain(explicitPath); expect(manifest).toContain(defaultPath); expect(manifest.indexOf(explicitPath)).toBeLessThan(manifest.indexOf(defaultPath)); }); test("Prometheus selector rendering uses qualified names, stable meta labels and literal RE2", () => { const observability = readObservabilityConfig(); observability.metricsBackend.discovery.labelSelector = { key: "metrics.example.com/release-track", value: "v1.2-beta", }; observability.metricsBackend.discovery.annotationKeys.scrape = "prometheus.io/scrape-enabled"; const manifest = renderManifest(observability, resolveTarget(observability, "NC01")); expect(manifest).toContain("__meta_kubernetes_pod_label_metrics_example_com_release_track"); expect(manifest).toContain("__meta_kubernetes_pod_annotation_prometheus_io_scrape_enabled"); expect(manifest).toContain("regex: '^v1\\.2-beta$'"); expect(prometheusMetaLabel("a.b/c-d_e")).toBe("a_b_c_d_e"); expect(re2Literal("v1.2-beta")).toBe("^v1\\.2-beta$"); expect(isKubernetesQualifiedName("metrics.example.com/release-track")).toBe(true); expect(isKubernetesQualifiedName("metrics.example.com/release/track")).toBe(false); expect(isKubernetesQualifiedName("Metrics.example.com/release-track")).toBe(false); expect(isKubernetesQualifiedName(`${"a".repeat(64)}.example/release-track`)).toBe(false); expect(isKubernetesLabelValue("v1.2-beta")).toBe(true); }); test("query commands expose only scoped help", () => { for (const operation of ["search", "trace", "diagnose-code-agent", "metrics-query"]) { const result = cli(["platform-infra", "observability", operation, "--help"]); expect(result.status).toBe(0); const payload = JSON.parse(result.stdout) as Record; expect(payload.data.scope).toBe(operation); expect(payload.data.command).toBe(`platform-infra observability ${operation}`); expect(payload.data.usage.every((line: string) => line.includes(`observability ${operation}`))).toBe(true); expect(result.stdout).not.toContain("platform-infra sub2api"); expect(result.stdout).not.toContain("platform-infra langbot"); expect(result.stdout).not.toContain("outputTruncated"); } }); test("top observability help is only an operation index", () => { const result = cli(["platform-infra", "observability", "--help"]); expect(result.status).toBe(0); const payload = JSON.parse(result.stdout) as Record; expect(payload.data.operations.map((item: Record) => item.name)).toEqual([ "plan", "apply", "status", "validate", "trace", "search", "diagnose-code-agent", "metrics-query", ]); expect(payload.data.scopedHelp).toContain(" --help"); expect(payload.data.usage).toBeUndefined(); expect(result.stdout).not.toContain("platform-infra sub2api"); }); test("configRef failures name the source and a bounded next command", () => { const rendered = renderObservabilityPlanFailure( new Error("config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01.runtime.namespace is missing segment namespace"), "NC01", ); expect(rendered.ok).toBe(false); expect(rendered.renderedText).toContain("config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01.runtime.namespace"); expect(rendered.renderedText).toContain("rg -n lanes config/hwlab-node-lanes.yaml"); expect(rendered.renderedText).not.toContain("/tmp/unidesk-cli-output"); }); }); function cli(args: string[]): { status: number | null; stdout: string; stderr: string } { const result = spawnSync("bun", ["scripts/cli.ts", ...args], { cwd: rootPath(), encoding: "utf8", timeout: 30_000, env: { ...process.env, NO_COLOR: "1" }, }); expect(result.stdout).not.toBe(""); return { status: result.status, stdout: result.stdout, stderr: result.stderr }; }