Skip to content

Commit

Permalink
Merge pull request #2310 from FabianKramm/main
Browse files Browse the repository at this point in the history
fix: ignore excluded annotations on create
  • Loading branch information
FabianKramm authored Dec 4, 2024
2 parents ed15868 + 97d9681 commit e375813
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pkg/controllers/resources/persistentvolumes/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (s *persistentVolumeSyncer) translate(ctx *synccontext.SyncContext, vPv *co

func (s *persistentVolumeSyncer) translateBackwards(pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) *corev1.PersistentVolume {
// build virtual persistent volume
vObj := translate.CopyObjectWithName(pPv, types.NamespacedName{Name: pPv.Name}, false)
vObj := translate.CopyObjectWithName(pPv, types.NamespacedName{Name: pPv.Name}, false, s.excludedAnnotations...)
if vPvc != nil {
if vObj.Spec.ClaimRef == nil {
vObj.Spec.ClaimRef = &corev1.ObjectReference{}
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/translate/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func AnnotationsBidirectionalUpdateFunction[T client.Object](event *synccontext.
if newHost == nil {
newHost = map[string]string{}
}
if !apiequality.Semantic.DeepEqual(event.VirtualOld.GetAnnotations(), event.Virtual.GetAnnotations()) {
if !maps.Equal(event.VirtualOld.GetAnnotations(), event.Virtual.GetAnnotations()) {
newHost = mergeMaps(event.VirtualOld.GetAnnotations(), event.Virtual.GetAnnotations(), event.Host.GetAnnotations(), func(key string, value interface{}) (string, interface{}) {
if stringutil.Contains(excludeAnnotations, key) {
return "", nil
Expand All @@ -242,7 +242,7 @@ func AnnotationsBidirectionalUpdateFunction[T client.Object](event *synccontext.

return transformToHost(key, value)
})
} else if !apiequality.Semantic.DeepEqual(event.HostOld.GetAnnotations(), event.Host.GetAnnotations()) {
} else if !maps.Equal(event.HostOld.GetAnnotations(), event.Host.GetAnnotations()) {
newVirtual = mergeMaps(event.HostOld.GetAnnotations(), event.Host.GetAnnotations(), event.Virtual.GetAnnotations(), func(key string, value interface{}) (string, interface{}) {
if stringutil.Contains(excludeAnnotations, key) {
return "", nil
Expand Down
132 changes: 132 additions & 0 deletions pkg/util/translate/labels_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package translate

import (
"testing"

"github.com/loft-sh/vcluster/pkg/syncer/synccontext"
"gotest.tools/v3/assert"
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

func TestAnnotationsSync(t *testing.T) {
// exclude the default class
vAnnotations, pAnnotations := AnnotationsBidirectionalUpdate(synccontext.NewSyncEventWithOld(
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-other",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
), "storageclass.kubernetes.io/is-default-class")
assert.DeepEqual(t, vAnnotations, map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
})
assert.DeepEqual(t, pAnnotations, map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-other",
NameAnnotation: "",
UIDAnnotation: "",
KindAnnotation: storagev1.SchemeGroupVersion.WithKind("StorageClass").String(),
HostNameAnnotation: "",
})

// not exclude the default class
vAnnotations, pAnnotations = AnnotationsBidirectionalUpdate(synccontext.NewSyncEventWithOld(
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-other",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
&storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
},
},
},
))
assert.DeepEqual(t, vAnnotations, map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-other",
})
assert.DeepEqual(t, pAnnotations, map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-other",
NameAnnotation: "",
UIDAnnotation: "",
KindAnnotation: storagev1.SchemeGroupVersion.WithKind("StorageClass").String(),
HostNameAnnotation: "",
})

// check on creation with exclude host -> virtual
pObj := &storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
"not-excluded": "true",
},
},
}
vObj := CopyObjectWithName(pObj, types.NamespacedName{}, true, "storageclass.kubernetes.io/is-default-class")
vAnnotations = VirtualAnnotations(pObj, vObj, "storageclass.kubernetes.io/is-default-class")
assert.DeepEqual(t, vAnnotations, map[string]string{
"not-excluded": "true",
})

// check on creation with exclude virtual -> host
vObj = &storagev1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"storageclass.kubernetes.io/is-default-class": "my-default",
"not-excluded": "true",
},
},
}
pObj = CopyObjectWithName(vObj, types.NamespacedName{}, true, "storageclass.kubernetes.io/is-default-class")
pAnnotations = HostAnnotations(vObj, pObj, "storageclass.kubernetes.io/is-default-class")
assert.DeepEqual(t, pAnnotations, map[string]string{
"not-excluded": "true",
ManagedAnnotationsAnnotation: "not-excluded",
NameAnnotation: "",
UIDAnnotation: "",
KindAnnotation: storagev1.SchemeGroupVersion.WithKind("StorageClass").String(),
HostNameAnnotation: "",
})
}
19 changes: 16 additions & 3 deletions pkg/util/translate/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/loft-sh/vcluster/pkg/scheme"
"github.com/loft-sh/vcluster/pkg/util/stringutil"
"github.com/pkg/errors"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsv1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
Expand All @@ -33,7 +34,7 @@ const (

var Owner client.Object

func CopyObjectWithName[T client.Object](obj T, name types.NamespacedName, setOwner bool) T {
func CopyObjectWithName[T client.Object](obj T, name types.NamespacedName, setOwner bool, excludedAnnotations ...string) T {
target := obj.DeepCopyObject().(T)

// reset metadata & translate name and namespace
Expand All @@ -48,23 +49,35 @@ func CopyObjectWithName[T client.Object](obj T, name types.NamespacedName, setOw
}
}

stripExcludedAnnotations(target, excludedAnnotations...)
return target
}

func HostMetadata[T client.Object](vObj T, name types.NamespacedName, excludedAnnotations ...string) T {
pObj := CopyObjectWithName(vObj, name, true)
pObj := CopyObjectWithName(vObj, name, true, excludedAnnotations...)
stripExcludedAnnotations(vObj, excludedAnnotations...)
pObj.SetAnnotations(HostAnnotations(vObj, pObj, excludedAnnotations...))
pObj.SetLabels(HostLabels(vObj, nil))
return pObj
}

func VirtualMetadata[T client.Object](pObj T, name types.NamespacedName, excludedAnnotations ...string) T {
vObj := CopyObjectWithName(pObj, name, false)
vObj := CopyObjectWithName(pObj, name, false, excludedAnnotations...)
vObj.SetAnnotations(VirtualAnnotations(pObj, nil, excludedAnnotations...))
vObj.SetLabels(VirtualLabels(pObj, nil))
return vObj
}

func stripExcludedAnnotations(obj client.Object, excludedAnnotations ...string) {
annotations := obj.GetAnnotations()
for k := range annotations {
if stringutil.Contains(excludedAnnotations, k) {
delete(annotations, k)
}
}
obj.SetAnnotations(annotations)
}

func VirtualAnnotations(pObj, vObj client.Object, excluded ...string) map[string]string {
excluded = append(excluded, NameAnnotation, NamespaceAnnotation, HostNameAnnotation, HostNamespaceAnnotation, UIDAnnotation, KindAnnotation, ManagedAnnotationsAnnotation, ManagedLabelsAnnotation)
var toAnnotations map[string]string
Expand Down

0 comments on commit e375813

Please sign in to comment.