Skip to content

fix: reconcile network contexts where they live - #396

Merged
scotwells merged 2 commits into
mainfrom
fix/network-context-project-plane
Aug 21, 2026
Merged

fix: reconcile network contexts where they live#396
scotwells merged 2 commits into
mainfrom
fix/network-context-project-plane

Conversation

@scotwells

@scotwells scotwells commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

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

  • An IPv4-only network becomes present in a location with nothing allocated
  • A binding retries while its context is not yet ready
  • A claim reports an unusable gateway instead of routing nothing
  • Build, lint and the envtest suite pass

Related to #164

Regression from #373. Builds on #385 and #391, and on the design in a network in every location it is used.

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
scotwells requested a review from privateip August 21, 2026 15:38
@scotwells
scotwells enabled auto-merge August 21, 2026 15:56
@scotwells
scotwells merged commit fd96832 into main Aug 21, 2026
13 of 14 checks passed
@scotwells
scotwells deleted the fix/network-context-project-plane branch August 21, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants