mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-23 17:43:25 +00:00
129 lines
4.7 KiB
Go
129 lines
4.7 KiB
Go
package finalizercontroller
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
workv1client "github.com/open-cluster-management/api/client/work/clientset/versioned/typed/work/v1"
|
|
workinformer "github.com/open-cluster-management/api/client/work/informers/externalversions/work/v1"
|
|
worklister "github.com/open-cluster-management/api/client/work/listers/work/v1"
|
|
"github.com/open-cluster-management/work/pkg/helper"
|
|
"github.com/open-cluster-management/work/pkg/spoke/controllers"
|
|
"github.com/openshift/library-go/pkg/controller/factory"
|
|
"github.com/openshift/library-go/pkg/operator/events"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/client-go/util/workqueue"
|
|
"k8s.io/klog/v2"
|
|
)
|
|
|
|
// ManifestWorkFinalizeController handles cleanup of manifestwork resources before deletion is allowed.
|
|
type ManifestWorkFinalizeController struct {
|
|
manifestWorkClient workv1client.ManifestWorkInterface
|
|
manifestWorkLister worklister.ManifestWorkNamespaceLister
|
|
appliedManifestWorkClient workv1client.AppliedManifestWorkInterface
|
|
appliedManifestWorkLister worklister.AppliedManifestWorkLister
|
|
hubHash string
|
|
rateLimiter workqueue.RateLimiter
|
|
}
|
|
|
|
func NewManifestWorkFinalizeController(
|
|
recorder events.Recorder,
|
|
manifestWorkClient workv1client.ManifestWorkInterface,
|
|
manifestWorkInformer workinformer.ManifestWorkInformer,
|
|
manifestWorkLister worklister.ManifestWorkNamespaceLister,
|
|
appliedManifestWorkClient workv1client.AppliedManifestWorkInterface,
|
|
appliedManifestWorkInformer workinformer.AppliedManifestWorkInformer,
|
|
hubHash string,
|
|
) factory.Controller {
|
|
|
|
controller := &ManifestWorkFinalizeController{
|
|
manifestWorkClient: manifestWorkClient,
|
|
manifestWorkLister: manifestWorkLister,
|
|
appliedManifestWorkClient: appliedManifestWorkClient,
|
|
appliedManifestWorkLister: appliedManifestWorkInformer.Lister(),
|
|
hubHash: hubHash,
|
|
rateLimiter: workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
|
|
}
|
|
|
|
return factory.New().
|
|
WithInformersQueueKeyFunc(func(obj runtime.Object) string {
|
|
accessor, _ := meta.Accessor(obj)
|
|
return accessor.GetName()
|
|
}, manifestWorkInformer.Informer()).
|
|
WithInformersQueueKeyFunc(helper.AppliedManifestworkQueueKeyFunc(hubHash), appliedManifestWorkInformer.Informer()).
|
|
WithSync(controller.sync).ToController("ManifestWorkFinalizer", recorder)
|
|
}
|
|
|
|
func (m *ManifestWorkFinalizeController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
|
|
manifestWorkName := controllerContext.QueueKey()
|
|
appliedManifestWorkName := fmt.Sprintf("%s-%s", m.hubHash, manifestWorkName)
|
|
klog.V(4).Infof("Reconciling ManifestWork %q", manifestWorkName)
|
|
|
|
manifestWork, err := m.manifestWorkLister.Get(manifestWorkName)
|
|
|
|
// Delete appliedmanifestwork if relating manfiestwork is not found or being deleted
|
|
switch {
|
|
case errors.IsNotFound(err):
|
|
err := m.deleteAppliedManifestWork(ctx, appliedManifestWorkName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case err != nil:
|
|
return err
|
|
case !manifestWork.DeletionTimestamp.IsZero():
|
|
err := m.deleteAppliedManifestWork(ctx, appliedManifestWorkName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return nil
|
|
}
|
|
|
|
_, err = m.appliedManifestWorkLister.Get(appliedManifestWorkName)
|
|
switch {
|
|
case errors.IsNotFound(err):
|
|
// if the instance is not found, then we simply continue below this block to remove the finalizer
|
|
case err != nil:
|
|
return err
|
|
default:
|
|
// appliedmanifestwork still exists, requeue the manifestwork to check in the next loop.
|
|
controllerContext.Queue().AddAfter(manifestWorkName, m.rateLimiter.When(manifestWorkName))
|
|
return nil
|
|
|
|
}
|
|
|
|
// Now we can remove manifestwork finalizer
|
|
// Skip if it is an orphaned appliedmanifestwork
|
|
if manifestWork == nil {
|
|
return nil
|
|
}
|
|
|
|
m.rateLimiter.Forget(manifestWorkName)
|
|
manifestWork = manifestWork.DeepCopy()
|
|
helper.RemoveFinalizer(manifestWork, controllers.ManifestWorkFinalizer)
|
|
_, err = m.manifestWorkClient.Update(ctx, manifestWork, metav1.UpdateOptions{})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to remove finalizer from ManifestWork %s/%s: %w", manifestWork.Namespace, manifestWork.Name, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *ManifestWorkFinalizeController) deleteAppliedManifestWork(ctx context.Context, appliedManifestWorkName string) error {
|
|
appliedManifestWork, err := m.appliedManifestWorkLister.Get(appliedManifestWorkName)
|
|
switch {
|
|
case errors.IsNotFound(err):
|
|
return nil
|
|
case err != nil:
|
|
return err
|
|
case !appliedManifestWork.DeletionTimestamp.IsZero():
|
|
return nil
|
|
}
|
|
|
|
return m.appliedManifestWorkClient.Delete(ctx, appliedManifestWorkName, metav1.DeleteOptions{})
|
|
}
|