Skip to content

Commit

Permalink
fix: Watch for changes in CloudStackCluster in the isonet controller …
Browse files Browse the repository at this point in the history
…and reconcile if needed
  • Loading branch information
hrak committed Aug 14, 2024
1 parent dd138bd commit e1a022d
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 7 deletions.
42 changes: 40 additions & 2 deletions controllers/cloudstackisolatednetwork_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ package controllers

import (
"context"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"strings"

"sigs.k8s.io/cluster-api/util/patch"
Expand All @@ -40,7 +45,7 @@ type CloudStackIsoNetReconciler struct {
csCtrlrUtils.ReconcilerBase
}

// CloudStackZoneReconciliationRunner is a ReconciliationRunner with extensions specific to CloudStack isolated network reconciliation.
// CloudStackIsoNetReconciliationRunner is a ReconciliationRunner with extensions specific to CloudStack isolated network reconciliation.
type CloudStackIsoNetReconciliationRunner struct {
*csCtrlrUtils.ReconciliationRunner
FailureDomain *infrav1.CloudStackFailureDomain
Expand Down Expand Up @@ -107,8 +112,41 @@ func (r *CloudStackIsoNetReconciliationRunner) ReconcileDelete() (retRes ctrl.Re

// SetupWithManager sets up the controller with the Manager.
func (reconciler *CloudStackIsoNetReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
CloudStackClusterToCloudStackIsolatedNetworks, err := csCtrlrUtils.CloudStackClusterToCloudStackIsolatedNetworks(reconciler.K8sClient, &infrav1.CloudStackIsolatedNetworkList{}, reconciler.Scheme, ctrl.LoggerFrom(ctx))
if err != nil {
return errors.Wrap(err, "failed to create CloudStackClusterToCloudStackIsolatedNetworks mapper")
}

err = ctrl.NewControllerManagedBy(mgr).
For(&infrav1.CloudStackIsolatedNetwork{}).
Watches(
&infrav1.CloudStackCluster{},
handler.EnqueueRequestsFromMapFunc(CloudStackClusterToCloudStackIsolatedNetworks),
builder.WithPredicates(
predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
oldCSCluster := e.ObjectOld.(*infrav1.CloudStackCluster)
newCSCluster := e.ObjectNew.(*infrav1.CloudStackCluster)

// APIServerLoadBalancer disabled in both new and old
if oldCSCluster.Spec.APIServerLoadBalancer == nil && newCSCluster.Spec.APIServerLoadBalancer == nil {
return false
}
// APIServerLoadBalancer toggled
if oldCSCluster.Spec.APIServerLoadBalancer == nil || newCSCluster.Spec.APIServerLoadBalancer == nil {
return true
}

return !reflect.DeepEqual(oldCSCluster.Spec.APIServerLoadBalancer, newCSCluster.Spec.APIServerLoadBalancer)
},
},
),
).
WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), reconciler.WatchFilterValue)).
Complete(reconciler)
if err != nil {
return errors.Wrap(err, "failed setting up with a controller manager")
}

return nil
}
2 changes: 1 addition & 1 deletion controllers/cloudstackmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ func (reconciler *CloudStackMachineReconciler) SetupWithManager(ctx context.Cont
//requeueCloudStackMachinesForUnpausedCluster := reconciler.requeueCloudStackMachinesForUnpausedCluster(ctx)
csMachineMapper, err := util.ClusterToTypedObjectsMapper(reconciler.K8sClient, &infrav1.CloudStackMachineList{}, reconciler.Scheme)
if err != nil {
return errors.Wrap(err, "failed to create mapper for Cluster to AzureMachines")
return errors.Wrap(err, "failed to create mapper for Cluster to CloudStackMachines")
}

err = ctrl.NewControllerManagedBy(mgr).
Expand Down
63 changes: 59 additions & 4 deletions controllers/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package utils
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"strings"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -111,18 +113,19 @@ func GetOwnerClusterName(obj metav1.ObjectMeta) (string, error) {
return "", errors.New("failed to get owner Cluster name")
}

// CloudStackClusterToCloudStackMachines is a handler.ToRequestsFunc to be used to enqeue requests for reconciliation
// CloudStackClusterToCloudStackMachines is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation
// of CloudStackMachines.
func CloudStackClusterToCloudStackMachines(c client.Client, obj runtime.Object, scheme *runtime.Scheme, log logr.Logger) (handler.MapFunc, error) {
func CloudStackClusterToCloudStackMachines(c client.Client, obj client.ObjectList, scheme *runtime.Scheme, log logr.Logger) (handler.MapFunc, error) {
gvk, err := apiutil.GVKForObject(obj, scheme)
if err != nil {
return nil, errors.Wrap(err, "failed to find GVK for CloudStackMachine")
}

return func(ctx context.Context, o client.Object) []ctrl.Request {
return func(ctx context.Context, o client.Object) []reconcile.Request {
csCluster, ok := o.(*infrav1.CloudStackCluster)
if !ok {
log.Error(fmt.Errorf("expected a CloudStackCluster but got a %T", o), "Error in CloudStackClusterToCloudStackMachines")
return nil
}

log = log.WithValues("objectMapper", "cloudstackClusterToCloudStackMachine", "cluster", klog.KRef(csCluster.Namespace, csCluster.Name))
Expand All @@ -141,7 +144,7 @@ func CloudStackClusterToCloudStackMachines(c client.Client, obj runtime.Object,

machineList := &clusterv1.MachineList{}
machineList.SetGroupVersionKind(gvk)
// list all of the requested objects within the cluster namespace with the cluster name label
// list all the requested objects within the cluster namespace with the cluster name label
if err := c.List(ctx, machineList, client.InNamespace(csCluster.Namespace), client.MatchingLabels{clusterv1.ClusterNameLabel: clusterName}); err != nil {
return nil
}
Expand All @@ -158,6 +161,58 @@ func CloudStackClusterToCloudStackMachines(c client.Client, obj runtime.Object,
}, nil
}

// CloudStackClusterToCloudStackIsolatedNetworks is a handler.ToRequestsFunc to be used to enqueue requests for reconciliation
// of CloudStackIsolatedNetworks.
func CloudStackClusterToCloudStackIsolatedNetworks(c client.Client, obj client.ObjectList, scheme *runtime.Scheme, log logr.Logger) (handler.MapFunc, error) {
gvk, err := apiutil.GVKForObject(obj, scheme)
if err != nil {
return nil, errors.Wrap(err, "failed to find GVK for CloudStackIsolatedNetwork")
}

return func(ctx context.Context, o client.Object) []reconcile.Request {
csCluster, ok := o.(*infrav1.CloudStackCluster)
if !ok {
log.Error(fmt.Errorf("expected a CloudStackCluster but got a %T", o), "Error in CloudStackClusterToCloudStackIsolatedNetworks")
return nil
}

log = log.WithValues("objectMapper", "cloudstackClusterToCloudStackIsolatedNetworks", "cluster", klog.KRef(csCluster.Namespace, csCluster.Name))

// Don't handle deleted CloudStackClusters
if !csCluster.ObjectMeta.DeletionTimestamp.IsZero() {
log.V(4).Info("CloudStackCluster has a deletion timestamp, skipping mapping.")
return nil
}

clusterName, err := GetOwnerClusterName(csCluster.ObjectMeta)
if err != nil {
log.Error(err, "Failed to get owning cluster, skipping mapping.")
return nil
}

isonetList := &infrav1.CloudStackIsolatedNetworkList{}
isonetList.SetGroupVersionKind(gvk)

// list all the requested objects within the cluster namespace with the cluster name label
if err := c.List(ctx, isonetList, client.InNamespace(csCluster.Namespace), client.MatchingLabels{clusterv1.ClusterNameLabel: clusterName}); err != nil {
return nil
}

var results []reconcile.Request
for _, isonet := range isonetList.Items {
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: isonet.GetNamespace(),
Name: isonet.GetName(),
},
}
results = append(results, req)
}

return results
}, nil
}

// DebugPredicate returns a predicate that logs the event that triggered the reconciliation
func DebugPredicate(logger logr.Logger) predicate.Funcs {
return predicate.Funcs{
Expand Down

0 comments on commit e1a022d

Please sign in to comment.