mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
[node operator] patching util functions
Signed-off-by: Malte Poll <mp@edgeless.systems>
This commit is contained in:
parent
614447495d
commit
3932581f2a
@ -6,7 +6,7 @@ require (
|
||||
github.com/medik8s/node-maintenance-operator v0.13.0
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/gomega v1.18.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stretchr/testify v1.7.5
|
||||
k8s.io/api v0.24.0
|
||||
k8s.io/apimachinery v0.24.0
|
||||
k8s.io/client-go v0.24.0
|
||||
@ -14,6 +14,8 @@ require (
|
||||
sigs.k8s.io/controller-runtime v0.12.1
|
||||
)
|
||||
|
||||
require github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
@ -53,7 +55,6 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
@ -75,7 +76,7 @@ require (
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.24.0 // indirect
|
||||
k8s.io/component-base v0.24.0 // indirect
|
||||
k8s.io/klog/v2 v2.60.1 // indirect
|
||||
|
@ -485,13 +485,16 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q=
|
||||
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
@ -968,8 +971,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -0,0 +1,26 @@
|
||||
package patch
|
||||
|
||||
import "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
// SetAnnotations creates a patch for a client.Object by merging annotations with existing annotations.
|
||||
func SetAnnotations(original, patched client.Object, annotations map[string]string) client.Patch {
|
||||
mergedAnnotations := patched.GetAnnotations()
|
||||
if mergedAnnotations == nil {
|
||||
mergedAnnotations = make(map[string]string, len(annotations))
|
||||
}
|
||||
for annotationKey, annotationValue := range annotations {
|
||||
mergedAnnotations[annotationKey] = annotationValue
|
||||
}
|
||||
patched.SetAnnotations(mergedAnnotations)
|
||||
return client.StrategicMergeFrom(original, client.MergeFromWithOptimisticLock{})
|
||||
}
|
||||
|
||||
// UnsetAnnotations creates a patch for a client.Object by deleting annotations from the object.
|
||||
func UnsetAnnotations(original, patched client.Object, annotationKeys []string) client.Patch {
|
||||
mergedAnnotations := patched.GetAnnotations()
|
||||
for _, annotationKey := range annotationKeys {
|
||||
delete(mergedAnnotations, annotationKey)
|
||||
}
|
||||
patched.SetAnnotations(mergedAnnotations)
|
||||
return client.StrategicMergeFrom(original, client.MergeFromWithOptimisticLock{})
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package patch
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var annotationsTestObject = corev1.Node{
|
||||
TypeMeta: v1.TypeMeta{
|
||||
Kind: "Node",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ResourceVersion: "0",
|
||||
},
|
||||
}
|
||||
|
||||
func TestSetAnnotations(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
oldAnnotations map[string]string
|
||||
newAnnotations map[string]string
|
||||
wantPatch []byte
|
||||
}{
|
||||
"empty patch only contains resource version": {
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node without existing annotations": {
|
||||
newAnnotations: map[string]string{"key": "value"},
|
||||
wantPatch: []byte(`{"metadata":{"annotations":{"key":"value"},"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with same existing annotations": {
|
||||
oldAnnotations: map[string]string{"key": "value"},
|
||||
newAnnotations: map[string]string{"key": "value"},
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with same key but different value": {
|
||||
oldAnnotations: map[string]string{"key": "oldvalue"},
|
||||
newAnnotations: map[string]string{"key": "newvalue"},
|
||||
wantPatch: []byte(`{"metadata":{"annotations":{"key":"newvalue"},"resourceVersion":"0"}}`),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
original := annotationsTestObject.DeepCopy()
|
||||
original.SetAnnotations(tc.oldAnnotations)
|
||||
patched := original.DeepCopy()
|
||||
patch := SetAnnotations(original, patched, tc.newAnnotations)
|
||||
data, err := patch.Data(patched)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.wantPatch, data)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsetAnnotations(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
oldAnnotations map[string]string
|
||||
annotationKeys []string
|
||||
wantPatch []byte
|
||||
}{
|
||||
"empty patch only contains resource version": {
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node without existing annotations": {
|
||||
annotationKeys: []string{"key"},
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with existing annotations": {
|
||||
oldAnnotations: map[string]string{"key": "value"},
|
||||
annotationKeys: []string{"key"},
|
||||
wantPatch: []byte(`{"metadata":{"annotations":null,"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with existing annotations delete one of multiple": {
|
||||
oldAnnotations: map[string]string{"key": "value", "otherkey": "othervalue"},
|
||||
annotationKeys: []string{"key"},
|
||||
wantPatch: []byte(`{"metadata":{"annotations":{"key":null},"resourceVersion":"0"}}`),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
original := annotationsTestObject.DeepCopy()
|
||||
original.SetAnnotations(tc.oldAnnotations)
|
||||
patched := original.DeepCopy()
|
||||
patch := UnsetAnnotations(original, patched, tc.annotationKeys)
|
||||
data, err := patch.Data(patched)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.wantPatch, data)
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package patch
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// SetLabels creates a patch for a client.Object by merging labels with existing labels.
|
||||
func SetLabels(original, patched client.Object, labels map[string]string) client.Patch {
|
||||
mergedLabels := patched.GetLabels()
|
||||
if mergedLabels == nil {
|
||||
mergedLabels = make(map[string]string, len(labels))
|
||||
}
|
||||
for labelKey, labelValue := range labels {
|
||||
mergedLabels[labelKey] = labelValue
|
||||
}
|
||||
patched.SetLabels(mergedLabels)
|
||||
return client.StrategicMergeFrom(original, client.MergeFromWithOptimisticLock{})
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package patch
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var labelsTestObject = corev1.Node{
|
||||
TypeMeta: v1.TypeMeta{
|
||||
Kind: "Node",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ResourceVersion: "0",
|
||||
},
|
||||
}
|
||||
|
||||
func TestSetLabels(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
oldLabels map[string]string
|
||||
newLabels map[string]string
|
||||
wantPatch []byte
|
||||
}{
|
||||
"empty patch only contains resource version": {
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node without existing labels": {
|
||||
newLabels: map[string]string{"key": "value"},
|
||||
wantPatch: []byte(`{"metadata":{"labels":{"key":"value"},"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with same existing labels": {
|
||||
oldLabels: map[string]string{"key": "value"},
|
||||
newLabels: map[string]string{"key": "value"},
|
||||
wantPatch: []byte(`{"metadata":{"resourceVersion":"0"}}`),
|
||||
},
|
||||
"patch on node with same key but different value": {
|
||||
oldLabels: map[string]string{"key": "oldvalue"},
|
||||
newLabels: map[string]string{"key": "newvalue"},
|
||||
wantPatch: []byte(`{"metadata":{"labels":{"key":"newvalue"},"resourceVersion":"0"}}`),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
original := labelsTestObject.DeepCopy()
|
||||
original.SetLabels(tc.oldLabels)
|
||||
patched := original.DeepCopy()
|
||||
patch := SetLabels(original, patched, tc.newLabels)
|
||||
data, err := patch.Data(patched)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.wantPatch, data)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user