Summary
Implement worker-side reconciliation to enforce Hub-and-Spoke peer connectivity based on controller-published peer intents. Workers must create, maintain, and remove tunnel links to match the desired peer list exactly.
Depends on: kubeslice-controller #300 (ADR merged — defines desiredPeers field location and schema)
What the worker receives from the controller
The controller (after implementing the TopologyResolver) writes a desired peer list into WorkerSliceConfig (or the field decided in ADR-002 Decision 6). The exact field path must match what the controller writes — confirm before coding.
Proposed schema addition to WorkerSliceConfig:
spec:
peers: # list of cluster names this worker should connect to
- hub-cluster-1
- spoke-cluster-a # only present if this worker IS the hub
If spec.peers is absent or empty and no topology is set → full mesh behavior unchanged (backward compat).
Reconcile algorithm
func ReconcilePeers(desired []string) error:
current = listActiveTunnelLinks() // existing peer connections on this worker
toCreate = desired - current // in desired, not yet connected
toDelete = current - desired // connected, no longer desired
for each peer in toCreate:
establishTunnelLink(peer)
for each peer in toDelete:
tearDownTunnelLink(peer)
return nil
Idempotency requirement: Calling ReconcilePeers twice with identical desired and current must produce zero writes on the second call. Test this explicitly.
Restart safety: After worker operator restart, listActiveTunnelLinks() must accurately reflect the actual state of tunnel links — not in-memory cache. If state is read from the cluster (CRs, OS network state), document which is authoritative.
Hub change handling
When spec.peers changes (e.g., hub changes from cluster-A to cluster-B):
1. toCreate = [cluster-B] — establish new link first
2. Wait for cluster-B link to report Connected (or proceed after timeout)
3. toDelete = [cluster-A] — tear down old link
The controller enforces the add-first-then-remove ordering at the intent level (see ADR-002 Decision 4). The worker must apply intents in the order received and must not reverse this order.
No-op for non-topology slices
If WorkerSliceConfig.spec.peers is absent → use existing full-mesh behavior unchanged. The new reconcile path must be gated on the presence of this field, not on a mode flag.
Acceptance Criteria
Summary
Implement worker-side reconciliation to enforce Hub-and-Spoke peer connectivity based on controller-published peer intents. Workers must create, maintain, and remove tunnel links to match the desired peer list exactly.
Depends on: kubeslice-controller #300 (ADR merged — defines
desiredPeersfield location and schema)What the worker receives from the controller
The controller (after implementing the
TopologyResolver) writes a desired peer list intoWorkerSliceConfig(or the field decided in ADR-002 Decision 6). The exact field path must match what the controller writes — confirm before coding.Proposed schema addition to
WorkerSliceConfig:If
spec.peersis absent or empty and notopologyis set → full mesh behavior unchanged (backward compat).Reconcile algorithm
Idempotency requirement: Calling
ReconcilePeerstwice with identicaldesiredandcurrentmust produce zero writes on the second call. Test this explicitly.Restart safety: After worker operator restart,
listActiveTunnelLinks()must accurately reflect the actual state of tunnel links — not in-memory cache. If state is read from the cluster (CRs, OS network state), document which is authoritative.Hub change handling
When
spec.peerschanges (e.g., hub changes from cluster-A to cluster-B):The controller enforces the add-first-then-remove ordering at the intent level (see ADR-002 Decision 4). The worker must apply intents in the order received and must not reverse this order.
No-op for non-topology slices
If
WorkerSliceConfig.spec.peersis absent → use existing full-mesh behavior unchanged. The new reconcile path must be gated on the presence of this field, not on a mode flag.Acceptance Criteria
spec.peersspec.peersspec.peersis absent — existing test suite passes unchanged