Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add resource id label #4199

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/kr/pretty v0.3.1
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
github.com/olekukonko/tablewriter v0.0.5
Expand Down Expand Up @@ -100,7 +101,6 @@ require (
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
Expand Down
14 changes: 14 additions & 0 deletions pkg/apis/policy/v1alpha1/well_known_constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
package v1alpha1

const (
// PropagationPolicyPermanentIDLabel is the identifier of a PropagationPolicy object.
// Karmada generates a unique identifier, such as metadata.UUID, for each PropagationPolicy object.
// This identifier will be used as a label selector to locate corresponding resources, such as ResourceBinding.
// The reason for generating a new unique identifier instead of simply using metadata.UUID is because:
// In backup scenarios, when applying the backup resource manifest in a new cluster, the UUID may change.
PropagationPolicyPermanentIDLabel = "propagationpolicy.karmada.io/permanent-id"

// ClusterPropagationPolicyPermanentIDLabel is the identifier of a ClusterPropagationPolicy object.
// Karmada generates a unique identifier, such as metadata.UUID, for each ClusterPropagationPolicy object.
// This identifier will be used as a label selector to locate corresponding resources, such as ResourceBinding.
// The reason for generating a new unique identifier instead of simply using metadata.UUID is because:
// In backup scenarios, when applying the backup resource manifest in a new cluster, the UUID may change.
ClusterPropagationPolicyPermanentIDLabel = "clusterpropagationpolicy.karmada.io/permanent-id"

// PropagationPolicyUIDLabel is the uid of PropagationPolicy object.
PropagationPolicyUIDLabel = "propagationpolicy.karmada.io/uid"

Expand Down
17 changes: 17 additions & 0 deletions pkg/apis/work/v1alpha2/well_known_constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
package v1alpha2

const (
// ResourceBindingPermanentIDLabel is the identifier of a ResourceBinding object.
// Karmada generates a unique identifier, such as metadata.UUID, for each ResourceBinding object.
// This identifier will be used as a label selector to locate corresponding resources, such as Work.
// The reason for generating a new unique identifier instead of simply using metadata.UUID is because:
// In backup scenarios, when applying the backup resource manifest in a new cluster, the UUID may change.
ResourceBindingPermanentIDLabel = "resourcebinding.karmada.io/permanent-id"

// ClusterResourceBindingPermanentIDLabel is the identifier of a ClusterResourceBinding object.
// Karmada generates a unique identifier, such as metadata.UUID, for each ClusterResourceBinding object.
// This identifier will be used as a label selector to locate corresponding resources, such as Work.
// The reason for generating a new unique identifier instead of simply using metadata.UUID is because:
// In backup scenarios, when applying the backup resource manifest in a new cluster, the UUID may change.
ClusterResourceBindingPermanentIDLabel = "clusterresourcebinding.karmada.io/permanent-id"

// WorkPermanentIDLabel is the ID of Work object.
WorkPermanentIDLabel = "work.karmada.io/permanent-id"

// ResourceBindingUIDLabel is the UID of ResourceBinding object.
ResourceBindingUIDLabel = "resourcebinding.karmada.io/uid"

Expand Down
16 changes: 12 additions & 4 deletions pkg/controllers/binding/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,23 @@ func mergeLabel(workload *unstructured.Unstructured, workNamespace string, bindi
util.MergeLabel(workload, workv1alpha1.WorkNameLabel, names.GenerateWorkName(workload.GetKind(), workload.GetName(), workload.GetNamespace()))
util.MergeLabel(workload, util.ManagedByKarmadaLabel, util.ManagedByKarmadaLabelValue)
if scope == apiextensionsv1.NamespaceScoped {
util.RemoveLabels(workload, workv1alpha2.ResourceBindingUIDLabel)

bindingID := util.GetLabelValue(binding.GetLabels(), workv1alpha2.ResourceBindingPermanentIDLabel)
util.MergeLabel(workload, workv1alpha2.ResourceBindingReferenceKey, names.GenerateBindingReferenceKey(binding.GetNamespace(), binding.GetName()))
util.MergeLabel(workload, workv1alpha2.ResourceBindingUIDLabel, string(binding.GetUID()))
util.MergeLabel(workload, workv1alpha2.ResourceBindingPermanentIDLabel, bindingID)

workLabel[workv1alpha2.ResourceBindingReferenceKey] = names.GenerateBindingReferenceKey(binding.GetNamespace(), binding.GetName())
workLabel[workv1alpha2.ResourceBindingUIDLabel] = string(binding.GetUID())
workLabel[workv1alpha2.ResourceBindingPermanentIDLabel] = bindingID
} else {
util.RemoveLabels(workload, workv1alpha2.ClusterResourceBindingUIDLabel)

bindingID := util.GetLabelValue(binding.GetLabels(), workv1alpha2.ClusterResourceBindingPermanentIDLabel)
util.MergeLabel(workload, workv1alpha2.ClusterResourceBindingReferenceKey, names.GenerateBindingReferenceKey("", binding.GetName()))
util.MergeLabel(workload, workv1alpha2.ClusterResourceBindingUIDLabel, string(binding.GetUID()))
util.MergeLabel(workload, workv1alpha2.ClusterResourceBindingPermanentIDLabel, bindingID)

workLabel[workv1alpha2.ClusterResourceBindingReferenceKey] = names.GenerateBindingReferenceKey("", binding.GetName())
workLabel[workv1alpha2.ClusterResourceBindingUIDLabel] = string(binding.GetUID())
workLabel[workv1alpha2.ClusterResourceBindingPermanentIDLabel] = bindingID
}
return workLabel
}
Expand Down
19 changes: 11 additions & 8 deletions pkg/controllers/binding/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"

policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
Expand Down Expand Up @@ -88,7 +87,7 @@ func Test_mergeTargetClusters(t *testing.T) {
func Test_mergeLabel(t *testing.T) {
namespace := "fake-ns"
bindingName := "fake-bindingName"
rbUID := "93162d3c-ee8e-4995-9034-05f4d5d2c2b9"
rbID := "93162d3c-ee8e-4995-9034-05f4d5d2c2b9"

tests := []struct {
name string
Expand All @@ -115,13 +114,15 @@ func Test_mergeLabel(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: bindingName,
Namespace: namespace,
UID: types.UID(rbUID),
Labels: map[string]string{
workv1alpha2.ResourceBindingPermanentIDLabel: rbID,
},
},
},
scope: v1.NamespaceScoped,
want: map[string]string{
workv1alpha2.ResourceBindingUIDLabel: rbUID,
workv1alpha2.ResourceBindingReferenceKey: names.GenerateBindingReferenceKey(namespace, bindingName),
workv1alpha2.ResourceBindingPermanentIDLabel: rbID,
workv1alpha2.ResourceBindingReferenceKey: names.GenerateBindingReferenceKey(namespace, bindingName),
},
},
{
Expand All @@ -138,13 +139,15 @@ func Test_mergeLabel(t *testing.T) {
binding: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: bindingName,
UID: types.UID(rbUID),
Labels: map[string]string{
workv1alpha2.ClusterResourceBindingPermanentIDLabel: rbID,
},
},
},
scope: v1.ClusterScoped,
want: map[string]string{
workv1alpha2.ClusterResourceBindingUIDLabel: rbUID,
workv1alpha2.ClusterResourceBindingReferenceKey: names.GenerateBindingReferenceKey("", bindingName),
workv1alpha2.ClusterResourceBindingPermanentIDLabel: rbID,
workv1alpha2.ClusterResourceBindingReferenceKey: names.GenerateBindingReferenceKey("", bindingName),
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/execution/execution_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,12 @@ func (c *Controller) syncToClusters(clusterName string, work *workv1alpha1.Work)
for _, manifest := range work.Spec.Workload.Manifests {
workload := &unstructured.Unstructured{}
err := workload.UnmarshalJSON(manifest.Raw)
util.MergeLabel(workload, workv1alpha2.WorkUIDLabel, string(work.UID))
if err != nil {
klog.Errorf("Failed to unmarshal workload, error is: %v", err)
errs = append(errs, err)
continue
}
util.MergeLabel(workload, workv1alpha2.WorkPermanentIDLabel, util.GetLabelValue(work.Labels, workv1alpha2.WorkPermanentIDLabel))

if err = c.tryCreateOrUpdateWorkload(clusterName, workload); err != nil {
klog.Errorf("Failed to create or update resource(%v/%v) in the given member cluster %s, err is %v", workload.GetNamespace(), workload.GetName(), clusterName, err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (r *HPAReplicasSyncer) Generic(e event.GenericEvent) bool {
}

func hasBeenPropagated(hpa *autoscalingv2.HorizontalPodAutoscaler) bool {
_, ppExist := hpa.GetLabels()[policyv1alpha1.PropagationPolicyUIDLabel]
_, cppExist := hpa.GetLabels()[policyv1alpha1.ClusterPropagationPolicyUIDLabel]
_, ppExist := hpa.GetLabels()[policyv1alpha1.PropagationPolicyNameLabel]
_, cppExist := hpa.GetLabels()[policyv1alpha1.ClusterPropagationPolicyLabel]
return ppExist || cppExist
}
36 changes: 24 additions & 12 deletions pkg/dependenciesdistributor/dependencies_distributor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"

"github.com/google/uuid"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -45,6 +46,9 @@ import (
)

const (
// bindingDependedIdLabelKey is the resoruce id of the independent binding which the attached binding depends on.
bindingDependedIdLabelKey = "resourcebinding.karmada.io/depended-id"

// bindingDependedByLabelKeyPrefix is the prefix to a label key specifying an attached binding referred by which independent binding.
// the key is in the label of an attached binding which should be unique, because resource like secret can be referred by multiple deployments.
bindingDependedByLabelKeyPrefix = "resourcebinding.karmada.io/depended-by-"
Expand Down Expand Up @@ -498,19 +502,14 @@ func (d *DependenciesDistributor) removeScheduleResultFromAttachedBindings(bindi
}

func (d *DependenciesDistributor) createOrUpdateAttachedBinding(attachedBinding *workv1alpha2.ResourceBinding) error {
if err := d.Client.Create(context.TODO(), attachedBinding); err != nil {
if !apierrors.IsAlreadyExists(err) {
klog.Infof("Failed to create resource binding(%s/%s): %v", attachedBinding.Namespace, attachedBinding.Name, err)
return err
existBinding := &workv1alpha2.ResourceBinding{}
key := client.ObjectKeyFromObject(attachedBinding)
err := d.Client.Get(context.TODO(), key, existBinding)
if err == nil {
if util.GetLabelValue(existBinding.Labels, workv1alpha2.ResourceBindingPermanentIDLabel) == "" {
existBinding.Labels = util.DedupeAndMergeLabels(existBinding.Labels,
map[string]string{workv1alpha2.ResourceBindingPermanentIDLabel: uuid.New().String()})
}

existBinding := &workv1alpha2.ResourceBinding{}
key := client.ObjectKeyFromObject(attachedBinding)
if err := d.Client.Get(context.TODO(), key, existBinding); err != nil {
klog.Infof("Failed to get resource binding(%s/%s): %v", attachedBinding.Namespace, attachedBinding.Name, err)
return err
}

existBinding.Spec.RequiredBy = mergeBindingSnapshot(existBinding.Spec.RequiredBy, attachedBinding.Spec.RequiredBy)
existBinding.Labels = util.DedupeAndMergeLabels(existBinding.Labels, attachedBinding.Labels)
existBinding.Spec.Resource = attachedBinding.Spec.Resource
Expand All @@ -520,6 +519,17 @@ func (d *DependenciesDistributor) createOrUpdateAttachedBinding(attachedBinding
return err
}
}

if !apierrors.IsNotFound(err) {
klog.Infof("Failed to get resource binding(%s/%s): %v", attachedBinding.Namespace, attachedBinding.Name, err)
return err
}

attachedBinding.Labels = util.DedupeAndMergeLabels(attachedBinding.Labels,
map[string]string{workv1alpha2.ResourceBindingPermanentIDLabel: uuid.New().String()})
if err := d.Client.Create(context.TODO(), attachedBinding); err != nil {
return err
}
return nil
}

Expand Down Expand Up @@ -630,6 +640,8 @@ func buildAttachedBinding(binding *workv1alpha2.ResourceBinding, object *unstruc
Clusters: binding.Spec.Clusters,
})

policyID := util.GetLabelValue(binding.Labels, workv1alpha2.ResourceBindingPermanentIDLabel)
dependedLabels = util.DedupeAndMergeLabels(dependedLabels, map[string]string{bindingDependedIdLabelKey: policyID})
return &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: names.GenerateBindingName(object.GetKind(), object.GetName()),
Expand Down
Loading
Loading