fix: reconcile network contexts where they live - #396
Merged
Conversation
Every NetworkContext in staging has been stuck since 2026-08-20. The presence controller writes them onto the hub, and the reconciler that would allocate a location's subnet only watches project control planes, so the two sets are disjoint and nothing ever reconciles a context: no subnet, no VPC networking, and no consumer can see whether a network is present in a location. The hub now decides a presence exists and the project control plane holds the object. The context is written beside the Network it is derived from, owned by it, where the subnet reconciler already runs. The replicator mirrors it and its Subnet back onto the hub, and the per-location propagation policy carries both to the cells serving that location and no others. Ready was a second half of the same freeze: it gated on Programmed, which no component has ever written, so it stayed Unknown forever. It now follows IPAMAllocated, and a location that needs no address space of its own reaches Ready as soon as it exists. Key changes: - Write the NetworkContext into the project namespace with the Network as controller, so the apiserver collects it and NetworkPresenceGCReconciler and its hub-side finalizer retire - Requeue while the context is not ready; the presence controller no longer watches the control plane the context lives in - Target teardown at the project-plane object so a replicated hub copy, which carries the same name and labels, is never reaped - Derive NetworkContext Ready from IPAMAllocated and deprecate Programmed - Replicate NetworkContext and Subnet with skipUpstreamStatusSync, propagating the labels the location policy selects on, and stamp those labels on the published Subnet - Scope NetworkContext and Subnet propagation to the location they name, so a cell serving nowhere is no longer handed every project's addressing - Refuse a claim when a location publishes a subnet yielding no usable gateway rather than handing out addresses that route nothing
Nothing ever wrote Programmed on a NetworkContext and nothing reads it now that Ready derives from IPAMAllocated. Leaving the condition seeded as Unknown by the CRD default publishes a state no component owns, so remove it outright rather than deprecate it in place. Key changes: - Drop NetworkContextProgrammed and its three reason constants - Seed only Ready in the status default, so a context carries no condition without an owner - Regenerate the CRD and the API reference, which also picks up the attachmentMode and Prepared drift left on main
scotwells
enabled auto-merge
August 21, 2026 15:56
privateip
approved these changes
Aug 21, 2026
This was referenced Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every network context in staging has been stuck since 20 August, so no location has a subnet, instances get no VPC networking, and a project cannot see whether its network is present in a location at all. Two controllers disagreed about where the object lives, and readiness was gated on a condition no component has ever written. This puts the object in the control plane that already reconciles it, and derives readiness from the address space a location actually holds.
What changed
A project can see its network's presence in each location, in the control plane it reads everything else from. Deleting a network takes those presences with it.
A location that needs no address space of its own is ready as soon as it exists. That covers an IPv4-only network, which is every live staging context today.
A presence reaches only the cells serving its location. Today every context for one location lands on both staging cells, including one that serves no location at all.
A workload whose location publishes a subnet that yields no gateway gets a clear refusal, rather than an interface with addresses and no route.
Companion change required
The fleet-wide propagation policy lives in datum-cloud/infra and must drop its network context selector. Landing this first leaves both policies active, which is harmless: both overwrite on conflict, and the new one is strictly narrower.
Not in scope
The address family default flipped from IPv4 to IPv6 in an earlier change, but a default applies only at creation, so networks that already persisted IPv4 need a data migration.
Important
That migration edits the network, and an edit no longer reaches a presence that is already ready. Restoring that needs to land before the migration runs.
Test plan
Related to #164
Regression from #373. Builds on #385 and #391, and on the design in a network in every location it is used.