fix: preflight codex stdio mount resources

This commit is contained in:
Codex
2026-05-24 07:52:14 +00:00
parent 51c2531f6f
commit 48abac41c6
5 changed files with 199 additions and 7 deletions
+115 -4
View File
@@ -39,7 +39,11 @@ const forbiddenControlPlanePattern = /docker-desktop|desktop-control-plane|127\.
const requiredDevSecretRefs = Object.freeze([
Object.freeze({ secretName: "hwlab-cloud-api-dev-db", secretKey: "database-url" }),
Object.freeze({ secretName: "hwlab-cloud-api-dev-db-admin", secretKey: "admin-url" }),
Object.freeze({ secretName: "hwlab-code-agent-provider", secretKey: "openai-api-key" })
Object.freeze({ secretName: "hwlab-code-agent-provider", secretKey: "openai-api-key" }),
Object.freeze({ secretName: "hwlab-code-agent-codex-auth", secretKey: "auth.json" })
]);
const requiredDevConfigMapRefs = Object.freeze([
Object.freeze({ configMapName: "hwlab-code-agent-codex-config", configMapKey: "config.toml" })
]);
const lockAnnotationPrefix = "hwlab.pikastech.local";
const lockAnnotationFields = {
@@ -1288,6 +1292,13 @@ function parseSecretDescribeKeys(stdout) {
return [...keys].sort();
}
function parseKeyLines(stdout) {
return String(stdout ?? "")
.split(/\r?\n/u)
.map((line) => line.trim())
.filter(Boolean);
}
function commandObservation(args, result) {
return {
command: shellCommand("kubectl", args),
@@ -1483,6 +1494,97 @@ function secretRefBlocker(ref, observation) {
});
}
async function observeRequiredConfigMapRef(ctx, kubectlContext, args, ref) {
const existsArgs = ["-n", args.targetNamespace, "get", "configmap", ref.configMapName, "-o", "name"];
const keyArgs = [
"-n",
args.targetNamespace,
"get",
"configmap",
ref.configMapName,
"-o",
"go-template={{range $k,$v := .data}}{{printf \"%s\\n\" $k}}{{end}}"
];
const exists = await preflightKubectl(ctx, kubectlContext, existsArgs, { timeoutMs: 10000 });
if (exists.code !== 0) {
return {
configMapName: ref.configMapName,
configMapKey: ref.configMapKey,
status: "missing-configmap",
exists: false,
keyPresent: false,
keysObserved: [],
existenceCommand: shellCommand("kubectl", existsArgs),
keyCommand: null,
error: commandSummary(exists),
configMapValueRead: false,
configMapValuePrinted: false
};
}
const keys = await preflightKubectl(ctx, kubectlContext, keyArgs, { timeoutMs: 10000 });
if (keys.code !== 0) {
return {
configMapName: ref.configMapName,
configMapKey: ref.configMapKey,
status: "key-observation-blocked",
exists: true,
keyPresent: false,
keysObserved: [],
existenceCommand: shellCommand("kubectl", existsArgs),
keyCommand: shellCommand("kubectl", keyArgs),
error: commandSummary(keys),
configMapValueRead: false,
configMapValuePrinted: false
};
}
const keysObserved = parseKeyLines(keys.stdout);
const keyPresent = keysObserved.includes(ref.configMapKey);
return {
configMapName: ref.configMapName,
configMapKey: ref.configMapKey,
status: keyPresent ? "present" : "missing-key",
exists: true,
keyPresent,
keysObserved,
existenceCommand: shellCommand("kubectl", existsArgs),
keyCommand: shellCommand("kubectl", keyArgs),
configMapValueRead: false,
configMapValuePrinted: false
};
}
function configMapRefBlocker(ref, observation) {
const scope = `configmap:${ref.configMapName}/${ref.configMapKey}`;
if (observation.status === "missing-configmap") {
return blocker({
type: "runtime_blocker",
scope,
reason: `Required DEV ConfigMap ${ref.configMapName} was not observed in ${defaultNamespace}.`,
impact: "The Code Agent Codex stdio provider pod would fail to mount config.toml after mutation.",
safeNextAction: `Create or restore ConfigMap ${ref.configMapName}/${ref.configMapKey} in ${defaultNamespace}, then retry DEV CD.`,
retryable: true
});
}
if (observation.status === "key-observation-blocked") {
return blocker({
type: "runtime_blocker",
scope,
reason: `Required DEV ConfigMap ${ref.configMapName} exists but key names could not be verified.`,
impact: "DEV CD cannot prove the Code Agent Codex config mount before applying workloads.",
safeNextAction: `Restore key-name visibility for ${ref.configMapName}, then retry.`,
retryable: true
});
}
return blocker({
type: "runtime_blocker",
scope,
reason: `Required DEV ConfigMap key ${ref.configMapName}/${ref.configMapKey} was not observed.`,
impact: "The Code Agent Codex stdio provider pod would reference a missing config.toml key after mutation.",
safeNextAction: `Add key ${ref.configMapKey} to ConfigMap ${ref.configMapName}, then retry DEV CD.`,
retryable: true
});
}
async function runDevCdPreflight({ ctx, args, kubectlContext }) {
const blockers = [];
const preflight = {
@@ -1502,11 +1604,14 @@ async function runDevCdPreflight({ ctx, args, kubectlContext }) {
},
controlPlane: null,
secretRefs: [],
configMaps: [],
safety: {
writeSideEffectsAttempted: false,
prodTouched: false,
secretValuesRead: false,
secretValuesPrinted: false,
configMapValuesRead: false,
configMapValuesPrinted: false,
secretKeyNamesOnly: true
},
blockers
@@ -1560,14 +1665,20 @@ async function runDevCdPreflight({ ctx, args, kubectlContext }) {
}
if (blockers.length === 0) {
preflight.secretRefs = await Promise.all(
requiredDevSecretRefs.map((ref) => observeRequiredSecretRef(ctx, kubectlContext, args, ref))
);
[preflight.secretRefs, preflight.configMaps] = await Promise.all([
Promise.all(requiredDevSecretRefs.map((ref) => observeRequiredSecretRef(ctx, kubectlContext, args, ref))),
Promise.all(requiredDevConfigMapRefs.map((ref) => observeRequiredConfigMapRef(ctx, kubectlContext, args, ref)))
]);
for (const [index, observation] of preflight.secretRefs.entries()) {
if (observation.status !== "present") {
blockers.push(secretRefBlocker(requiredDevSecretRefs[index], observation));
}
}
for (const [index, observation] of preflight.configMaps.entries()) {
if (observation.status !== "present") {
blockers.push(configMapRefBlocker(requiredDevConfigMapRefs[index], observation));
}
}
}
preflight.status = blockers.length === 0 ? "pass" : "blocked";