mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-26 15:27:53 -05: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/medik8s/node-maintenance-operator v0.13.0
|
||||||
github.com/onsi/ginkgo v1.16.5
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.18.1
|
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/api v0.24.0
|
||||||
k8s.io/apimachinery v0.24.0
|
k8s.io/apimachinery v0.24.0
|
||||||
k8s.io/client-go v0.24.0
|
k8s.io/client-go v0.24.0
|
||||||
@ -14,6 +14,8 @@ require (
|
|||||||
sigs.k8s.io/controller-runtime v0.12.1
|
sigs.k8s.io/controller-runtime v0.12.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.81.0 // indirect
|
cloud.google.com/go v0.81.0 // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // 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_golang v1.12.1 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
@ -75,7 +76,7 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // 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/apiextensions-apiserver v0.24.0 // indirect
|
||||||
k8s.io/component-base v0.24.0 // indirect
|
k8s.io/component-base v0.24.0 // indirect
|
||||||
k8s.io/klog/v2 v2.60.1 // 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.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.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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.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.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.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.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/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-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/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.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-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-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.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.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
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=
|
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…
x
Reference in New Issue
Block a user