feat: harden self-managed reconciliation

This commit is contained in:
2026-09-05 10:17:55 +00:00 Unverified
parent 8e9d207915
commit 321f4e807a
40 changed files with 4977 additions and 404 deletions
+20 -5
View File
@@ -236,7 +236,15 @@ function toManagedRole(claim: PostgresClaim): ManagedRole {
};
}
async function reconcileManagedRoles(claims: PostgresClaim[]): Promise<void> {
function throwIfAborted(signal?: AbortSignal): void {
if (!signal?.aborted) return;
throw new Error("Workspace operation execution was cancelled");
}
async function reconcileManagedRoles(
claims: PostgresClaim[],
signal?: AbortSignal,
): Promise<void> {
if (claims.length === 0) return;
const cluster = await readObject<
@@ -264,6 +272,7 @@ async function reconcileManagedRoles(claims: PostgresClaim[]): Promise<void> {
}
try {
throwIfAborted(signal);
await applyResource({
apiVersion: "postgresql.cnpg.io/v1",
kind: "Cluster",
@@ -287,6 +296,7 @@ async function reconcileManagedRoles(claims: PostgresClaim[]): Promise<void> {
async function reconcileDatabases(
project: string,
claims: PostgresClaim[],
signal?: AbortSignal,
): Promise<void> {
const uniqueDatabases = new Map<string, PostgresClaim>();
for (const claim of claims) {
@@ -295,6 +305,7 @@ async function reconcileDatabases(
for (const claim of uniqueDatabases.values()) {
try {
throwIfAborted(signal);
await applyResource({
apiVersion: "postgresql.cnpg.io/v1",
kind: "Database",
@@ -328,16 +339,19 @@ async function reconcileDatabases(
export async function reconcilePostgresClaim(
project: string,
claim: PostgresClaim,
signal?: AbortSignal,
): Promise<RoleCredentials> {
throwIfAborted(signal);
const credentials = await ensureRoleSecret(claim);
await reconcileManagedRoles([claim]);
await reconcileDatabases(project, [claim]);
await reconcileManagedRoles([claim], signal);
await reconcileDatabases(project, [claim], signal);
return credentials;
}
export async function reconcilePostgresClaims(
project: string,
compose: ComposeSpecification,
signal?: AbortSignal,
): Promise<Record<string, Record<string, string>>> {
const claims = getComposePostgresClaims(compose);
if (claims.length === 0) return {};
@@ -345,11 +359,12 @@ export async function reconcilePostgresClaims(
const credentialsBySecret = new Map<string, RoleCredentials>();
for (const claim of claims) {
if (credentialsBySecret.has(claim.secretName)) continue;
throwIfAborted(signal);
credentialsBySecret.set(claim.secretName, await ensureRoleSecret(claim));
}
await reconcileManagedRoles(claims);
await reconcileDatabases(project, claims);
await reconcileManagedRoles(claims, signal);
await reconcileDatabases(project, claims, signal);
return Object.fromEntries(
claims.map((claim) => {