feat: dedicated PVC per agent for OPENCODE_DB (FAR-63, Option B)
Replaces the Option A shared-PVC path implementation with a long-lived dedicated PVC per agent, mounted at /opencode-db with OPENCODE_DB=/opencode-db. Changes: - k8s-client.ts: add getPvc/createPvc/deletePvc CoreV1Api helpers - execute.ts: add ensureAgentDbPvc() that gets-or-creates a PVC named opencode-db-<agentId> before Job creation; pass agentDbClaimName through to buildJobManifest; return null for ephemeral mode (emptyDir used instead) - job-manifest.ts: accept agentDbClaimName on JobBuildInput; mount dedicated PVC or emptyDir at /opencode-db; set OPENCODE_DB=/opencode-db; revert init container to simple form (no mkdir, no PVC mount) - config-schema.ts: replace opencodeDbMode/opencodeDbPath with agentDbMode (dedicated_pvc|ephemeral, default dedicated_pvc), agentDbStorageClass (required for dedicated_pvc), agentDbStorageCapacity (default 1Gi) - test.ts: add create/delete RBAC checks for persistentvolumeclaims - pvc.test.ts: unit tests for ensureAgentDbPvc (7 cases incl. error paths) - 289/289 tests pass; typecheck clean - No agent-delete hook exists; opencode-db PVC janitor routine is a deferred follow-up task Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -174,3 +174,46 @@ export function resetCache(): void {
|
||||
kcCache.clear();
|
||||
cachedSelfPod = null;
|
||||
}
|
||||
|
||||
function isNotFound(err: unknown): boolean {
|
||||
if (!(err instanceof Error)) return false;
|
||||
const asAny = err as unknown as Record<string, unknown>;
|
||||
if (typeof asAny.statusCode === "number" && asAny.statusCode === 404) return true;
|
||||
const resp = asAny.response as Record<string, unknown> | undefined;
|
||||
return typeof resp?.statusCode === "number" && resp.statusCode === 404;
|
||||
}
|
||||
|
||||
/** Returns the PVC if it exists, or null if not found. Throws on other errors. */
|
||||
export async function getPvc(
|
||||
namespace: string,
|
||||
name: string,
|
||||
kubeconfigPath?: string,
|
||||
): Promise<k8s.V1PersistentVolumeClaim | null> {
|
||||
try {
|
||||
return await getCoreApi(kubeconfigPath).readNamespacedPersistentVolumeClaim({ name, namespace });
|
||||
} catch (err) {
|
||||
if (isNotFound(err)) return null;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function createPvc(
|
||||
namespace: string,
|
||||
spec: k8s.V1PersistentVolumeClaim,
|
||||
kubeconfigPath?: string,
|
||||
): Promise<k8s.V1PersistentVolumeClaim> {
|
||||
return getCoreApi(kubeconfigPath).createNamespacedPersistentVolumeClaim({ namespace, body: spec });
|
||||
}
|
||||
|
||||
/** Deletes a PVC, ignoring 404 (already gone). */
|
||||
export async function deletePvc(
|
||||
namespace: string,
|
||||
name: string,
|
||||
kubeconfigPath?: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await getCoreApi(kubeconfigPath).deleteNamespacedPersistentVolumeClaim({ name, namespace });
|
||||
} catch (err) {
|
||||
if (!isNotFound(err)) throw err;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user