Skip to content

Commit

Permalink
Add Watch for Zone changes to update FailureDomains accordingly
Browse files Browse the repository at this point in the history
Signed-off-by: Gong Zhang <[email protected]>
  • Loading branch information
zhanggbj committed Aug 12, 2024
1 parent 1865532 commit 204790f
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 587 deletions.
2 changes: 1 addition & 1 deletion config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
- "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}"
- "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}"
- --v=4
- "--feature-gates=NodeAntiAffinity=${EXP_NODE_ANTI_AFFINITY:=false},NamespaceScopedZone=${EXP_NAMESPACE_SCOPED_ZONE:=false}"
- "--feature-gates=NodeAntiAffinity=${EXP_NODE_ANTI_AFFINITY:=false},NamespaceScopedZones=${EXP_NAMESPACE_SCOPED_ZONES:=false}"
image: controller:latest
imagePullPolicy: IfNotPresent
name: manager
Expand Down
42 changes: 38 additions & 4 deletions controllers/vmware/vspherecluster_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,18 +370,52 @@ func (r *ClusterReconciler) VSphereMachineToCluster(ctx context.Context, o clien
}}
}

// ZoneToVSphereClusters adds reconcile requests for VSphereClusters when Zone has an event.
func (r *ClusterReconciler) ZoneToVSphereClusters(ctx context.Context, o client.Object) []reconcile.Request {
log := ctrl.LoggerFrom(ctx)

zone, ok := o.(*topologyv1.Zone)
if !ok {
log.Error(nil, fmt.Sprintf("Expected a Zone but got a %T", o))
return nil
}
log = log.WithValues("Zone", klog.KObj(zone))
ctx = ctrl.LoggerInto(ctx, log)

VSphereClusters := &vmwarev1.VSphereClusterList{}
err := r.Client.List(ctx, VSphereClusters, &client.ListOptions{Namespace: zone.Namespace})
if err != nil {
log.V(4).Error(err, "Failed to get VSphereClusters from Zone")
return nil
}

log.V(6).Info("Triggering VSphereCluster reconcile from Zone")
requests := []reconcile.Request{}
for _, c := range VSphereClusters.Items {
r := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: c.Name,
Namespace: c.Namespace,
},
}
requests = append(requests, r)
}

return requests
}

// Returns the failure domain information discovered on the cluster
// hosting this controller.
func (r *ClusterReconciler) getFailureDomains(ctx context.Context, namespace string) (clusterv1.FailureDomains, error) {
failureDomains := clusterv1.FailureDomains{}
// Determine the source of failure domain based on feature gates NamespaceScopedZone.
// If NamespaceScopedZone is enabled, use Zone which is Namespace scoped,otherwise use
// Determine the source of failure domain based on feature gates NamespaceScopedZones.
// If NamespaceScopedZones is enabled, use Zone which is Namespace scoped,otherwise use
// Availability Zone which is Cluster scoped.
if feature.Gates.Enabled(feature.NamespaceScopedZone) {
if feature.Gates.Enabled(feature.NamespaceScopedZones) {
zoneList := &topologyv1.ZoneList{}
listOptions := &client.ListOptions{Namespace: namespace}
if err := r.Client.List(ctx, zoneList, listOptions); err != nil {
return nil, err
return nil, errors.Wrapf(err, fmt.Sprintf("Failed to list Zones in namespace %s", namespace))
}

for _, zone := range zoneList.Items {
Expand Down
2 changes: 1 addition & 1 deletion controllers/vmware/vspherecluster_reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func TestClusterReconciler_getFailureDomains(t *testing.T) {
WithObjects(append([]client.Object{namespace}, tt.objects...)...).
Build(),
}
defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.NamespaceScopedZone, tt.featureGate)()
defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.NamespaceScopedZones, tt.featureGate)()
got, err := r.getFailureDomains(ctx, namespace.Name)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterReconciler.getFailureDomains() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
16 changes: 13 additions & 3 deletions controllers/vspherecluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
vmwarev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/vmware/v1beta1"
"sigs.k8s.io/cluster-api-provider-vsphere/controllers/vmware"
"sigs.k8s.io/cluster-api-provider-vsphere/feature"
topologyv1 "sigs.k8s.io/cluster-api-provider-vsphere/internal/apis/topology/v1alpha1"
capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
inframanager "sigs.k8s.io/cluster-api-provider-vsphere/pkg/manager"
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/services"
Expand Down Expand Up @@ -72,15 +73,24 @@ func AddClusterControllerToManager(ctx context.Context, controllerManagerCtx *ca
},
NetworkProvider: networkProvider,
}
return ctrl.NewControllerManagedBy(mgr).
builder := ctrl.NewControllerManagedBy(mgr).
For(&vmwarev1.VSphereCluster{}).
WithOptions(options).
Watches(
&vmwarev1.VSphereMachine{},
handler.EnqueueRequestsFromMapFunc(reconciler.VSphereMachineToCluster),
).
WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), controllerManagerCtx.WatchFilterValue)).
Complete(reconciler)
WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), controllerManagerCtx.WatchFilterValue))

// Conditionally add a Watch for topologyv1.Zone when the feature gate is enabled
if feature.Gates.Enabled(feature.NamespaceScopedZones) {
builder = builder.Watches(
&topologyv1.Zone{},
handler.EnqueueRequestsFromMapFunc(reconciler.ZoneToVSphereClusters),
).WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), controllerManagerCtx.WatchFilterValue))
}

return builder.Complete(reconciler)
}

reconciler := &clusterReconciler{
Expand Down
8 changes: 4 additions & 4 deletions feature/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ const (
// alpha: v1.4
NodeAntiAffinity featuregate.Feature = "NodeAntiAffinity"

// NamespaceScopedZone is a feature gate for the NamespaceScopedZone functionality for supervisor.
// NamespaceScopedZones is a feature gate for the NamespaceScopedZones functionality for supervisor.
//
// alpha: v1.11
NamespaceScopedZone featuregate.Feature = "NamespaceScopedZone"
NamespaceScopedZones featuregate.Feature = "NamespaceScopedZones"
)

func init() {
Expand All @@ -48,6 +48,6 @@ func init() {
// To add a new feature, define a key for it above and add it here.
var defaultCAPVFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
// Every feature should be initiated here:
NodeAntiAffinity: {Default: false, PreRelease: featuregate.Alpha},
NamespaceScopedZone: {Default: false, PreRelease: featuregate.Alpha},
NodeAntiAffinity: {Default: false, PreRelease: featuregate.Alpha},
NamespaceScopedZones: {Default: false, PreRelease: featuregate.Alpha},
}
2 changes: 1 addition & 1 deletion test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1"
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -42,6 +41,7 @@ import (

infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
vmwarev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/vmware/v1beta1"
topologyv1 "sigs.k8s.io/cluster-api-provider-vsphere/internal/apis/topology/v1alpha1"
vsphereframework "sigs.k8s.io/cluster-api-provider-vsphere/test/framework"
vsphereip "sigs.k8s.io/cluster-api-provider-vsphere/test/framework/ip"
vspherelog "sigs.k8s.io/cluster-api-provider-vsphere/test/framework/log"
Expand Down
2 changes: 1 addition & 1 deletion test/framework/vmoperator/vmoperator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/pkg/errors"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
vmoprv1common "github.com/vmware-tanzu/vm-operator/api/v1alpha2/common"
topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1"
"github.com/vmware/govmomi/pbm"
"github.com/vmware/govmomi/vapi/library"
"github.com/vmware/govmomi/vapi/rest"
Expand All @@ -44,6 +43,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

topologyv1 "sigs.k8s.io/cluster-api-provider-vsphere/internal/apis/topology/v1alpha1"
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/session"
vcsimv1 "sigs.k8s.io/cluster-api-provider-vsphere/test/infrastructure/vcsim/api/v1alpha1"
)
Expand Down
1 change: 0 additions & 1 deletion test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ require (
github.com/vmware-tanzu/net-operator-api v0.0.0-20240326163340-1f32d6bf7f9d
// The version of vm-operator should be kept in sync with the manifests at: config/deployments/integration-tests
github.com/vmware-tanzu/vm-operator/api v1.8.6
github.com/vmware-tanzu/vm-operator/external/tanzu-topology v0.0.0-20240404200847-de75746a9505
github.com/vmware/govmomi v0.39.0
)

Expand Down
Loading

0 comments on commit 204790f

Please sign in to comment.