diff --git a/.server-changes/compute-network-labels.md b/.server-changes/compute-network-labels.md new file mode 100644 index 0000000000..874081885d --- /dev/null +++ b/.server-changes/compute-network-labels.md @@ -0,0 +1,6 @@ +--- +area: supervisor +type: feature +--- + +Forward per-run identity labels to the compute provider on create and restore, letting network policy select runs (e.g. private link). diff --git a/apps/supervisor/src/index.ts b/apps/supervisor/src/index.ts index aa9255ef26..64f3959c2b 100644 --- a/apps/supervisor/src/index.ts +++ b/apps/supervisor/src/index.ts @@ -376,6 +376,7 @@ class ManagedSupervisor { envId: message.environment.id, orgId: message.organization.id, projectId: message.project.id, + hasPrivateLink: message.organization.hasPrivateLink, dequeuedAt: message.dequeuedAt, }); recordPhaseSince("restore", restoreStart, undefined); diff --git a/apps/supervisor/src/workloadManager/compute.ts b/apps/supervisor/src/workloadManager/compute.ts index 3c40ac9e2e..3efad7d407 100644 --- a/apps/supervisor/src/workloadManager/compute.ts +++ b/apps/supervisor/src/workloadManager/compute.ts @@ -133,6 +133,14 @@ export class ComputeWorkloadManager implements WorkloadManager { // Strip image digest - resolve by tag, not digest const imageRef = stripImageDigest(opts.image); + // Labels forwarded to the compute provider for network-policy selection; + // the provider promotes a configured subset to its network layer. Mirrors + // the privatelink label the Kubernetes workload manager sets on the run pod. + const labels: Record = {}; + if (opts.hasPrivateLink) { + labels.privatelink = opts.orgId; + } + // Wide event: single canonical log line emitted in finally const event: Record = { // High-cardinality identifiers @@ -173,6 +181,7 @@ export class ComputeWorkloadManager implements WorkloadManager { deploymentVersion: opts.deploymentVersion, machine: opts.machine.name, }, + ...(Object.keys(labels).length > 0 ? { labels } : {}), }) ); @@ -297,6 +306,7 @@ export class ComputeWorkloadManager implements WorkloadManager { envId?: string; orgId?: string; projectId?: string; + hasPrivateLink?: boolean; dequeuedAt?: Date; }): Promise { const metadata: Record = { @@ -309,6 +319,14 @@ export class ComputeWorkloadManager implements WorkloadManager { TRIGGER_WORKER_INSTANCE_NAME: this.opts.runner.instanceName, }; + // Resupply the same labels on restore (mirror of the create path); the + // provider doesn't persist them across a snapshot, so without this a + // restored run would lose its policy-based network selection. + const labels: Record = {}; + if (opts.hasPrivateLink && opts.orgId) { + labels.privatelink = opts.orgId; + } + this.logger.verbose("restore request body", { snapshotId: opts.snapshotId, runnerId: opts.runnerId, @@ -322,6 +340,7 @@ export class ComputeWorkloadManager implements WorkloadManager { metadata, cpu: opts.machine.cpu, memory_gb: opts.machine.memory, + ...(Object.keys(labels).length > 0 ? { labels } : {}), }) ); diff --git a/internal-packages/compute/src/types.ts b/internal-packages/compute/src/types.ts index cb977f83a7..5d8d5e26af 100644 --- a/internal-packages/compute/src/types.ts +++ b/internal-packages/compute/src/types.ts @@ -42,6 +42,10 @@ export const InstanceCreateRequestSchema = z.object({ cpu: z.number(), memory_gb: z.number(), metadata: z.record(z.unknown()).optional(), + // Per-instance identity labels; the provider promotes a configured subset + // to network-policy selection. Distinct from metadata, which is + // observability-only and never selected on. + labels: z.record(z.string()).optional(), }); export type InstanceCreateRequest = z.infer; @@ -66,6 +70,10 @@ export const SnapshotRestoreRequestSchema = z.object({ metadata: z.record(z.string()), cpu: z.number(), memory_gb: z.number(), + // Per-instance identity labels; the caller must resupply the same set as on + // create. The provider doesn't persist them across a snapshot, so omitting + // them drops the restored run's policy-based network selection. + labels: z.record(z.string()).optional(), }); export type SnapshotRestoreRequest = z.infer;