Suspendedremoval
Some checks failed
Build and Push / build (push) Failing after 48s

This commit is contained in:
2026-05-01 18:07:00 +02:00
parent 7d58c78cb9
commit a5812dca9a
16 changed files with 880 additions and 90 deletions

View File

@@ -130,3 +130,46 @@ export async function patchTenantSpec(
}
return res.json() as Promise<PiecedTenant>;
}
/**
* Set or clear an annotation on a PiecedTenant CR.
*
* Pass `value=null` to remove the annotation. K8s merge-patch removes
* a key when its value is null in the patch — that's exactly the
* semantic we want.
*
* Used by the resume-request flow (Bug 37a): the portal sets
* `pieced.ch/resume-request-pending` when a customer creates a
* resume request, and clears it when the request transitions to a
* terminal state. The operator reads this annotation to pause its
* 60-day deletion timer while a resume request is in flight.
*
* Annotations are namespaced informally — we use `pieced.ch/...` for
* everything we own, mirroring the labels.
*/
export async function setTenantAnnotation(
name: string,
key: string,
value: string | null
): Promise<PiecedTenant> {
const url = `${getBaseUrl()}/apis/${API_VERSION}/${PLURAL}/${name}`;
const res = await fetch(url, {
method: "PATCH",
headers: {
Accept: "application/json",
"Content-Type": "application/merge-patch+json",
...getAuthHeaders(),
},
body: JSON.stringify({
metadata: { annotations: { [key]: value } },
}),
});
if (!res.ok) {
const text = await res.text();
const err = new Error(`K8s annotate /${name}: ${res.status} ${text}`);
(err as any).statusCode = res.status;
throw err;
}
return res.json() as Promise<PiecedTenant>;
}