Deprecate name/namespace labels of work
Signed-off-by: whitewindmills <jayfantasyhjh@gmail.com>
This commit is contained in:
parent
8f9a624620
commit
8328054439
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2021 The Karmada Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package v1alpha1
|
|
||||||
|
|
||||||
const (
|
|
||||||
// WorkNamespaceLabel is added to objects to specify associated Work's namespace.
|
|
||||||
WorkNamespaceLabel = "work.karmada.io/namespace"
|
|
||||||
|
|
||||||
// WorkNameLabel is added to objects to specify associated Work's name.
|
|
||||||
WorkNameLabel = "work.karmada.io/name"
|
|
||||||
)
|
|
|
@ -58,12 +58,6 @@ const (
|
||||||
// - Manifest in Work object: describes the name of ClusterResourceBinding which the manifest derived from.
|
// - Manifest in Work object: describes the name of ClusterResourceBinding which the manifest derived from.
|
||||||
ClusterResourceBindingAnnotationKey = "clusterresourcebinding.karmada.io/name"
|
ClusterResourceBindingAnnotationKey = "clusterresourcebinding.karmada.io/name"
|
||||||
|
|
||||||
// WorkNamespaceLabel is added to objects to specify associated Work's namespace.
|
|
||||||
WorkNamespaceLabel = "work.karmada.io/namespace"
|
|
||||||
|
|
||||||
// WorkNameLabel is added to objects to specify associated Work's name.
|
|
||||||
WorkNameLabel = "work.karmada.io/name"
|
|
||||||
|
|
||||||
// BindingManagedByLabel is added to ResourceBinding to represent what kind of resource manages this Binding.
|
// BindingManagedByLabel is added to ResourceBinding to represent what kind of resource manages this Binding.
|
||||||
BindingManagedByLabel = "binding.karmada.io/managed-by"
|
BindingManagedByLabel = "binding.karmada.io/managed-by"
|
||||||
)
|
)
|
||||||
|
|
|
@ -110,7 +110,7 @@ func (c *Controller) Reconcile(ctx context.Context, req controllerruntime.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
if !util.IsClusterReady(&cluster.Status) {
|
if !util.IsClusterReady(&cluster.Status) {
|
||||||
klog.Errorf("Stop sync work(%s/%s) for cluster(%s) as cluster not ready.", work.Namespace, work.Name, cluster.Name)
|
klog.Errorf("Stop syncing the work(%s/%s) for the cluster(%s) as cluster not ready.", work.Namespace, work.Name, cluster.Name)
|
||||||
return controllerruntime.Result{}, fmt.Errorf("cluster(%s) not ready", cluster.Name)
|
return controllerruntime.Result{}, fmt.Errorf("cluster(%s) not ready", cluster.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,18 +133,18 @@ func (c *Controller) syncWork(clusterName string, work *workv1alpha1.Work) (cont
|
||||||
err := c.syncToClusters(clusterName, work)
|
err := c.syncToClusters(clusterName, work)
|
||||||
metrics.ObserveSyncWorkloadLatency(err, start)
|
metrics.ObserveSyncWorkloadLatency(err, start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Failed to sync work(%s) to cluster(%s): %v", work.Name, clusterName, err)
|
msg := fmt.Sprintf("Failed to sync work(%s/%s) to cluster(%s), err: %v", work.Namespace, work.Name, clusterName, err)
|
||||||
klog.Errorf(msg)
|
klog.Errorf(msg)
|
||||||
c.EventRecorder.Event(work, corev1.EventTypeWarning, events.EventReasonSyncWorkloadFailed, msg)
|
c.EventRecorder.Event(work, corev1.EventTypeWarning, events.EventReasonSyncWorkloadFailed, msg)
|
||||||
return controllerruntime.Result{}, err
|
return controllerruntime.Result{}, err
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("Sync work (%s) to cluster(%s) successful.", work.Name, clusterName)
|
msg := fmt.Sprintf("Sync work(%s/%s) to cluster(%s) successful.", work.Namespace, work.Name, clusterName)
|
||||||
klog.V(4).Infof(msg)
|
klog.V(4).Infof(msg)
|
||||||
c.EventRecorder.Event(work, corev1.EventTypeNormal, events.EventReasonSyncWorkloadSucceed, msg)
|
c.EventRecorder.Event(work, corev1.EventTypeNormal, events.EventReasonSyncWorkloadSucceed, msg)
|
||||||
return controllerruntime.Result{}, nil
|
return controllerruntime.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// tryDeleteWorkload tries to delete resource in the given member cluster.
|
// tryDeleteWorkload tries to delete resources in the given member cluster.
|
||||||
func (c *Controller) tryDeleteWorkload(clusterName string, work *workv1alpha1.Work) error {
|
func (c *Controller) tryDeleteWorkload(clusterName string, work *workv1alpha1.Work) error {
|
||||||
for _, manifest := range work.Spec.Workload.Manifests {
|
for _, manifest := range work.Spec.Workload.Manifests {
|
||||||
workload := &unstructured.Unstructured{}
|
workload := &unstructured.Unstructured{}
|
||||||
|
@ -174,6 +174,7 @@ func (c *Controller) tryDeleteWorkload(clusterName string, work *workv1alpha1.Wo
|
||||||
klog.Infof("Abort deleting the resource(kind=%s, %s/%s) exists in cluster %v but not managed by karmada", clusterObj.GetKind(), clusterObj.GetNamespace(), clusterObj.GetName(), clusterName)
|
klog.Infof("Abort deleting the resource(kind=%s, %s/%s) exists in cluster %v but not managed by karmada", clusterObj.GetKind(), clusterObj.GetNamespace(), clusterObj.GetName(), clusterName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
util.MergeLabel(workload, workv1alpha2.WorkPermanentIDLabel, util.GetLabelValue(work.Labels, workv1alpha2.WorkPermanentIDLabel))
|
||||||
|
|
||||||
err = c.ObjectWatcher.Delete(clusterName, workload)
|
err = c.ObjectWatcher.Delete(clusterName, workload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -207,7 +208,7 @@ func (c *Controller) syncToClusters(clusterName string, work *workv1alpha1.Work)
|
||||||
workload := &unstructured.Unstructured{}
|
workload := &unstructured.Unstructured{}
|
||||||
err := workload.UnmarshalJSON(manifest.Raw)
|
err := workload.UnmarshalJSON(manifest.Raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to unmarshal workload, error is: %v", err)
|
klog.Errorf("Failed to unmarshal workload of the work(%s/%s), error is: %v", work.GetNamespace(), work.GetName(), err)
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -253,12 +254,11 @@ func (c *Controller) tryCreateOrUpdateWorkload(clusterName string, workload *uns
|
||||||
clusterObj, err := helper.GetObjectFromCache(c.RESTMapper, c.InformerManager, fedKey)
|
clusterObj, err := helper.GetObjectFromCache(c.RESTMapper, c.InformerManager, fedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !apierrors.IsNotFound(err) {
|
if !apierrors.IsNotFound(err) {
|
||||||
klog.Errorf("Failed to get resource %v from member cluster, err is %v ", workload.GetName(), err)
|
klog.Errorf("Failed to get the resource(kind=%s, %s/%s) from member cluster(%s), err is %v ", workload.GetKind(), workload.GetNamespace(), workload.GetName(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = c.ObjectWatcher.Create(clusterName, workload)
|
err = c.ObjectWatcher.Create(clusterName, workload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to create resource(%v/%v) in the given member cluster %s, err is %v", workload.GetNamespace(), workload.GetName(), clusterName, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -266,13 +266,12 @@ func (c *Controller) tryCreateOrUpdateWorkload(clusterName string, workload *uns
|
||||||
|
|
||||||
err = c.ObjectWatcher.Update(clusterName, workload, clusterObj)
|
err = c.ObjectWatcher.Update(clusterName, workload, clusterObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to update resource in the given member cluster %s, err is %v", clusterName, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateAppliedCondition update the Applied condition for the given Work
|
// updateAppliedCondition updates the applied condition for the given Work.
|
||||||
func (c *Controller) updateAppliedCondition(work *workv1alpha1.Work, status metav1.ConditionStatus, reason, message string) error {
|
func (c *Controller) updateAppliedCondition(work *workv1alpha1.Work, status metav1.ConditionStatus, reason, message string) error {
|
||||||
newWorkAppliedCondition := metav1.Condition{
|
newWorkAppliedCondition := metav1.Condition{
|
||||||
Type: workv1alpha1.WorkApplied,
|
Type: workv1alpha1.WorkApplied,
|
||||||
|
@ -292,7 +291,7 @@ func (c *Controller) updateAppliedCondition(work *workv1alpha1.Work, status meta
|
||||||
if err = c.Get(context.TODO(), client.ObjectKey{Namespace: work.Namespace, Name: work.Name}, updated); err == nil {
|
if err = c.Get(context.TODO(), client.ObjectKey{Namespace: work.Namespace, Name: work.Name}, updated); err == nil {
|
||||||
work = updated
|
work = updated
|
||||||
} else {
|
} else {
|
||||||
klog.Errorf("Failed to get updated work %s/%s: %v", work.Namespace, work.Name, err)
|
klog.Errorf("Failed to get the updated work(%s/%s), err: %v", work.Namespace, work.Name, err)
|
||||||
}
|
}
|
||||||
return updateErr
|
return updateErr
|
||||||
})
|
})
|
||||||
|
@ -301,7 +300,7 @@ func (c *Controller) updateAppliedCondition(work *workv1alpha1.Work, status meta
|
||||||
func (c *Controller) eventf(object *unstructured.Unstructured, eventType, reason, messageFmt string, args ...interface{}) {
|
func (c *Controller) eventf(object *unstructured.Unstructured, eventType, reason, messageFmt string, args ...interface{}) {
|
||||||
ref, err := helper.GenEventRef(object)
|
ref, err := helper.GenEventRef(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("ignore event(%s) as failed to build event reference for: kind=%s, %s due to %v", reason, object.GetKind(), klog.KObj(object), err)
|
klog.Errorf("Ignore event(%s) as failed to build event reference for: kind=%s, %s due to %v", reason, object.GetKind(), klog.KObj(object), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.EventRecorder.Eventf(ref, eventType, reason, messageFmt, args...)
|
c.EventRecorder.Eventf(ref, eventType, reason, messageFmt, args...)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||||
|
@ -34,6 +35,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||||
|
|
||||||
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
||||||
|
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
"github.com/karmada-io/karmada/pkg/util/helper"
|
"github.com/karmada-io/karmada/pkg/util/helper"
|
||||||
"github.com/karmada-io/karmada/pkg/util/names"
|
"github.com/karmada-io/karmada/pkg/util/names"
|
||||||
|
@ -55,24 +57,34 @@ func (c *EndpointSliceController) Reconcile(ctx context.Context, req controllerr
|
||||||
work := &workv1alpha1.Work{}
|
work := &workv1alpha1.Work{}
|
||||||
if err := c.Client.Get(ctx, req.NamespacedName, work); err != nil {
|
if err := c.Client.Get(ctx, req.NamespacedName, work); err != nil {
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
// Cleanup derived EndpointSlices after work has been removed.
|
// Clean up derived EndpointSlices after work has been removed.
|
||||||
err = helper.DeleteEndpointSlice(c.Client, labels.Set{
|
endpointSlices := &discoveryv1.EndpointSliceList{}
|
||||||
workv1alpha1.WorkNamespaceLabel: req.Namespace,
|
if err = c.List(context.TODO(), endpointSlices, client.HasLabels{workv1alpha2.WorkPermanentIDLabel}); err != nil {
|
||||||
workv1alpha1.WorkNameLabel: req.Name,
|
return controllerruntime.Result{}, err
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
return controllerruntime.Result{}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
for i, es := range endpointSlices.Items {
|
||||||
|
if es.Annotations[workv1alpha2.WorkNamespaceAnnotation] == req.Namespace &&
|
||||||
|
es.Annotations[workv1alpha2.WorkNameAnnotation] == req.Name {
|
||||||
|
if err := c.Delete(context.TODO(), &endpointSlices.Items[i]); err != nil && !apierrors.IsNotFound(err) {
|
||||||
|
klog.Errorf("Failed to delete endpointslice(%s/%s) after the work(%s/%s) has been removed, err: %v",
|
||||||
|
es.Namespace, es.Name, req.Namespace, req.Name, err)
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return controllerruntime.Result{}, utilerrors.NewAggregate(errs)
|
||||||
}
|
}
|
||||||
return controllerruntime.Result{}, err
|
return controllerruntime.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !work.DeletionTimestamp.IsZero() {
|
if !work.DeletionTimestamp.IsZero() {
|
||||||
err := helper.DeleteEndpointSlice(c.Client, labels.Set{
|
// Clean up derived EndpointSlices when deleting the work.
|
||||||
workv1alpha1.WorkNamespaceLabel: req.Namespace,
|
if err := helper.DeleteEndpointSlice(c.Client, labels.Set{
|
||||||
workv1alpha1.WorkNameLabel: req.Name,
|
workv1alpha2.WorkPermanentIDLabel: work.Labels[workv1alpha2.WorkPermanentIDLabel],
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
klog.Errorf("Failed to delete endpointslice of the work(%s/%s) when deleting the work, err is %v", work.Namespace, work.Name, err)
|
||||||
return controllerruntime.Result{}, err
|
return controllerruntime.Result{}, err
|
||||||
}
|
}
|
||||||
return controllerruntime.Result{}, c.removeFinalizer(work.DeepCopy())
|
return controllerruntime.Result{}, c.removeFinalizer(work.DeepCopy())
|
||||||
|
@ -83,10 +95,10 @@ func (c *EndpointSliceController) Reconcile(ctx context.Context, req controllerr
|
||||||
// Once the conflict between service_export_controller.go and endpointslice_collect_controller.go is fixed, the following code should be deleted.
|
// Once the conflict between service_export_controller.go and endpointslice_collect_controller.go is fixed, the following code should be deleted.
|
||||||
if serviceName := util.GetLabelValue(work.Labels, util.ServiceNameLabel); serviceName == "" {
|
if serviceName := util.GetLabelValue(work.Labels, util.ServiceNameLabel); serviceName == "" {
|
||||||
err := helper.DeleteEndpointSlice(c.Client, labels.Set{
|
err := helper.DeleteEndpointSlice(c.Client, labels.Set{
|
||||||
workv1alpha1.WorkNamespaceLabel: req.Namespace,
|
workv1alpha2.WorkPermanentIDLabel: work.Labels[workv1alpha2.WorkPermanentIDLabel],
|
||||||
workv1alpha1.WorkNameLabel: req.Name,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
klog.Errorf("Failed to delete endpointslice of the work(%s/%s) when the serviceexport is deleted, err is %v", work.Namespace, work.Name, err)
|
||||||
return controllerruntime.Result{}, err
|
return controllerruntime.Result{}, err
|
||||||
}
|
}
|
||||||
return controllerruntime.Result{}, c.removeFinalizer(work.DeepCopy())
|
return controllerruntime.Result{}, c.removeFinalizer(work.DeepCopy())
|
||||||
|
@ -146,12 +158,11 @@ func (c *EndpointSliceController) collectEndpointSliceFromWork(work *workv1alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
desiredEndpointSlice := deriveEndpointSlice(endpointSlice, clusterName)
|
desiredEndpointSlice := deriveEndpointSlice(endpointSlice, clusterName)
|
||||||
desiredEndpointSlice.Labels = map[string]string{
|
desiredEndpointSlice.Labels = util.DedupeAndMergeLabels(desiredEndpointSlice.Labels, map[string]string{
|
||||||
workv1alpha1.WorkNamespaceLabel: work.Namespace,
|
workv1alpha2.WorkPermanentIDLabel: work.Labels[workv1alpha2.WorkPermanentIDLabel],
|
||||||
workv1alpha1.WorkNameLabel: work.Name,
|
|
||||||
discoveryv1.LabelServiceName: names.GenerateDerivedServiceName(work.Labels[util.ServiceNameLabel]),
|
discoveryv1.LabelServiceName: names.GenerateDerivedServiceName(work.Labels[util.ServiceNameLabel]),
|
||||||
util.ManagedByKarmadaLabel: util.ManagedByKarmadaLabelValue,
|
util.ManagedByKarmadaLabel: util.ManagedByKarmadaLabelValue,
|
||||||
}
|
})
|
||||||
|
|
||||||
if err = helper.CreateOrUpdateEndpointSlice(c.Client, desiredEndpointSlice); err != nil {
|
if err = helper.CreateOrUpdateEndpointSlice(c.Client, desiredEndpointSlice); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -112,7 +112,7 @@ func (c *WorkStatusController) Reconcile(ctx context.Context, req controllerrunt
|
||||||
}
|
}
|
||||||
|
|
||||||
if !util.IsClusterReady(&cluster.Status) {
|
if !util.IsClusterReady(&cluster.Status) {
|
||||||
klog.Errorf("Stop sync work(%s/%s) for cluster(%s) as cluster not ready.", work.Namespace, work.Name, cluster.Name)
|
klog.Errorf("Stop syncing the Work(%s/%s) to the cluster(%s) as not ready.", work.Namespace, work.Name, cluster.Name)
|
||||||
return controllerruntime.Result{}, fmt.Errorf("cluster(%s) not ready", cluster.Name)
|
return controllerruntime.Result{}, fmt.Errorf("cluster(%s) not ready", cluster.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ func generateKey(obj interface{}) (util.QueueKey, error) {
|
||||||
func getClusterNameFromAnnotation(resource *unstructured.Unstructured) (string, error) {
|
func getClusterNameFromAnnotation(resource *unstructured.Unstructured) (string, error) {
|
||||||
workNamespace, exist := resource.GetAnnotations()[workv1alpha2.WorkNamespaceAnnotation]
|
workNamespace, exist := resource.GetAnnotations()[workv1alpha2.WorkNamespaceAnnotation]
|
||||||
if !exist {
|
if !exist {
|
||||||
klog.V(4).Infof("Ignore resource(%s/%s/%s) which not managed by karmada", resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
klog.V(4).Infof("Ignore resource(kind=%s, %s/%s) which is not managed by Karmada.", resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,16 +196,17 @@ func (c *WorkStatusController) syncWorkStatus(key util.QueueKey) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
workNamespace, nsExist := observedObj.GetAnnotations()[workv1alpha2.WorkNamespaceAnnotation]
|
observedAnnotations := observedObj.GetAnnotations()
|
||||||
workName, nameExist := observedObj.GetAnnotations()[workv1alpha2.WorkNameAnnotation]
|
workNamespace, nsExist := observedAnnotations[workv1alpha2.WorkNamespaceAnnotation]
|
||||||
|
workName, nameExist := observedAnnotations[workv1alpha2.WorkNameAnnotation]
|
||||||
if !nsExist || !nameExist {
|
if !nsExist || !nameExist {
|
||||||
klog.Infof("Ignore object(%s) which not managed by karmada.", fedKey.String())
|
klog.Infof("Ignore object(%s) which not managed by Karmada.", fedKey.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
workObject := &workv1alpha1.Work{}
|
workObject := &workv1alpha1.Work{}
|
||||||
if err := c.Client.Get(context.TODO(), client.ObjectKey{Namespace: workNamespace, Name: workName}, workObject); err != nil {
|
if err := c.Client.Get(context.TODO(), client.ObjectKey{Namespace: workNamespace, Name: workName}, workObject); err != nil {
|
||||||
// Stop processing if resource no longer exist.
|
// Stop processing if the resource no longer exists.
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -214,7 +215,7 @@ func (c *WorkStatusController) syncWorkStatus(key util.QueueKey) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop update status if Work object in terminating state.
|
// stop updating status if Work object in terminating state.
|
||||||
if !workObject.DeletionTimestamp.IsZero() {
|
if !workObject.DeletionTimestamp.IsZero() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -230,6 +231,7 @@ func (c *WorkStatusController) syncWorkStatus(key util.QueueKey) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util.MergeLabel(desiredObj, workv1alpha2.WorkPermanentIDLabel, util.GetLabelValue(workObject.Labels, workv1alpha2.WorkPermanentIDLabel))
|
||||||
// we should check if the observed status is consistent with the declaration to prevent accidental changes made
|
// we should check if the observed status is consistent with the declaration to prevent accidental changes made
|
||||||
// in member clusters.
|
// in member clusters.
|
||||||
needUpdate, err := c.ObjectWatcher.NeedsUpdate(clusterName, desiredObj, observedObj)
|
needUpdate, err := c.ObjectWatcher.NeedsUpdate(clusterName, desiredObj, observedObj)
|
||||||
|
@ -239,7 +241,7 @@ func (c *WorkStatusController) syncWorkStatus(key util.QueueKey) error {
|
||||||
|
|
||||||
if needUpdate {
|
if needUpdate {
|
||||||
if err := c.ObjectWatcher.Update(clusterName, desiredObj, observedObj); err != nil {
|
if err := c.ObjectWatcher.Update(clusterName, desiredObj, observedObj); err != nil {
|
||||||
klog.Errorf("Update %s failed: %v", fedKey.String(), err)
|
klog.Errorf("Updating %s failed: %v", fedKey.String(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// We can't return even after a success updates, because that might lose the chance to collect status.
|
// We can't return even after a success updates, because that might lose the chance to collect status.
|
||||||
|
@ -251,7 +253,7 @@ func (c *WorkStatusController) syncWorkStatus(key util.QueueKey) error {
|
||||||
// status changes.
|
// status changes.
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Infof("reflecting %s(%s/%s) status to Work(%s/%s)", observedObj.GetKind(), observedObj.GetNamespace(), observedObj.GetName(), workNamespace, workName)
|
klog.Infof("Reflecting the resource(kind=%s, %s/%s) status to the Work(%s/%s).", observedObj.GetKind(), observedObj.GetNamespace(), observedObj.GetName(), workNamespace, workName)
|
||||||
return c.reflectStatus(workObject, observedObj)
|
return c.reflectStatus(workObject, observedObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +303,7 @@ func (c *WorkStatusController) recreateResourceIfNeeded(work *workv1alpha1.Work,
|
||||||
if reflect.DeepEqual(desiredGVK, workloadKey.GroupVersionKind()) &&
|
if reflect.DeepEqual(desiredGVK, workloadKey.GroupVersionKind()) &&
|
||||||
manifest.GetNamespace() == workloadKey.Namespace &&
|
manifest.GetNamespace() == workloadKey.Namespace &&
|
||||||
manifest.GetName() == workloadKey.Name {
|
manifest.GetName() == workloadKey.Name {
|
||||||
klog.Infof("recreating %s", workloadKey.String())
|
klog.Infof("Recreating resource(%s).", workloadKey.String())
|
||||||
err := c.ObjectWatcher.Create(workloadKey.Cluster, manifest)
|
err := c.ObjectWatcher.Create(workloadKey.Cluster, manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.eventf(manifest, corev1.EventTypeWarning, events.EventReasonSyncWorkloadFailed, "Failed to create or update resource(%s/%s) in member cluster(%s): %v", manifest.GetNamespace(), manifest.GetName(), workloadKey.Cluster, err)
|
c.eventf(manifest, corev1.EventTypeWarning, events.EventReasonSyncWorkloadFailed, "Failed to create or update resource(%s/%s) in member cluster(%s): %v", manifest.GetNamespace(), manifest.GetName(), workloadKey.Cluster, err)
|
||||||
|
@ -550,7 +552,7 @@ func (c *WorkStatusController) SetupWithManager(mgr controllerruntime.Manager) e
|
||||||
func (c *WorkStatusController) eventf(object *unstructured.Unstructured, eventType, reason, messageFmt string, args ...interface{}) {
|
func (c *WorkStatusController) eventf(object *unstructured.Unstructured, eventType, reason, messageFmt string, args ...interface{}) {
|
||||||
ref, err := helper.GenEventRef(object)
|
ref, err := helper.GenEventRef(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("ignore event(%s) as failed to build event reference for: kind=%s, %s due to %v", reason, object.GetKind(), klog.KObj(object), err)
|
klog.Errorf("Ignore event(%s) as failing to build event reference for: kind=%s, %s due to %v", reason, object.GetKind(), klog.KObj(object), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.EventRecorder.Eventf(ref, eventType, reason, messageFmt, args...)
|
c.EventRecorder.Eventf(ref, eventType, reason, messageFmt, args...)
|
||||||
|
|
|
@ -408,7 +408,7 @@ func TestGenerateKey(t *testing.T) {
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"namespace": "default",
|
"namespace": "default",
|
||||||
"labels": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"test": "karmada-es-cluster",
|
"test": "karmada-es-cluster",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -471,7 +471,7 @@ func TestGetClusterNameFromAnnotation(t *testing.T) {
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"namespace": "default",
|
"namespace": "default",
|
||||||
"labels": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"foo": "karmada-es-cluster",
|
"foo": "karmada-es-cluster",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,7 +41,6 @@ import (
|
||||||
|
|
||||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||||
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
|
||||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/get"
|
"github.com/karmada-io/karmada/pkg/karmadactl/get"
|
||||||
|
@ -317,8 +316,7 @@ func (o *CommandPromoteOption) revertPromotedDeps(memberClusterFactory cmdutil.F
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// remove the karmada label of dependency resource in member cluster to avoid deleting it when deleting the resource in control plane
|
// remove the karmada label of dependency resource in member cluster to avoid deleting it when deleting the resource in control plane
|
||||||
u.RemoveLabels(depObj, workv1alpha1.WorkNamespaceLabel)
|
u.RemoveLabels(depObj, workv1alpha2.WorkPermanentIDLabel, u.ManagedByKarmadaLabel)
|
||||||
u.RemoveLabels(depObj, workv1alpha1.WorkNameLabel)
|
|
||||||
if len(depObj.GetNamespace()) != 0 {
|
if len(depObj.GetNamespace()) != 0 {
|
||||||
// update the dependency resource in member cluster
|
// update the dependency resource in member cluster
|
||||||
_, err := memberDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Update(context.Background(), depObj, metav1.UpdateOptions{})
|
_, err := memberDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Update(context.Background(), depObj, metav1.UpdateOptions{})
|
||||||
|
@ -707,7 +705,7 @@ func (o *CommandPromoteOption) createClusterPropagationPolicy(karmadaClient *kar
|
||||||
// preprocessResource delete redundant fields to convert resource as template
|
// preprocessResource delete redundant fields to convert resource as template
|
||||||
func preprocessResource(obj *unstructured.Unstructured) error {
|
func preprocessResource(obj *unstructured.Unstructured) error {
|
||||||
// remove fields that generated by kube-apiserver and no need(or can't) propagate to member clusters.
|
// remove fields that generated by kube-apiserver and no need(or can't) propagate to member clusters.
|
||||||
if err := prune.RemoveIrrelevantField(obj); err != nil {
|
if err := prune.RemoveIrrelevantFields(obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ var kindIrrelevantFieldPruners = map[string]irrelevantFieldPruneFunc{
|
||||||
util.ServiceKind: removeServiceIrrelevantField,
|
util.ServiceKind: removeServiceIrrelevantField,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveIrrelevantField used to remove fields that generated by kube-apiserver and no need(or can't) propagate to
|
// RemoveIrrelevantFields used to remove fields that generated by kube-apiserver and no need(or can't) propagate to
|
||||||
// member clusters.
|
// member clusters.
|
||||||
func RemoveIrrelevantField(workload *unstructured.Unstructured, extraHooks ...func(*unstructured.Unstructured)) error {
|
func RemoveIrrelevantFields(workload *unstructured.Unstructured, extraHooks ...func(*unstructured.Unstructured)) error {
|
||||||
// populated by the kubernetes.
|
// populated by the kubernetes.
|
||||||
unstructured.RemoveNestedField(workload.Object, "metadata", "creationTimestamp")
|
unstructured.RemoveNestedField(workload.Object, "metadata", "creationTimestamp")
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ func TestRemoveIrrelevantField(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if err := RemoveIrrelevantField(tt.workload, tt.extraHooks...); err != nil {
|
if err := RemoveIrrelevantFields(tt.workload, tt.extraHooks...); err != nil {
|
||||||
t.Fatalf("RemoveIrrelevantField() expects no error but got: %v", err)
|
t.Fatalf("RemoveIrrelevantField() expects no error but got: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewObjectWatcher(kubeClientSet client.Client, restMapper meta.RESTMapper, c
|
||||||
func (o *objectWatcherImpl) Create(clusterName string, desireObj *unstructured.Unstructured) error {
|
func (o *objectWatcherImpl) Create(clusterName string, desireObj *unstructured.Unstructured) error {
|
||||||
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to build dynamic cluster client for cluster %s.", clusterName)
|
klog.Errorf("Failed to build dynamic cluster client for cluster %s, err: %v.", clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,23 +87,23 @@ func (o *objectWatcherImpl) Create(clusterName string, desireObj *unstructured.U
|
||||||
|
|
||||||
fedKey, err := keys.FederatedKeyFunc(clusterName, desireObj)
|
fedKey, err := keys.FederatedKeyFunc(clusterName, desireObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to get FederatedKey %s, error: %v", desireObj.GetName(), err)
|
klog.Errorf("Failed to get FederatedKey %s, error: %v.", desireObj.GetName(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = helper.GetObjectFromCache(o.RESTMapper, o.InformerManager, fedKey)
|
_, err = helper.GetObjectFromCache(o.RESTMapper, o.InformerManager, fedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !apierrors.IsNotFound(err) {
|
if !apierrors.IsNotFound(err) {
|
||||||
klog.Errorf("Failed to get resource %v from member cluster, err is %v ", desireObj.GetName(), err)
|
klog.Errorf("Failed to get resource(kind=%s, %s/%s) from member cluster, err is %v.", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterObj, err := dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Create(context.TODO(), desireObj, metav1.CreateOptions{})
|
clusterObj, err := dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Create(context.TODO(), desireObj, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to create resource(kind=%s, %s/%s) in cluster %s, err is %v ", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
klog.Errorf("Failed to create resource(kind=%s, %s/%s) in cluster %s, err is %v.", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Infof("Created resource(kind=%s, %s/%s) on cluster: %s", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
klog.Infof("Created the resource(kind=%s, %s/%s) on cluster(%s).", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
||||||
// record version
|
// record version
|
||||||
o.recordVersion(clusterObj, dynamicClusterClient.ClusterName)
|
o.recordVersion(clusterObj, dynamicClusterClient.ClusterName)
|
||||||
}
|
}
|
||||||
|
@ -142,20 +142,19 @@ func (o *objectWatcherImpl) Update(clusterName string, desireObj, clusterObj *un
|
||||||
updateAllowed := o.allowUpdate(clusterName, desireObj, clusterObj)
|
updateAllowed := o.allowUpdate(clusterName, desireObj, clusterObj)
|
||||||
if !updateAllowed {
|
if !updateAllowed {
|
||||||
// The existing resource is not managed by Karmada, and no conflict resolution found, avoid updating the existing resource by default.
|
// The existing resource is not managed by Karmada, and no conflict resolution found, avoid updating the existing resource by default.
|
||||||
return fmt.Errorf("resource(kind=%s, %s/%s) already exist in cluster %v and the %s strategy value is empty, karmada will not manage this resource",
|
return fmt.Errorf("resource(kind=%s, %s/%s) already exists in the cluster %v and the %s strategy value is empty, Karmada will not manage this resource",
|
||||||
desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, workv1alpha2.ResourceConflictResolutionAnnotation,
|
desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, workv1alpha2.ResourceConflictResolutionAnnotation)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to build dynamic cluster client for cluster %s.", clusterName)
|
klog.Errorf("Failed to build dynamic cluster client for cluster %s, err: %v.", clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr, err := restmapper.GetGroupVersionResource(o.RESTMapper, desireObj.GroupVersionKind())
|
gvr, err := restmapper.GetGroupVersionResource(o.RESTMapper, desireObj.GroupVersionKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to update resource(kind=%s, %s/%s) in cluster %s as mapping GVK to GVR failed: %v", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
klog.Errorf("Failed to update the resource(kind=%s, %s/%s) in the cluster %s as mapping GVK to GVR failed: %v", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,11 +166,11 @@ func (o *objectWatcherImpl) Update(clusterName string, desireObj, clusterObj *un
|
||||||
|
|
||||||
resource, err := dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Update(context.TODO(), desireObj, metav1.UpdateOptions{})
|
resource, err := dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Update(context.TODO(), desireObj, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to update resource(kind=%s, %s/%s) in cluster %s, err is %v ", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
klog.Errorf("Failed to update resource(kind=%s, %s/%s) in cluster %s, err: %v.", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Infof("Updated resource(kind=%s, %s/%s) on cluster: %s", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
klog.Infof("Updated the resource(kind=%s, %s/%s) on cluster(%s).", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
||||||
|
|
||||||
// record version
|
// record version
|
||||||
o.recordVersion(resource, clusterName)
|
o.recordVersion(resource, clusterName)
|
||||||
|
@ -181,13 +180,13 @@ func (o *objectWatcherImpl) Update(clusterName string, desireObj, clusterObj *un
|
||||||
func (o *objectWatcherImpl) Delete(clusterName string, desireObj *unstructured.Unstructured) error {
|
func (o *objectWatcherImpl) Delete(clusterName string, desireObj *unstructured.Unstructured) error {
|
||||||
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
dynamicClusterClient, err := o.ClusterClientSetFunc(clusterName, o.KubeClientSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to build dynamic cluster client for cluster %s.", clusterName)
|
klog.Errorf("Failed to build dynamic cluster client for cluster %s, err: %v.", clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr, err := restmapper.GetGroupVersionResource(o.RESTMapper, desireObj.GroupVersionKind())
|
gvr, err := restmapper.GetGroupVersionResource(o.RESTMapper, desireObj.GroupVersionKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to delete resource(kind=%s, %s/%s) in cluster %s as mapping GVK to GVR failed: %v", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
klog.Errorf("Failed to delete the resource(kind=%s, %s/%s) in the cluster %s as mapping GVK to GVR failed: %v", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,10 +202,10 @@ func (o *objectWatcherImpl) Delete(clusterName string, desireObj *unstructured.U
|
||||||
|
|
||||||
err = dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Delete(context.TODO(), desireObj.GetName(), deleteOption)
|
err = dynamicClusterClient.DynamicClientSet.Resource(gvr).Namespace(desireObj.GetNamespace()).Delete(context.TODO(), desireObj.GetName(), deleteOption)
|
||||||
if err != nil && !apierrors.IsNotFound(err) {
|
if err != nil && !apierrors.IsNotFound(err) {
|
||||||
klog.Errorf("Failed to delete resource %v in cluster %s, err is %v ", desireObj.GetName(), clusterName, err)
|
klog.Errorf("Failed to delete the resource(kind=%s, %s/%s) in the cluster %s, err: %v.", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
klog.Infof("Deleted resource(kind=%s, %s/%s) on cluster: %s", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
klog.Infof("Deleted the resource(kind=%s, %s/%s) on cluster(%s).", desireObj.GetKind(), desireObj.GetNamespace(), desireObj.GetName(), clusterName)
|
||||||
|
|
||||||
objectKey := o.genObjectKey(desireObj)
|
objectKey := o.genObjectKey(desireObj)
|
||||||
o.deleteVersionRecord(dynamicClusterClient.ClusterName, objectKey)
|
o.deleteVersionRecord(dynamicClusterClient.ClusterName, objectKey)
|
||||||
|
@ -273,28 +272,32 @@ func (o *objectWatcherImpl) NeedsUpdate(clusterName string, desiredObj, clusterO
|
||||||
// get resource version
|
// get resource version
|
||||||
version, exist := o.getVersionRecord(clusterName, desiredObj.GroupVersionKind().String()+"/"+desiredObj.GetNamespace()+"/"+desiredObj.GetName())
|
version, exist := o.getVersionRecord(clusterName, desiredObj.GroupVersionKind().String()+"/"+desiredObj.GetNamespace()+"/"+desiredObj.GetName())
|
||||||
if !exist {
|
if !exist {
|
||||||
klog.Errorf("Failed to update resource(kind=%s, %s/%s) in cluster %s for the version record does not exist", desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName)
|
klog.Errorf("Failed to update the resource(kind=%s, %s/%s) in the cluster %s because the version record does not exist.", desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName)
|
||||||
return false, fmt.Errorf("failed to update resource(kind=%s, %s/%s) in cluster %s for the version record does not exist", desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName)
|
return false, fmt.Errorf("failed to update resource(kind=%s, %s/%s) in cluster %s for the version record does not exist", desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lifted.ObjectNeedsUpdate(desiredObj, clusterObj, version), nil
|
return lifted.ObjectNeedsUpdate(desiredObj, clusterObj, version), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *objectWatcherImpl) isManagedResource(clusterObj *unstructured.Unstructured) bool {
|
||||||
|
return util.GetLabelValue(clusterObj.GetLabels(), util.ManagedByKarmadaLabel) == util.ManagedByKarmadaLabelValue
|
||||||
|
}
|
||||||
|
|
||||||
func (o *objectWatcherImpl) allowUpdate(clusterName string, desiredObj, clusterObj *unstructured.Unstructured) bool {
|
func (o *objectWatcherImpl) allowUpdate(clusterName string, desiredObj, clusterObj *unstructured.Unstructured) bool {
|
||||||
// If the existing resource is managed by Karmada, then the updating is allowed.
|
// If the existing resource is managed by Karmada, then the updating is allowed.
|
||||||
if util.GetLabelValue(clusterObj.GetLabels(), util.ManagedByKarmadaLabel) == util.ManagedByKarmadaLabelValue {
|
if o.isManagedResource(clusterObj) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
klog.Warningf("The existing resource(kind=%s, %s/%s) in the cluster(%s) is not managed by Karmada.",
|
||||||
|
clusterObj.GetKind(), clusterObj.GetNamespace(), clusterObj.GetName(), clusterName)
|
||||||
|
|
||||||
// This happens when promoting workload to the Karmada control plane
|
// This happens when promoting workload to the Karmada control plane.
|
||||||
conflictResolution := util.GetAnnotationValue(desiredObj.GetAnnotations(), workv1alpha2.ResourceConflictResolutionAnnotation)
|
conflictResolution := util.GetAnnotationValue(desiredObj.GetAnnotations(), workv1alpha2.ResourceConflictResolutionAnnotation)
|
||||||
if conflictResolution == workv1alpha2.ResourceConflictResolutionOverwrite {
|
if conflictResolution == workv1alpha2.ResourceConflictResolutionOverwrite {
|
||||||
|
klog.Infof("Force overwriting of the resource(kind=%s, %s/%s) in the cluster(%s).",
|
||||||
|
desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// The existing resource is not managed by Karmada, and no conflict resolution found, avoid updating the existing resource by default.
|
|
||||||
klog.Warningf("resource(kind=%s, %s/%s) already exist in cluster %v and the %s strategy value is empty, karmada will not manage this resource",
|
|
||||||
desiredObj.GetKind(), desiredObj.GetNamespace(), desiredObj.GetName(), clusterName, workv1alpha2.ResourceConflictResolutionAnnotation,
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (a *MutatingAdmission) Handle(_ context.Context, req admission.Request) adm
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admission.Errored(http.StatusBadRequest, err)
|
return admission.Errored(http.StatusBadRequest, err)
|
||||||
}
|
}
|
||||||
klog.V(2).Infof("Mutating work(%s) for request: %s", work.Name, req.Operation)
|
klog.V(2).Infof("Mutating the work(%s/%s) for request: %s", work.Namespace, work.Name, req.Operation)
|
||||||
|
|
||||||
var manifests []workv1alpha1.Manifest
|
var manifests []workv1alpha1.Manifest
|
||||||
|
|
||||||
|
@ -54,19 +54,19 @@ func (a *MutatingAdmission) Handle(_ context.Context, req admission.Request) adm
|
||||||
workloadObj := &unstructured.Unstructured{}
|
workloadObj := &unstructured.Unstructured{}
|
||||||
err := json.Unmarshal(manifest.Raw, workloadObj)
|
err := json.Unmarshal(manifest.Raw, workloadObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to unmarshal work(%s) manifest to Unstructured", work.Name)
|
klog.Errorf("Failed to unmarshal the work(%s/%s) manifest to Unstructured, err: %v", work.Namespace, work.Name, err)
|
||||||
return admission.Errored(http.StatusInternalServerError, err)
|
return admission.Errored(http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = prune.RemoveIrrelevantField(workloadObj, prune.RemoveJobTTLSeconds)
|
err = prune.RemoveIrrelevantFields(workloadObj, prune.RemoveJobTTLSeconds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to remove irrelevant field for work(%s): %v", work.Name, err)
|
klog.Errorf("Failed to remove irrelevant fields for the work(%s/%s), err: %v", work.Namespace, work.Name, err)
|
||||||
return admission.Errored(http.StatusInternalServerError, err)
|
return admission.Errored(http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workloadJSON, err := workloadObj.MarshalJSON()
|
workloadJSON, err := workloadObj.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to marshal workload of work(%s)", work.Name)
|
klog.Errorf("Failed to marshal workload of the work(%s/%s), err: %s", work.Namespace, work.Name, err)
|
||||||
return admission.Errored(http.StatusInternalServerError, err)
|
return admission.Errored(http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
manifests = append(manifests, workv1alpha1.Manifest{RawExtension: runtime.RawExtension{Raw: workloadJSON}})
|
manifests = append(manifests, workv1alpha1.Manifest{RawExtension: runtime.RawExtension{Raw: workloadJSON}})
|
||||||
|
|
Loading…
Reference in New Issue