Skip to content

Commit

Permalink
Update v1 controller to cleanup finalizer on CAPI clusters
Browse files Browse the repository at this point in the history
Signed-off-by: Danil-Grigorev <danil.grigorev@suse.com>
  • Loading branch information
Danil-Grigorev committed Jul 12, 2024
1 parent 47dbec6 commit cbe0e63
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 9 deletions.
55 changes: 52 additions & 3 deletions internal/controllers/import_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
Expand All @@ -43,6 +45,7 @@ import (
"sigs.k8s.io/cluster-api/util/predicates"

"github.com/rancher/turtles/feature"
managementv3 "github.com/rancher/turtles/internal/rancher/management/v3"
provisioningv1 "github.com/rancher/turtles/internal/rancher/provisioning/v1"
"github.com/rancher/turtles/util"
turtlesannotations "github.com/rancher/turtles/util/annotations"
Expand Down Expand Up @@ -143,16 +146,23 @@ func (r *CAPIImportReconciler) Reconcile(ctx context.Context, req ctrl.Request)

log = log.WithValues("cluster", capiCluster.Name)

// Collect errors as an aggregate to return together after all patches have been performed.
var errs []error

if !capiCluster.ObjectMeta.DeletionTimestamp.IsZero() && controllerutil.RemoveFinalizer(capiCluster, managementv3.CapiClusterFinalizer) {
if err := r.Client.Patch(ctx, capiCluster, patchBase); err != nil {
log.Error(err, "failed to remove CAPI cluster finalizer "+managementv3.CapiClusterFinalizer)
errs = append(errs, err)
}
}

// Wait for controlplane to be ready. This should never be false as the predicates
// do the filtering.
if !capiCluster.Status.ControlPlaneReady && !conditions.IsTrue(capiCluster, clusterv1.ControlPlaneReadyCondition) {
log.Info("clusters control plane is not ready, requeue")
return ctrl.Result{RequeueAfter: defaultRequeueDuration}, nil
}

// Collect errors as an aggregate to return together after all patches have been performed.
var errs []error

result, err := r.reconcile(ctx, capiCluster)
if err != nil {
errs = append(errs, fmt.Errorf("error reconciling cluster: %w", err))
Expand Down Expand Up @@ -350,3 +360,42 @@ func (r *CAPIImportReconciler) reconcileDelete(ctx context.Context, capiCluster

return ctrl.Result{}, nil
}

// CAPIDowngradeReconciler is a reconciler for downgraded managementv3 clusters.
type CAPIDowngradeReconciler struct {
RancherClient client.Client
Scheme *runtime.Scheme
}

// SetupWithManager sets up reconciler with manager.
func (r *CAPIDowngradeReconciler) SetupWithManager(_ context.Context, mgr ctrl.Manager, options controller.Options) error {
if err := ctrl.NewControllerManagedBy(mgr).
For(&managementv3.Cluster{}).
WithOptions(options).
WithEventFilter(predicate.NewPredicateFuncs(func(object client.Object) bool {
_, exist := object.GetLabels()[ownedLabelName]
return exist
})).
Complete(reconcile.AsReconciler(r.RancherClient, r)); err != nil {
return fmt.Errorf("creating new downgrade controller: %w", err)
}

return nil
}

// Reconcile performs check for downgraded clusters and removes finalizer on the clusters still owned by the previous management v3 controller.
func (r *CAPIDowngradeReconciler) Reconcile(ctx context.Context, cluster *managementv3.Cluster) (res ctrl.Result, err error) {
log := log.FromContext(ctx)

patchBase := client.MergeFromWithOptions(cluster.DeepCopy(), client.MergeFromWithOptimisticLock{})

if !controllerutil.RemoveFinalizer(cluster, managementv3.CapiClusterFinalizer) {
return
}

if err = r.RancherClient.Patch(ctx, cluster, patchBase); err != nil {
log.Error(err, "Unable to remove turtles finalizer from cluster"+cluster.Name)
}

return
}
19 changes: 19 additions & 0 deletions internal/controllers/import_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,25 @@ var _ = Describe("reconcile CAPI Cluster", func() {
}).Should(Succeed())
})

It("should remove a CAPI cluster with turtles finalizer", func() {
capiCluster.Finalizers = []string{managementv3.CapiClusterFinalizer}
Expect(cl.Create(ctx, capiCluster)).To(Succeed())
capiCluster.Status.ControlPlaneReady = true
Expect(cl.Status().Update(ctx, capiCluster)).To(Succeed())
Expect(cl.Delete(ctx, capiCluster)).To(Succeed())

Eventually(func(g Gomega) {
_, err := r.Reconcile(ctx, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: capiCluster.Namespace,
Name: capiCluster.Name,
},
})
g.Expect(err).ToNot(HaveOccurred())
g.Expect(cl.Get(ctx, client.ObjectKeyFromObject(capiCluster), capiCluster)).To(HaveOccurred())
}).Should(Succeed())
})

It("should reconcile a CAPI cluster when rancher cluster doesn't exist", func() {
capiCluster.Labels = map[string]string{
importLabelName: "true",
Expand Down
12 changes: 6 additions & 6 deletions internal/controllers/import_controller_v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,15 @@ func (r *CAPIImportManagementV3Reconciler) Reconcile(ctx context.Context, req ct
// Collect errors as an aggregate to return together after all patches have been performed.
var errs []error

patchBase := client.MergeFromWithOptions(capiCluster.DeepCopy(), client.MergeFromWithOptimisticLock{})

result, err := r.reconcile(ctx, capiCluster)
if err != nil {
errs = append(errs, fmt.Errorf("error reconciling cluster: %w", err))
}

if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
capiClusterCopy := capiCluster.DeepCopy()

patchBase := client.MergeFromWithOptions(capiCluster, client.MergeFromWithOptimisticLock{})

if err := r.Client.Patch(ctx, capiClusterCopy, patchBase); err != nil {
if err := r.Client.Patch(ctx, capiCluster, patchBase); err != nil {
errs = append(errs, fmt.Errorf("failed to patch cluster: %w", err))
}
return nil
Expand Down Expand Up @@ -456,6 +454,8 @@ func (r *CAPIImportManagementV3Reconciler) reconcileDelete(ctx context.Context,
capiCluster.Name,
turtlesannotations.ClusterImportedAnnotation))

patchBase := client.MergeFromWithOptions(capiCluster.DeepCopy(), client.MergeFromWithOptimisticLock{})

annotations := capiCluster.GetAnnotations()
if annotations == nil {
annotations = map[string]string{}
Expand All @@ -465,7 +465,7 @@ func (r *CAPIImportManagementV3Reconciler) reconcileDelete(ctx context.Context,
capiCluster.SetAnnotations(annotations)
controllerutil.RemoveFinalizer(capiCluster, managementv3.CapiClusterFinalizer)

if err := r.Client.Update(ctx, capiCluster); err != nil {
if err := r.Client.Patch(ctx, capiCluster, patchBase); err != nil {
return fmt.Errorf("error removing finalizer: %w", err)
}

Expand Down
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager) {
setupLog.Error(err, "unable to create capi controller")
os.Exit(1)
}

if err := (&controllers.CAPIDowngradeReconciler{
RancherClient: rancherClient,
}).SetupWithManager(ctx, mgr, controller.Options{
MaxConcurrentReconciles: concurrencyNumber,
}); err != nil {
setupLog.Error(err, "unable to create rancher management v3 downgrade controller")
os.Exit(1)
}
}

if feature.Gates.Enabled(feature.RancherKubeSecretPatch) {
Expand Down

0 comments on commit cbe0e63

Please sign in to comment.