add finalizer in resource binding and cluster resource binding

Signed-off-by: dddddai <dddwq@foxmail.com>
This commit is contained in:
dddddai 2021-09-29 11:21:51 +08:00
parent c4e22717df
commit ede9fad83c
5 changed files with 68 additions and 18 deletions

View File

@ -13,6 +13,7 @@ import (
"k8s.io/klog/v2"
controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
@ -45,19 +46,23 @@ func (c *ResourceBindingController) Reconcile(ctx context.Context, req controlle
binding := &workv1alpha2.ResourceBinding{}
if err := c.Client.Get(context.TODO(), req.NamespacedName, binding); err != nil {
// The resource no longer exist, clean up derived Work objects.
// The resource no longer exist, in which case we stop processing.
if apierrors.IsNotFound(err) {
return helper.DeleteWorks(c.Client, labels.Set{
workv1alpha2.ResourceBindingNamespaceLabel: req.Namespace,
workv1alpha2.ResourceBindingNameLabel: req.Name,
})
return controllerruntime.Result{}, nil
}
return controllerruntime.Result{Requeue: true}, err
}
if !binding.DeletionTimestamp.IsZero() {
return controllerruntime.Result{}, nil
if err := helper.DeleteWorks(c.Client, labels.Set{
workv1alpha2.ResourceBindingNamespaceLabel: req.Namespace,
workv1alpha2.ResourceBindingNameLabel: req.Name,
}); err != nil {
klog.Errorf("Failed to delete works related to %s/%s: %v", binding.GetNamespace(), binding.GetName(), err)
return controllerruntime.Result{Requeue: true}, err
}
return c.removeFinalizer(binding)
}
isReady := helper.IsBindingReady(binding.Spec.Clusters)
@ -69,6 +74,20 @@ func (c *ResourceBindingController) Reconcile(ctx context.Context, req controlle
return c.syncBinding(binding)
}
// removeFinalizer removes finalizer from the given ResourceBinding
func (c *ResourceBindingController) removeFinalizer(rb *workv1alpha2.ResourceBinding) (controllerruntime.Result, error) {
if !controllerutil.ContainsFinalizer(rb, util.BindingControllerFinalizer) {
return controllerruntime.Result{}, nil
}
controllerutil.RemoveFinalizer(rb, util.BindingControllerFinalizer)
err := c.Client.Update(context.TODO(), rb)
if err != nil {
return controllerruntime.Result{Requeue: true}, err
}
return controllerruntime.Result{}, nil
}
// syncBinding will sync resourceBinding to Works.
func (c *ResourceBindingController) syncBinding(binding *workv1alpha2.ResourceBinding) (controllerruntime.Result, error) {
clusterNames := helper.GetBindingClusterNames(binding.Spec.Clusters)

View File

@ -13,6 +13,7 @@ import (
"k8s.io/klog/v2"
controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
@ -45,18 +46,22 @@ func (c *ClusterResourceBindingController) Reconcile(ctx context.Context, req co
clusterResourceBinding := &workv1alpha2.ClusterResourceBinding{}
if err := c.Client.Get(context.TODO(), req.NamespacedName, clusterResourceBinding); err != nil {
// The resource no longer exist, clean up derived Work objects.
// The resource no longer exist, in which case we stop processing.
if apierrors.IsNotFound(err) {
return helper.DeleteWorks(c.Client, labels.Set{
workv1alpha2.ClusterResourceBindingLabel: req.Name,
})
return controllerruntime.Result{}, nil
}
return controllerruntime.Result{Requeue: true}, err
}
if !clusterResourceBinding.DeletionTimestamp.IsZero() {
return controllerruntime.Result{}, nil
if err := helper.DeleteWorks(c.Client, labels.Set{
workv1alpha2.ClusterResourceBindingLabel: req.Name,
}); err != nil {
klog.Errorf("Failed to delete works related to %s: %v", clusterResourceBinding.GetName(), err)
return controllerruntime.Result{Requeue: true}, err
}
return c.removeFinalizer(clusterResourceBinding)
}
isReady := helper.IsBindingReady(clusterResourceBinding.Spec.Clusters)
@ -68,6 +73,20 @@ func (c *ClusterResourceBindingController) Reconcile(ctx context.Context, req co
return c.syncBinding(clusterResourceBinding)
}
// removeFinalizer removes finalizer from the given ClusterResourceBinding
func (c *ClusterResourceBindingController) removeFinalizer(crb *workv1alpha2.ClusterResourceBinding) (controllerruntime.Result, error) {
if !controllerutil.ContainsFinalizer(crb, util.ClusterResourceBindingControllerFinalizer) {
return controllerruntime.Result{}, nil
}
controllerutil.RemoveFinalizer(crb, util.ClusterResourceBindingControllerFinalizer)
err := c.Client.Update(context.TODO(), crb)
if err != nil {
return controllerruntime.Result{Requeue: true}, err
}
return controllerruntime.Result{}, nil
}
// syncBinding will sync clusterResourceBinding to Works.
func (c *ClusterResourceBindingController) syncBinding(binding *workv1alpha2.ClusterResourceBinding) (controllerruntime.Result, error) {
clusterNames := helper.GetBindingClusterNames(binding.Spec.Clusters)

View File

@ -43,6 +43,14 @@ const (
// ExecutionControllerFinalizer is added to Work to ensure manifests propagated to member cluster
// is deleted before Work itself is deleted.
ExecutionControllerFinalizer = "karmada.io/execution-controller"
// BindingControllerFinalizer is added to ResourceBinding to ensure related Works are deleted
// before ResourceBinding itself is deleted.
BindingControllerFinalizer = "karmada.io/binding-controller"
// ClusterResourceBindingControllerFinalizer is added to ClusterResourceBinding to ensure related Works are deleted
// before ClusterResourceBinding itself is deleted.
ClusterResourceBindingControllerFinalizer = "karmada.io/cluster-resource-binding-controller"
)
const (

View File

@ -438,6 +438,7 @@ func (d *ResourceDetector) ApplyPolicy(object *unstructured.Unstructured, object
// Just update necessary fields, especially avoid modifying Spec.Clusters which is scheduling result, if already exists.
bindingCopy.Labels = binding.Labels
bindingCopy.OwnerReferences = binding.OwnerReferences
bindingCopy.Finalizers = binding.Finalizers
bindingCopy.Spec.Resource = binding.Spec.Resource
bindingCopy.Spec.ReplicaRequirements = binding.Spec.ReplicaRequirements
bindingCopy.Spec.Replicas = binding.Spec.Replicas
@ -486,6 +487,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
// Just update necessary fields, especially avoid modifying Spec.Clusters which is scheduling result, if already exists.
bindingCopy.Labels = binding.Labels
bindingCopy.OwnerReferences = binding.OwnerReferences
bindingCopy.Finalizers = binding.Finalizers
bindingCopy.Spec.Resource = binding.Spec.Resource
bindingCopy.Spec.ReplicaRequirements = binding.Spec.ReplicaRequirements
bindingCopy.Spec.Replicas = binding.Spec.Replicas
@ -515,6 +517,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
// Just update necessary fields, especially avoid modifying Spec.Clusters which is scheduling result, if already exists.
bindingCopy.Labels = binding.Labels
bindingCopy.OwnerReferences = binding.OwnerReferences
bindingCopy.Finalizers = binding.Finalizers
bindingCopy.Spec.Resource = binding.Spec.Resource
bindingCopy.Spec.ReplicaRequirements = binding.Spec.ReplicaRequirements
bindingCopy.Spec.Replicas = binding.Spec.Replicas
@ -625,7 +628,8 @@ func (d *ResourceDetector) BuildResourceBinding(object *unstructured.Unstructure
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(object, objectKey.GroupVersionKind()),
},
Labels: labels,
Labels: labels,
Finalizers: []string{util.BindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: workv1alpha2.ObjectReference{
@ -656,7 +660,8 @@ func (d *ResourceDetector) BuildClusterResourceBinding(object *unstructured.Unst
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(object, objectKey.GroupVersionKind()),
},
Labels: labels,
Labels: labels,
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: workv1alpha2.ObjectReference{

View File

@ -15,7 +15,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/dynamic"
"k8s.io/klog/v2"
controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
@ -175,11 +174,11 @@ func GetWorks(c client.Client, ls labels.Set) (*workv1alpha1.WorkList, error) {
}
// DeleteWorks will delete all Work objects by labels.
func DeleteWorks(c client.Client, selector labels.Set) (controllerruntime.Result, error) {
func DeleteWorks(c client.Client, selector labels.Set) error {
workList, err := GetWorks(c, selector)
if err != nil {
klog.Errorf("Failed to get works by label %v: %v", selector, err)
return controllerruntime.Result{Requeue: true}, err
return err
}
var errs []error
@ -191,10 +190,10 @@ func DeleteWorks(c client.Client, selector labels.Set) (controllerruntime.Result
}
if len(errs) > 0 {
return controllerruntime.Result{Requeue: true}, errors.NewAggregate(errs)
return errors.NewAggregate(errs)
}
return controllerruntime.Result{}, nil
return nil
}
// GenerateNodeClaimByPodSpec will return a NodeClaim from PodSpec.