Skip to content

Commit 1f153bb

Browse files
committed
fix(supervisor): reject padded org override keys and sharpen placement wording
The override lookup is exact, so a padded or blank org key would parse at startup and then never match a run. The release note now describes the user-visible result and the docs row states the selector-override vs toleration-append semantics separately.
1 parent a79d283 commit 1f153bb

4 files changed

Lines changed: 17 additions & 3 deletions

File tree

.server-changes/supervisor-org-placement-overrides.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ area: supervisor
33
type: feature
44
---
55

6-
Operators can now pin an organization's runs to specific nodes, with per-organization node selectors and tolerations for run pods.
6+
Operators can now route an organization's runs to specific Kubernetes node pools.

apps/supervisor/src/envUtil.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ describe("OrgPlacementOverrides", () => {
288288
).toEqual({ org_123: { nodeSelector: { pool: "a" } } });
289289
});
290290

291+
it("should reject blank or padded org keys, since the lookup is exact", () => {
292+
for (const key of [" ", " org_123", "org_123 "]) {
293+
expect(
294+
OrgPlacementOverrides.safeParse(JSON.stringify({ [key]: {} })).success
295+
).toBe(false);
296+
}
297+
});
298+
291299
it("should reject an empty node selector value instead of pinning the org to nothing", () => {
292300
for (const value of ["", " "]) {
293301
expect(

apps/supervisor/src/envUtil.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,13 @@ export const OrgPlacementOverrides = z
221221
.pipe(
222222
z
223223
.record(
224-
z.string().min(1),
224+
z
225+
.string()
226+
.min(1)
227+
.refine((key) => key === key.trim() && key.trim().length > 0, {
228+
message:
229+
"Org override keys must not be blank or padded with whitespace; the lookup is exact",
230+
}),
225231
z
226232
.object({
227233
nodeSelector: NodeSelector.optional(),

docs/self-hosting/env/supervisor.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ mode: "wide"
4848
| `KUBERNETES_NAMESPACE` | No | default | The namespace that runs should be in. |
4949
| `KUBERNETES_WORKER_NODETYPE_LABEL` | No | v4-worker | Nodes for runs need `nodetype=<this>`. Empty: any node. |
5050
| `KUBERNETES_RUNNER_TOLERATIONS` | No || Run pod tolerations. CSV: `key=value:effect`/`key:effect`. |
51-
| `KUBERNETES_ORG_PLACEMENT_OVERRIDES` | No || Per-org node selector and tolerations for run pods, merged over the defaults. JSON keyed by the org's internal ID (the `org` label on run pods). |
51+
| `KUBERNETES_ORG_PLACEMENT_OVERRIDES` | No || Per-org node selectors override matching defaults, and tolerations append to existing run-pod tolerations. JSON keyed by the org's internal ID (the `org` label on run pods). |
5252
| `KUBERNETES_IMAGE_PULL_SECRETS` | No || Image pull secrets (CSV). |
5353
| `KUBERNETES_EPHEMERAL_STORAGE_SIZE_LIMIT` | No | 10Gi | Ephemeral storage size limit. Applies to all runs. |
5454
| `KUBERNETES_EPHEMERAL_STORAGE_SIZE_REQUEST` | No | 2Gi | Ephemeral storage size request. Applies to all runs. |

0 commit comments

Comments
 (0)