Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion internal/controller/testing_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

karmadapolicyv1alpha1 "github.com/karmada-io/api/policy/v1alpha1"
computev1alpha "go.datum.net/compute/api/v1alpha"
networkingv1alpha "go.datum.net/network-services-operator/api/v1alpha"
)

// ─── Scheme helpers ───────────────────────────────────────────────────────────
Expand All @@ -34,11 +35,12 @@ func newProjectScheme() *runtime.Scheme {
}

// newKarmadaScheme builds a runtime.Scheme with the types needed by the Karmada
// API server (corev1 + compute + karmada policy).
// API server (corev1 + compute + networking + karmada policy).
func newKarmadaScheme() *runtime.Scheme {
s := runtime.NewScheme()
_ = corev1.AddToScheme(s)
_ = computev1alpha.AddToScheme(s)
_ = networkingv1alpha.AddToScheme(s)
_ = karmadapolicyv1alpha1.Install(s)
return s
}
Expand Down
39 changes: 34 additions & 5 deletions internal/controller/workloaddeployment_federator.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,24 @@ func (r *WorkloadDeploymentFederator) Reconcile(ctx context.Context, req mcrecon
// Upsert the WorkloadDeployment in the downstream control plane via the
// strategy client so any future Create calls also go through
// ensureDownstreamNamespace automatically.
if err := r.upsertDownstreamDeployment(ctx, strategy.GetClient(), &deployment, downstreamNS); err != nil {
hubDeployment, err := r.upsertDownstreamDeployment(ctx, strategy.GetClient(), &deployment, downstreamNS)
if err != nil {
return ctrl.Result{}, err
}

if err := r.ensurePropagationPolicy(ctx, downstreamNS, deployment.Spec.CityCode); err != nil {
return ctrl.Result{}, err
}

if err := r.syncStatusFromDownstream(ctx, cl.GetClient(), &deployment, downstreamNS); err != nil {
// Ask for the deployment's network to be present where it runs. This follows
// the hub deployment because the location it is placed in is only known from
// the status the cell aggregates back onto it.
binding, err := r.ensureNetworkBinding(ctx, hubDeployment)
if err != nil {
return ctrl.Result{}, err
}

if err := r.syncStatusFromDownstream(ctx, cl.GetClient(), &deployment, downstreamNS, binding); err != nil {
return ctrl.Result{}, err
}

Expand Down Expand Up @@ -276,12 +285,16 @@ func (r *WorkloadDeploymentFederator) ensureDownstreamNamespace(ctx context.Cont
// upsertDownstreamDeployment creates or updates the WorkloadDeployment in the
// downstream namespace via the provided client (expected to be strategy.GetClient()
// so the downstream namespace is created with upstream tracking labels).
//
// It returns the downstream object as it now stands, which is what anything
// hanging off the hub deployment — its UID for an owner reference, its
// aggregated status for the location it landed in — has to be built from.
func (r *WorkloadDeploymentFederator) upsertDownstreamDeployment(
ctx context.Context,
downstreamClient client.Client,
deployment *computev1alpha.WorkloadDeployment,
downstreamNS string,
) error {
) (*computev1alpha.WorkloadDeployment, error) {
kd := &computev1alpha.WorkloadDeployment{
ObjectMeta: metav1.ObjectMeta{
Name: deployment.Name,
Expand Down Expand Up @@ -328,11 +341,11 @@ func (r *WorkloadDeploymentFederator) upsertDownstreamDeployment(
return nil
})
if err != nil {
return fmt.Errorf("failed to upsert downstream deployment %s/%s: %w", downstreamNS, deployment.Name, err)
return nil, fmt.Errorf("failed to upsert downstream deployment %s/%s: %w", downstreamNS, deployment.Name, err)
}

log.FromContext(ctx).Info("upserted downstream deployment", "result", result, "downstreamNamespace", downstreamNS)
return nil
return kd, nil
}

// ensurePropagationPolicy creates or updates a PropagationPolicy in the downstream
Expand Down Expand Up @@ -435,6 +448,7 @@ func (r *WorkloadDeploymentFederator) syncStatusFromDownstream(
projectClient client.Client,
deployment *computev1alpha.WorkloadDeployment,
downstreamNS string,
binding *networkingv1alpha.NetworkBinding,
) error {
var kd computev1alpha.WorkloadDeployment
if err := r.FederationClient.Get(ctx, types.NamespacedName{
Expand All @@ -454,6 +468,7 @@ func (r *WorkloadDeploymentFederator) syncStatusFromDownstream(
if resolverCond := apimeta.FindStatusCondition(deployment.Status.Conditions, computev1alpha.ReferencedDataReady); resolverCond != nil {
apimeta.SetStatusCondition(&merged.Conditions, *resolverCond)
}
applyNetworkBindingRefusal(merged, binding, deployment.Generation)

if equality.Semantic.DeepEqual(deployment.Status, *merged) {
return nil
Expand All @@ -472,6 +487,7 @@ func (r *WorkloadDeploymentFederator) syncStatusFromDownstream(
if resolverCond := apimeta.FindStatusCondition(deployment.Status.Conditions, computev1alpha.ReferencedDataReady); resolverCond != nil {
apimeta.SetStatusCondition(&merged.Conditions, *resolverCond)
}
applyNetworkBindingRefusal(merged, binding, deployment.Generation)
if equality.Semantic.DeepEqual(deployment.Status, *merged) {
return nil
}
Expand Down Expand Up @@ -575,6 +591,19 @@ func (r *WorkloadDeploymentFederator) SetupWithManager(mgr mcmanager.Manager) er
&computev1alpha.WorkloadDeployment{},
preserveClusterName,
))

// Watch the NetworkBindings this controller writes, so what NSO says
// about a declared presence reaches the deployment's own status without
// waiting for a resync, and so a recreate after a location change is
// driven by the old binding disappearing.
preserveOnBinding := func(_ multicluster.ClusterName, _ cluster.Cluster) handler.TypedEventHandler[*networkingv1alpha.NetworkBinding, mcreconcile.Request] {
return mchandler.TypedEnqueueRequestsFromMapFuncWithClusterPreservation(r.mapNetworkBindingToRequest)
}
b = b.WatchesRawSource(milosource.MustNewClusterSource(
r.FederationCluster,
&networkingv1alpha.NetworkBinding{},
preserveOnBinding,
))
}

return b.Complete(r)
Expand Down
Loading
Loading