fix: 修复 AgentRun provider 假活性与容量可见性

This commit is contained in:
Codex
2026-07-11 04:16:58 +02:00
parent ce5c20f627
commit 04cd3e5f12
21 changed files with 3063 additions and 214 deletions
+151 -9
View File
@@ -39,8 +39,9 @@ import { triggerCurrentYamlLaneConfirmed } from "./cleanup-scripts";
import { readAgentRunClientConfig } from "./config";
import { displayValue } from "./options";
import { pathValue } from "./render";
import { providerSecretActivationPreflight, providerSecretDesiredEncodedFingerprint, providerSecretStagedActivation } from "./provider-activation";
import { startAsyncAgentRunJob } from "./rest-bridge";
import { collectLaneSecretSources, readSecretSourceValue, restartYamlLaneScript, secretSyncScript } from "./secrets";
import { collectLaneSecretSources, inspectSecretSourceValue, restartYamlLaneScript, secretSyncScript } from "./secrets";
import { capture, captureJsonPayload, compactCapture, isGitSha, stringOrNull } from "./utils";
import { yamlLaneK3sSourceStatusScript, yamlLaneSourceBootstrapProbeScript } from "./yaml-lane";
@@ -217,8 +218,8 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
valuesPrinted: false,
};
}
const values = sources.map((source) => ({ spec: source, value: readSecretSourceValue(spec, source) }));
const plan = values.map(({ spec: item, value }) => ({
const inspected = sources.map((source) => ({ spec: source, inspection: inspectSecretSourceValue(spec, source) }));
const plan = inspected.map(({ spec: item, inspection }) => ({
id: item.id,
namespace: item.targetRef.namespace,
secret: item.targetRef.name,
@@ -226,11 +227,105 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
sourceRef: item.sourceRef,
sourceMode: item.sourceMode,
sourceKey: item.sourceKey,
sourcePath: value.redactedPath,
fingerprint: value.fingerprint,
valueBytes: value.valueBytes,
transform: item.transform ?? null,
...inspection.summary,
valuesPrinted: false,
}));
const unavailable = inspected.filter(({ inspection }) => !inspection.ok);
if (unavailable.length > 0) {
return {
ok: false,
command: "agentrun control-plane secret-sync",
mode: options.dryRun || !options.confirm ? "dry-run-blocked" : "confirm-blocked-before-mutation",
mutation: false,
configPath,
target: compactAgentRunLaneStatusTarget(spec),
degradedReason: "lane-secret-source-unavailable",
blockedBeforeMutation: true,
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: {
secretCount: plan.length,
readyCount: plan.length - unavailable.length,
unavailableCount: unavailable.length,
items: plan,
valuesPrinted: false,
},
next: {
retryDryRun: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --dry-run`,
},
valuesPrinted: false,
};
}
const values = inspected.map(({ spec: item, inspection }) => ({ spec: item, value: inspection.sourceValue! }));
const providerSecretsByTargetRef = new Map<string, AgentRunLaneSpec["secrets"][number]>();
for (const secret of spec.secrets) {
if (secret.providerCredentialProfile === null) continue;
const targetRef = laneSecretTargetRefKey(secret.targetRef);
const existing = providerSecretsByTargetRef.get(targetRef);
if (existing !== undefined) {
throw new Error(`provider Secret targetRef ${targetRef} is declared by both ${existing.id} and ${secret.id}`);
}
providerSecretsByTargetRef.set(targetRef, secret);
}
const providerValues = values.filter(({ spec: item }) => providerSecretsByTargetRef.has(laneSecretTargetRefKey(item.targetRef)));
const providerSecrets = providerValues.map(({ spec: item }) => providerSecretsByTargetRef.get(laneSecretTargetRefKey(item.targetRef))!);
const providerActivationTargets = providerValues.map(({ spec: item, value }) => {
return {
id: item.id,
targetRef: item.targetRef,
desiredEncodedFingerprint: providerSecretDesiredEncodedFingerprint(value.value),
};
});
const activationPreflight = providerValues.length > 0
? await providerSecretActivationPreflight(config, spec, providerActivationTargets, { full: options.full || options.raw })
: null;
const syncValues = values.filter(({ spec: item }) => !providerSecretsByTargetRef.has(laneSecretTargetRefKey(item.targetRef)));
if (activationPreflight !== null && activationPreflight.ok !== true) {
const profiles = providerSecrets
.map((secret) => secret.providerCredentialProfile)
.filter((profile): profile is string => profile !== null);
return {
ok: false,
command: "agentrun control-plane secret-sync",
mode: options.dryRun || !options.confirm ? "dry-run-blocked-before-mutation" : "confirm-blocked-before-mutation",
status: "blocked",
mutation: false,
blockedBeforeMutation: true,
secretSyncStarted: false,
configPath,
target: { node: spec.nodeId, lane: spec.lane, namespace: spec.runtime.namespace, valuesPrinted: false },
degradedReason: activationPreflight.reason ?? "existing-runner-provider-secret-activation-risk",
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: {
secretCount: plan.length,
items: plan.slice(0, 8).map((item) => ({
id: item.id,
namespace: item.namespace,
secret: item.secret,
key: item.key,
present: item.present,
fingerprint: item.fingerprint,
valueBytes: item.valueBytes,
valuesPrinted: false,
})),
omittedCount: Math.max(0, plan.length - 8),
valuesPrinted: false,
},
activationPreflight,
execution: {
providerSecretClassification: "exact-target-ref",
providerSecretWriteBlockedCount: providerValues.length,
secretSyncStarted: false,
valuesPrinted: false,
},
stagedActivation: providerSecretStagedActivation(spec, profiles),
next: {
observeRunners: `bun scripts/cli.ts agentrun control-plane cleanup-runners --node ${spec.nodeId} --lane ${spec.lane} --dry-run`,
retryAfterManagerFence: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --confirm`,
},
valuesPrinted: false,
};
}
if (options.dryRun || !options.confirm) {
return {
ok: true,
@@ -240,7 +335,14 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
configPath,
target: compactAgentRunLaneStatusTarget(spec),
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
plan: { secretCount: plan.length, items: plan, activationPreflight, valuesPrinted: false },
execution: {
providerSecretClassification: "exact-target-ref",
providerSecretWritePolicy: "skip-exact-no-op-until-manager-activation-fence",
providerSecretWriteSkippedCount: providerValues.length,
writableNonProviderSecretCount: syncValues.length,
valuesPrinted: false,
},
next: {
confirm: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --confirm`,
status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`,
@@ -248,7 +350,35 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
valuesPrinted: false,
};
}
const result = await capture(config, spec.nodeKubeRoute, ["sh", "--", secretSyncScript(spec, values.map(({ spec: item, value }) => ({ targetRef: item.targetRef, value: value.value })))]);
if (syncValues.length === 0) {
return {
ok: true,
command: "agentrun control-plane secret-sync",
mode: "confirmed-provider-secret-no-op-skip",
mutation: false,
secretSyncStarted: false,
providerSecretWriteSkipped: providerValues.length > 0,
configPath,
target: compactAgentRunLaneStatusTarget(spec),
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
activationPreflight,
result: {
ok: true,
status: "skipped-exact-provider-secret-no-op",
skippedProviderSecretCount: providerValues.length,
providerSecretClassification: "exact-target-ref",
reason: "provider-secret-writes-require-agentrun-manager-activation-fence",
runtimeSecretValuesDecoded: false,
valuesPrinted: false,
},
next: {
status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`,
},
valuesPrinted: false,
};
}
const result = await capture(config, spec.nodeKubeRoute, ["sh", "--", secretSyncScript(spec, syncValues.map(({ spec: item, value }) => ({ targetRef: item.targetRef, value: value.value })))]);
const payload = captureJsonPayload(result);
return {
ok: result.exitCode === 0 && payload.ok !== false,
@@ -258,7 +388,15 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
configPath,
target: compactAgentRunLaneStatusTarget(spec),
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
plan: {
secretCount: plan.length,
items: plan,
providerSecretWriteSkippedCount: providerValues.length,
providerSecretClassification: "exact-target-ref",
writableNonProviderSecretCount: syncValues.length,
valuesPrinted: false,
},
activationPreflight,
result: payload,
capture: compactCapture(result, { full: result.exitCode !== 0, stdoutTailChars: 3000, stderrTailChars: 3000 }),
next: {
@@ -268,6 +406,10 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
};
}
function laneSecretTargetRefKey(targetRef: { namespace: string; name: string; key: string }): string {
return `${targetRef.namespace}/${targetRef.name}/${targetRef.key}`;
}
export async function exposeAgentRun(_config: UniDeskConfig, options: ConfirmOptions): Promise<Record<string, unknown>> {
const clientConfig = readAgentRunClientConfig();
const exposure = clientConfig.publicExposure;