import { execFileSync } from "node:child_process"; const namespace = process.env.NAMESPACE || ""; const configMap = process.env.CONFIGMAP || ""; const followerIds = parseFollowerIds(process.env.FOLLOWERS_JSON || "[]"); const maxTimingStages = Number(process.env.MAX_TIMING_STAGES || "24"); function parseFollowerIds(text) { try { const parsed = JSON.parse(text); return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string" && item.length > 0) : []; } catch { return []; } } function kubectlConfigMap() { try { const stdout = execFileSync("kubectl", ["-n", namespace, "get", "configmap", configMap, "-o", "json"], { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"], }); return { ok: true, present: true, object: JSON.parse(stdout), error: "" }; } catch (error) { const stderr = String(error?.stderr || error?.message || ""); if (/not found/i.test(stderr)) return { ok: true, present: false, object: null, error: stderr }; return { ok: false, present: false, object: null, error: stderr || "kubectl configmap read failed" }; } } function compactStateText(text) { if (typeof text !== "string" || text.length === 0) return null; let state; try { state = JSON.parse(text); } catch { return null; } return { id: stringOrNull(state.id), adapter: stringOrNull(state.adapter), enabled: state.enabled === true, phase: stringOrNull(state.phase), source: compactSource(state.source), target: compactTarget(state.target), lastTriggeredSha: stringOrNull(state.lastTriggeredSha), lastSucceededSha: stringOrNull(state.lastSucceededSha), pipelineRun: stringOrNull(state.pipelineRun), inFlightJob: stringOrNull(state.inFlightJob), controller: compactController(state.controller), decision: stringOrNull(state.decision), dryRun: state.dryRun === true, updatedAt: stringOrNull(state.updatedAt), timings: compactTimings(state.timings), warnings: arrayStrings(state.warnings).slice(0, 6), stateFormat: stringOrNull(state.stateFormat), }; } function compactSource(source) { const value = recordOrNull(source); if (value === null) return null; return { repository: stringOrNull(value.repository), branch: stringOrNull(value.branch), branchRef: stringOrNull(value.branchRef), snapshotPrefix: stringOrNull(value.snapshotPrefix), observedSha: stringOrNull(value.observedSha), }; } function compactTarget(target) { const value = recordOrNull(target); if (value === null) return null; return { node: stringOrNull(value.node), lane: stringOrNull(value.lane), namespace: stringOrNull(value.namespace), sentinel: stringOrNull(value.sentinel), targetSha: stringOrNull(value.targetSha), }; } function compactController(controller) { const value = recordOrNull(controller); if (value === null) return null; return { mode: stringOrNull(value.mode), stateConfigMap: stringOrNull(value.stateConfigMap), leaseName: stringOrNull(value.leaseName), }; } function compactTimings(timings) { const value = recordOrNull(timings); if (value === null) return null; return { budgetSeconds: numberOrNull(value.budgetSeconds), totalSeconds: numberOrNull(value.totalSeconds), totalStatus: stringOrNull(value.totalStatus), totalSource: stringOrNull(value.totalSource), startedAt: stringOrNull(value.startedAt), finishedAt: stringOrNull(value.finishedAt), overBudget: typeof value.overBudget === "boolean" ? value.overBudget : null, stages: arrayRecords(value.stages).slice(0, maxTimingStages).map(compactStageTiming), }; } function compactStageTiming(stage) { return { stage: stringOrNull(stage.stage), status: stringOrNull(stage.status), seconds: numberOrNull(stage.seconds), budgetSeconds: numberOrNull(stage.budgetSeconds), source: stringOrNull(stage.source), object: stringOrNull(stage.object), }; } function recordOrNull(value) { return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null; } function arrayRecords(value) { return Array.isArray(value) ? value.filter((item) => recordOrNull(item) !== null) : []; } function arrayStrings(value) { return Array.isArray(value) ? value.filter((item) => typeof item === "string") : []; } function stringOrNull(value) { return typeof value === "string" && value.length > 0 ? value : null; } function numberOrNull(value) { return typeof value === "number" && Number.isFinite(value) ? value : null; } const result = kubectlConfigMap(); const errors = []; const stateByFollower = {}; const valueBytes = {}; if (result.ok && result.present) { const data = recordOrNull(result.object?.data) || {}; for (const id of followerIds) { const text = typeof data[id] === "string" ? data[id] : ""; if (text.length === 0) continue; valueBytes[id] = Buffer.byteLength(text, "utf8"); const compact = compactStateText(text); if (compact === null) errors.push(`${id}: invalid state json`); else stateByFollower[id] = compact; } } if (!result.ok) errors.push(result.error); process.stdout.write(JSON.stringify({ ok: result.ok && errors.length === 0, present: result.present, stateByFollower, valueBytes, errors, statusAuthority: "target-node-summary", parsedDownstreamCliOutput: false, }));