Add binding event

Signed-off-by: pigletfly <wangbing.adam@gmail.com>
This commit is contained in:
pigletfly 2021-09-09 17:03:12 +08:00 committed by changzhen
parent 8343abc4ab
commit 8600106853
3 changed files with 102 additions and 52 deletions

View File

@ -199,24 +199,24 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
klog.Fatalf("Failed to setup policy controller: %v", err)
}
bindingController := &binding.ResourceBindingController{
Client: mgr.GetClient(),
DynamicClient: dynamicClientSet,
EventRecorder: mgr.GetEventRecorderFor(binding.ControllerName),
RESTMapper: mgr.GetRESTMapper(),
OverrideManager: overrideManager,
}
bindingController := binding.NewResourceBindingController(
mgr.GetClient(),
dynamicClientSet,
mgr.GetEventRecorderFor(binding.ControllerName),
mgr.GetRESTMapper(),
overrideManager,
)
if err := bindingController.SetupWithManager(mgr); err != nil {
klog.Fatalf("Failed to setup binding controller: %v", err)
}
clusterResourceBindingController := &binding.ClusterResourceBindingController{
Client: mgr.GetClient(),
DynamicClient: dynamicClientSet,
EventRecorder: mgr.GetEventRecorderFor(binding.ClusterResourceBindingControllerName),
RESTMapper: mgr.GetRESTMapper(),
OverrideManager: overrideManager,
}
clusterResourceBindingController := binding.NewClusterResourceBindingController(
mgr.GetClient(),
dynamicClientSet,
mgr.GetEventRecorderFor(binding.ClusterResourceBindingControllerName),
mgr.GetRESTMapper(),
overrideManager,
)
if err := clusterResourceBindingController.SetupWithManager(mgr); err != nil {
klog.Fatalf("Failed to setup cluster resource binding controller: %v", err)
}

View File

@ -2,7 +2,9 @@ package binding
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
@ -26,16 +28,34 @@ import (
"github.com/karmada-io/karmada/pkg/util/overridemanager"
)
// ControllerName is the controller name that will be used when reporting events.
const ControllerName = "binding-controller"
const (
// ControllerName is the controller name that will be used when reporting events.
ControllerName = "binding-controller"
eventTypeFindOrphanWorks = "FindOrphanWorks"
eventTypeFetchWorkload = "FetchWorkload"
eventTypeTransformResourceBinding = "TransformResourceBinding"
eventTypeAggregateWorkStatuses = "AggregateWorkStatuses"
)
// ResourceBindingController is to sync ResourceBinding.
type ResourceBindingController struct {
client.Client // used to operate ResourceBinding resources.
DynamicClient dynamic.Interface // used to fetch arbitrary resources.
EventRecorder record.EventRecorder
RESTMapper meta.RESTMapper
OverrideManager overridemanager.OverrideManager
client client.Client // used to operate ResourceBinding resources.
dynamicClient dynamic.Interface // used to fetch arbitrary resources.
recorder record.EventRecorder
restMapper meta.RESTMapper
overrideManager overridemanager.OverrideManager
}
// NewResourceBindingController creates a new ResourceBindingController.
func NewResourceBindingController(client client.Client, dynamicClient dynamic.Interface, recorder record.EventRecorder, restMapper meta.RESTMapper, overrideManager overridemanager.OverrideManager) *ResourceBindingController {
rbConroller := ResourceBindingController{
client: client,
dynamicClient: dynamicClient,
recorder: recorder,
restMapper: restMapper,
overrideManager: overrideManager,
}
return &rbConroller
}
// Reconcile performs a full reconciliation for the object referred to by the Request.
@ -45,7 +65,7 @@ func (c *ResourceBindingController) Reconcile(ctx context.Context, req controlle
klog.V(4).Infof("Reconciling ResourceBinding %s.", req.NamespacedName.String())
binding := &workv1alpha2.ResourceBinding{}
if err := c.Client.Get(context.TODO(), req.NamespacedName, binding); err != nil {
if err := c.client.Get(context.TODO(), req.NamespacedName, binding); err != nil {
// The resource no longer exist, in which case we stop processing.
if apierrors.IsNotFound(err) {
return controllerruntime.Result{}, nil
@ -55,7 +75,7 @@ func (c *ResourceBindingController) Reconcile(ctx context.Context, req controlle
}
if !binding.DeletionTimestamp.IsZero() {
if err := helper.DeleteWorks(c.Client, labels.Set{
if err := helper.DeleteWorks(c.client, labels.Set{
workv1alpha2.ResourceBindingNamespaceLabel: req.Namespace,
workv1alpha2.ResourceBindingNameLabel: req.Name,
}); err != nil {
@ -67,7 +87,10 @@ func (c *ResourceBindingController) Reconcile(ctx context.Context, req controlle
isReady := helper.IsBindingReady(binding.Spec.Clusters)
if !isReady {
klog.Infof("ResourceBinding(%s/%s) is not ready to sync", binding.GetNamespace(), binding.GetName())
msg := fmt.Sprintf("ResourceBinding %s is not ready.", req.NamespacedName.String())
klog.Infof(msg)
c.recorder.Event(binding, corev1.EventTypeWarning, "ResourceBindingNotReady", msg)
return controllerruntime.Result{}, nil
}
@ -81,7 +104,7 @@ func (c *ResourceBindingController) removeFinalizer(rb *workv1alpha2.ResourceBin
}
controllerutil.RemoveFinalizer(rb, util.BindingControllerFinalizer)
err := c.Client.Update(context.TODO(), rb)
err := c.client.Update(context.TODO(), rb)
if err != nil {
return controllerruntime.Result{Requeue: true}, err
}
@ -91,41 +114,47 @@ func (c *ResourceBindingController) removeFinalizer(rb *workv1alpha2.ResourceBin
// syncBinding will sync resourceBinding to Works.
func (c *ResourceBindingController) syncBinding(binding *workv1alpha2.ResourceBinding) (controllerruntime.Result, error) {
clusterNames := helper.GetBindingClusterNames(binding.Spec.Clusters)
works, err := helper.FindOrphanWorks(c.Client, binding.Namespace, binding.Name, clusterNames, apiextensionsv1.NamespaceScoped)
works, err := helper.FindOrphanWorks(c.client, binding.Namespace, binding.Name, clusterNames, apiextensionsv1.NamespaceScoped)
if err != nil {
klog.Errorf("Failed to find orphan works by resourceBinding(%s/%s). Error: %v.",
binding.GetNamespace(), binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFindOrphanWorks), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
err = helper.RemoveOrphanWorks(c.Client, works)
err = helper.RemoveOrphanWorks(c.client, works)
if err != nil {
klog.Errorf("Failed to remove orphan works by resourceBinding(%s/%s). Error: %v.",
binding.GetNamespace(), binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFindOrphanWorks), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for resourceBinding(%s/%s). Error: %v.",
binding.GetNamespace(), binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFetchWorkload), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
err = ensureWork(c.Client, workload, c.OverrideManager, binding, apiextensionsv1.NamespaceScoped)
err = ensureWork(c.client, workload, c.overrideManager, binding, apiextensionsv1.NamespaceScoped)
if err != nil {
klog.Errorf("Failed to transform resourceBinding(%s/%s) to works. Error: %v.",
binding.GetNamespace(), binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeTransformResourceBinding), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
err = helper.AggregateResourceBindingWorkStatus(c.Client, binding, workload)
err = helper.AggregateResourceBindingWorkStatus(c.client, binding, workload)
if err != nil {
klog.Errorf("Failed to aggregate workStatuses to resourceBinding(%s/%s). Error: %v.",
binding.GetNamespace(), binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeAggregateWorkStatuses), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
klog.V(4).Infof("Update resourceBinding(%s/%s) with AggregatedStatus successfully.", binding.Namespace, binding.Name)
c.recorder.Event(binding, corev1.EventTypeNormal, "SyncResourceBinding", "ResourceBinding synced successfully")
return controllerruntime.Result{}, nil
}
@ -172,14 +201,14 @@ func (c *ResourceBindingController) newOverridePolicyFunc() handler.MapFunc {
}
bindingList := &workv1alpha2.ResourceBindingList{}
if err := c.Client.List(context.TODO(), bindingList); err != nil {
if err := c.client.List(context.TODO(), bindingList); err != nil {
klog.Errorf("Failed to list resourceBindings, error: %v", err)
return nil
}
var requests []reconcile.Request
for _, binding := range bindingList.Items {
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for resourceBinding(%s/%s). Error: %v.", binding.Namespace, binding.Name, err)
return nil
@ -201,14 +230,14 @@ func (c *ResourceBindingController) newReplicaSchedulingPolicyFunc() handler.Map
return func(a client.Object) []reconcile.Request {
rspResourceSelectors := a.(*policyv1alpha1.ReplicaSchedulingPolicy).Spec.ResourceSelectors
bindingList := &workv1alpha2.ResourceBindingList{}
if err := c.Client.List(context.TODO(), bindingList); err != nil {
if err := c.client.List(context.TODO(), bindingList); err != nil {
klog.Errorf("Failed to list resourceBindings, error: %v", err)
return nil
}
var requests []reconcile.Request
for _, binding := range bindingList.Items {
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for resourceBinding(%s/%s). Error: %v.", binding.Namespace, binding.Name, err)
return nil

View File

@ -2,7 +2,9 @@ package binding
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
@ -31,11 +33,23 @@ const ClusterResourceBindingControllerName = "cluster-resource-binding-controlle
// ClusterResourceBindingController is to sync ClusterResourceBinding.
type ClusterResourceBindingController struct {
client.Client // used to operate ClusterResourceBinding resources.
DynamicClient dynamic.Interface // used to fetch arbitrary resources.
EventRecorder record.EventRecorder
RESTMapper meta.RESTMapper
OverrideManager overridemanager.OverrideManager
client client.Client // used to operate ClusterResourceBinding resources.
dynamicClient dynamic.Interface // used to fetch arbitrary resources.
recorder record.EventRecorder
restMapper meta.RESTMapper
overrideManager overridemanager.OverrideManager
}
// NewClusterResourceBindingController creates a new ClusterResourceBindingController.
func NewClusterResourceBindingController(client client.Client, dynamicClient dynamic.Interface, recorder record.EventRecorder, restMapper meta.RESTMapper, overrideManager overridemanager.OverrideManager) *ClusterResourceBindingController {
crbConroller := ClusterResourceBindingController{
client: client,
dynamicClient: dynamicClient,
recorder: recorder,
restMapper: restMapper,
overrideManager: overrideManager,
}
return &crbConroller
}
// Reconcile performs a full reconciliation for the object referred to by the Request.
@ -45,7 +59,7 @@ func (c *ClusterResourceBindingController) Reconcile(ctx context.Context, req co
klog.V(4).Infof("Reconciling ClusterResourceBinding %s.", req.NamespacedName.String())
clusterResourceBinding := &workv1alpha2.ClusterResourceBinding{}
if err := c.Client.Get(context.TODO(), req.NamespacedName, clusterResourceBinding); err != nil {
if err := c.client.Get(context.TODO(), req.NamespacedName, clusterResourceBinding); err != nil {
// The resource no longer exist, in which case we stop processing.
if apierrors.IsNotFound(err) {
return controllerruntime.Result{}, nil
@ -55,7 +69,7 @@ func (c *ClusterResourceBindingController) Reconcile(ctx context.Context, req co
}
if !clusterResourceBinding.DeletionTimestamp.IsZero() {
if err := helper.DeleteWorks(c.Client, labels.Set{
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)
@ -66,7 +80,10 @@ func (c *ClusterResourceBindingController) Reconcile(ctx context.Context, req co
isReady := helper.IsBindingReady(clusterResourceBinding.Spec.Clusters)
if !isReady {
klog.Infof("ClusterResourceBinding %s is not ready to sync", clusterResourceBinding.GetName())
msg := fmt.Sprintf("ClusterResourceBinding %s is not ready to sync.", clusterResourceBinding.GetName())
klog.Infof(msg)
c.recorder.Event(clusterResourceBinding, corev1.EventTypeWarning, "ResourceBindingNotReady", msg)
return controllerruntime.Result{}, nil
}
@ -80,7 +97,7 @@ func (c *ClusterResourceBindingController) removeFinalizer(crb *workv1alpha2.Clu
}
controllerutil.RemoveFinalizer(crb, util.ClusterResourceBindingControllerFinalizer)
err := c.Client.Update(context.TODO(), crb)
err := c.client.Update(context.TODO(), crb)
if err != nil {
return controllerruntime.Result{Requeue: true}, err
}
@ -90,33 +107,37 @@ func (c *ClusterResourceBindingController) removeFinalizer(crb *workv1alpha2.Clu
// syncBinding will sync clusterResourceBinding to Works.
func (c *ClusterResourceBindingController) syncBinding(binding *workv1alpha2.ClusterResourceBinding) (controllerruntime.Result, error) {
clusterNames := helper.GetBindingClusterNames(binding.Spec.Clusters)
works, err := helper.FindOrphanWorks(c.Client, "", binding.Name, clusterNames, apiextensionsv1.ClusterScoped)
works, err := helper.FindOrphanWorks(c.client, "", binding.Name, clusterNames, apiextensionsv1.ClusterScoped)
if err != nil {
klog.Errorf("Failed to find orphan works by ClusterResourceBinding(%s). Error: %v.", binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFindOrphanWorks), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
err = helper.RemoveOrphanWorks(c.Client, works)
err = helper.RemoveOrphanWorks(c.client, works)
if err != nil {
klog.Errorf("Failed to remove orphan works by clusterResourceBinding(%s). Error: %v.", binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFindOrphanWorks), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for clusterResourceBinding(%s). Error: %v.", binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeFetchWorkload), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
err = ensureWork(c.Client, workload, c.OverrideManager, binding, apiextensionsv1.ClusterScoped)
err = ensureWork(c.client, workload, c.overrideManager, binding, apiextensionsv1.ClusterScoped)
if err != nil {
klog.Errorf("Failed to transform clusterResourceBinding(%s) to works. Error: %v.", binding.GetName(), err)
return controllerruntime.Result{Requeue: true}, err
}
err = helper.AggregateClusterResourceBindingWorkStatus(c.Client, binding, workload)
err = helper.AggregateClusterResourceBindingWorkStatus(c.client, binding, workload)
if err != nil {
klog.Errorf("Failed to aggregate workStatuses to clusterResourceBinding(%s). Error: %v.", binding.GetName(), err)
c.recorder.Event(binding, corev1.EventTypeWarning, fmt.Sprintf("Failed %s", eventTypeTransformResourceBinding), err.Error())
return controllerruntime.Result{Requeue: true}, err
}
klog.V(4).Infof("Update clusterResourceBinding(%s) with AggregatedStatus successfully.", binding.Name)
@ -164,14 +185,14 @@ func (c *ClusterResourceBindingController) newOverridePolicyFunc() handler.MapFu
}
bindingList := &workv1alpha2.ClusterResourceBindingList{}
if err := c.Client.List(context.TODO(), bindingList); err != nil {
if err := c.client.List(context.TODO(), bindingList); err != nil {
klog.Errorf("Failed to list clusterResourceBindings, error: %v", err)
return nil
}
var requests []reconcile.Request
for _, binding := range bindingList.Items {
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for clusterResourceBinding(%s). Error: %v.", binding.Name, err)
return nil
@ -193,14 +214,14 @@ func (c *ClusterResourceBindingController) newReplicaSchedulingPolicyFunc() hand
return func(a client.Object) []reconcile.Request {
rspResourceSelectors := a.(*policyv1alpha1.ReplicaSchedulingPolicy).Spec.ResourceSelectors
bindingList := &workv1alpha2.ClusterResourceBindingList{}
if err := c.Client.List(context.TODO(), bindingList); err != nil {
if err := c.client.List(context.TODO(), bindingList); err != nil {
klog.Errorf("Failed to list clusterResourceBindings, error: %v", err)
return nil
}
var requests []reconcile.Request
for _, binding := range bindingList.Items {
workload, err := helper.FetchWorkload(c.DynamicClient, c.RESTMapper, binding.Spec.Resource)
workload, err := helper.FetchWorkload(c.dynamicClient, c.restMapper, binding.Spec.Resource)
if err != nil {
klog.Errorf("Failed to fetch workload for clusterResourceBinding(%s). Error: %v.", binding.Name, err)
return nil