fix: reload AgentRun DB secrets from YAML
This commit is contained in:
@@ -289,11 +289,13 @@ interface RemoteJobStart {
|
||||
|
||||
export function platformDbHelp(): unknown {
|
||||
return {
|
||||
command: "platform-db postgres plan|status|apply",
|
||||
command: "platform-db postgres plan|status|apply|export-secrets",
|
||||
output: "json",
|
||||
usage: [
|
||||
`bun scripts/cli.ts platform-db postgres plan --config ${defaultConfigPath}`,
|
||||
`bun scripts/cli.ts platform-db postgres status --config ${defaultConfigPath} [--full|--raw]`,
|
||||
`bun scripts/cli.ts platform-db postgres export-secrets --config ${defaultConfigPath} --dry-run`,
|
||||
`bun scripts/cli.ts platform-db postgres export-secrets --config ${defaultConfigPath} --confirm`,
|
||||
`bun scripts/cli.ts platform-db postgres apply --config ${defaultConfigPath} --dry-run`,
|
||||
`bun scripts/cli.ts platform-db postgres apply --config ${defaultConfigPath} --confirm`,
|
||||
`bun scripts/cli.ts platform-db postgres apply --config ${defaultConfigPath} --confirm --wait`,
|
||||
@@ -302,6 +304,7 @@ export function platformDbHelp(): unknown {
|
||||
safety: {
|
||||
configTruth: defaultConfigPath,
|
||||
defaultMutation: false,
|
||||
exportSecrets: "export-secrets only materializes YAML-declared local Secret source/export files; it does not touch the remote PostgreSQL service.",
|
||||
apply: "apply --confirm returns an async UniDesk job; the job uses short trans calls and a remote PK01 job instead of keeping one long SSH session open.",
|
||||
redaction: "Passwords and full DATABASE_URL values are never printed; output is limited to key names, presence, fingerprints and state.",
|
||||
noK3s: "PK01 PostgreSQL is host-systemd, not Docker or k3s.",
|
||||
@@ -315,6 +318,7 @@ export async function runPlatformDbCommand(config: UniDeskConfig, args: string[]
|
||||
const options = parseOptions(args.slice(2));
|
||||
if (action === "plan") return await plan(config, options);
|
||||
if (action === "status") return await status(config, options);
|
||||
if (action === "export-secrets") return await exportSecrets(options);
|
||||
if (action === "apply") return await apply(config, options);
|
||||
return unsupported(args);
|
||||
}
|
||||
@@ -359,7 +363,7 @@ function parseOptions(args: string[]): PlatformDbOptions {
|
||||
throw new Error(`unsupported platform-db option: ${arg}`);
|
||||
}
|
||||
}
|
||||
if (options.confirm && options.dryRun) throw new Error("apply accepts only one of --confirm or --dry-run");
|
||||
if (options.confirm && options.dryRun) throw new Error("platform-db postgres accepts only one of --confirm or --dry-run");
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -526,6 +530,40 @@ async function apply(config: UniDeskConfig, options: PlatformDbOptions): Promise
|
||||
};
|
||||
}
|
||||
|
||||
async function exportSecrets(options: PlatformDbOptions): Promise<Record<string, unknown>> {
|
||||
const pg = readPostgresHostConfig(options.configPath);
|
||||
if (!options.confirm || options.dryRun) {
|
||||
const localState = buildLocalSecretState(pg, false);
|
||||
return {
|
||||
ok: localState.inspection.ok,
|
||||
action: "platform-db-postgres-export-secrets",
|
||||
mode: "dry-run",
|
||||
mutation: false,
|
||||
config: configSummary(pg),
|
||||
localSecrets: localState.summary,
|
||||
next: {
|
||||
confirm: `bun scripts/cli.ts platform-db postgres export-secrets --config ${pg.configPath} --confirm`,
|
||||
syncConsumers: "run the consumer-specific secret sync command after confirmed export",
|
||||
},
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
const localState = ensureLocalSecretState(pg);
|
||||
return {
|
||||
ok: true,
|
||||
action: "platform-db-postgres-export-secrets",
|
||||
mode: "confirmed",
|
||||
mutation: true,
|
||||
config: configSummary(pg),
|
||||
localSecrets: localState.summary,
|
||||
next: {
|
||||
status: `bun scripts/cli.ts platform-db postgres status --config ${pg.configPath}`,
|
||||
syncSecrets: "run the consumer-specific secret sync command after confirmed export",
|
||||
},
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function readPostgresHostConfig(pathArg: string): PostgresHostConfig {
|
||||
const configPath = resolveConfigPath(pathArg);
|
||||
const parsed = asRecord(Bun.YAML.parse(readFileSync(configPath, "utf8")) as unknown, configPath);
|
||||
@@ -1005,10 +1043,14 @@ function inspectSecrets(pg: PostgresHostConfig, materialize: boolean): SecretIns
|
||||
}
|
||||
|
||||
function ensureLocalSecretState(pg: PostgresHostConfig): { inspection: SecretInspection; summary: Record<string, unknown>; exports: Array<Record<string, unknown>> } {
|
||||
const inspection = inspectSecrets(pg, true);
|
||||
return buildLocalSecretState(pg, true);
|
||||
}
|
||||
|
||||
function buildLocalSecretState(pg: PostgresHostConfig, materialize: boolean): { inspection: SecretInspection; summary: Record<string, unknown>; exports: Array<Record<string, unknown>> } {
|
||||
const inspection = inspectSecrets(pg, materialize);
|
||||
if (!inspection.ok) throw new Error("required secret source keys are missing and cannot be generated from YAML");
|
||||
validateObjectSecretConsistency(pg, inspection);
|
||||
const exports = pg.exports.connectionStrings.map((item) => writeConnectionStringExport(pg, inspection, item));
|
||||
const exports = pg.exports.connectionStrings.map((item) => connectionStringExportState(pg, inspection, item, materialize));
|
||||
return {
|
||||
inspection,
|
||||
exports,
|
||||
@@ -1035,7 +1077,7 @@ function validateObjectSecretConsistency(pg: PostgresHostConfig, inspection: Sec
|
||||
}
|
||||
}
|
||||
|
||||
function writeConnectionStringExport(pg: PostgresHostConfig, inspection: SecretInspection, item: ConnectionStringExportConfig): Record<string, unknown> {
|
||||
function connectionStringExportState(pg: PostgresHostConfig, inspection: SecretInspection, item: ConnectionStringExportConfig, materialize: boolean): Record<string, unknown> {
|
||||
const source = inspection.materials.get(item.sourceSecretRef);
|
||||
if (source === undefined) throw new Error(`export source secret not found: ${item.sourceSecretRef}`);
|
||||
const rendered = renderConnectionString(item, source.values);
|
||||
@@ -1044,7 +1086,7 @@ function writeConnectionStringExport(pg: PostgresHostConfig, inspection: SecretI
|
||||
const existing = existsSync(targetPath) ? parseEnvFile(readFileSync(targetPath, "utf8")) : {};
|
||||
const before = existing[item.writeToSecretSource.key];
|
||||
const next = { ...existing, [item.writeToSecretSource.key]: rendered };
|
||||
writeEnvFile(targetPath, next);
|
||||
if (materialize) writeEnvFile(targetPath, next);
|
||||
return {
|
||||
name: item.name,
|
||||
sourceRef: item.sourceSecretRef,
|
||||
|
||||
Reference in New Issue
Block a user