支持 provider profile Secret 首次创建

This commit is contained in:
Codex
2026-06-08 02:08:50 +08:00
parent 41886aef80
commit 96bdc262ad
3 changed files with 79 additions and 10 deletions
+14 -4
View File
@@ -110,7 +110,7 @@ export async function setProviderProfileConfig(profileValue: string, body: unkno
"config.toml": base64Data(configToml),
},
};
const applied = await kubectlReplaceSecret(secretManifest, options.kubectlCommand ?? "kubectl");
const applied = await kubectlUpsertSecret(secretManifest, options.kubectlCommand ?? "kubectl");
return {
action: "provider-profile-config-updated",
mutation: true,
@@ -167,7 +167,7 @@ export async function setProviderProfileCredential(profileValue: string, body: u
"config.toml": base64Data(rendered.config.configToml),
},
};
const applied = await kubectlReplaceSecret(secretManifest, options.kubectlCommand ?? "kubectl");
const applied = await kubectlUpsertSecret(secretManifest, options.kubectlCommand ?? "kubectl");
return {
action: "provider-profile-credential-updated",
mutation: true,
@@ -543,14 +543,24 @@ async function kubectlGetSecret(name: string, namespace: string, kubectlCommand:
return parseKubectlObject(result.stdout, "secret");
}
async function kubectlReplaceSecret(manifest: JsonRecord, kubectlCommand: string): Promise<JsonRecord> {
async function kubectlUpsertSecret(manifest: JsonRecord, kubectlCommand: string): Promise<JsonRecord> {
const name = stringPath(manifest, ["metadata", "name"]) ?? "<unknown>";
const namespace = stringPath(manifest, ["metadata", "namespace"]) ?? defaultNamespace;
const replace = await runKubectl(kubectlCommand, ["replace", "-f", "-", "-o", "json"], `${JSON.stringify(manifest)}\n`);
const stdin = `${JSON.stringify(manifest)}\n`;
const replace = await runKubectl(kubectlCommand, ["replace", "-f", "-", "-o", "json"], stdin);
if (replace.code === 0) return await kubectlRemoveLastAppliedAnnotation(kubectlCommand, name, namespace);
if (isKubectlNotFoundFailure(replace)) {
const created = await runKubectl(kubectlCommand, ["create", "-f", "-", "-o", "json"], stdin);
if (created.code === 0) return parseKubectlObject(created.stdout, "provider profile secret create", { redactSecretData: true });
throw new AgentRunError("infra-failed", `kubectl create provider profile secret ${namespace}/${name} failed with code ${created.code}`, { httpStatus: 502, details: redactJson({ stderr: redactText(created.stderr.slice(-2000)), stdout: redactText(created.stdout.slice(-1000)) }) });
}
throw new AgentRunError("infra-failed", `kubectl replace provider profile secret ${namespace}/${name} failed with code ${replace.code}`, { httpStatus: 502, details: redactJson({ stderr: redactText(replace.stderr.slice(-2000)), stdout: redactText(replace.stdout.slice(-1000)) }) });
}
function isKubectlNotFoundFailure(result: { stdout: string; stderr: string }): boolean {
return /notfound|not found|not-found/iu.test(`${result.stderr}\n${result.stdout}`);
}
async function kubectlRemoveLastAppliedAnnotation(kubectlCommand: string, name: string, namespace: string): Promise<JsonRecord> {
const patch = { metadata: { annotations: { [kubectlLastAppliedAnnotation]: null } } };
const result = await runKubectl(kubectlCommand, ["patch", "secret", name, "-n", namespace, "--type", "merge", "-p", JSON.stringify(patch), "-o", "json"]);