diff --git a/cmdutils/switches/switches_test.go b/cmdutils/switches/switches_test.go index 2ade244..73d75cc 100644 --- a/cmdutils/switches/switches_test.go +++ b/cmdutils/switches/switches_test.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/configutils/configutils.go b/configutils/configutils.go index 0b07c8a..fd0ad22 100644 --- a/configutils/configutils.go +++ b/configutils/configutils.go @@ -112,7 +112,7 @@ func getKubeconfigFlag() string { // It also applies saner defaults for QPS and burst based on the Kubernetes // controller manager defaults (20 QPS, 30 burst) // -// Config precedence +// # Config precedence // // * Kubeconfig / --kubeconfig value / flag pointing at a file // diff --git a/metautils/metautils.go b/metautils/metautils.go index b2bcc26..2c5e082 100644 --- a/metautils/metautils.go +++ b/metautils/metautils.go @@ -353,6 +353,12 @@ func FilterList(list client.ObjectList, f func(obj client.Object) bool) error { return SetList(list, filtered) } +// HasLabel checks if the object has a label with the given key. +func HasLabel(obj metav1.Object, key string) bool { + _, ok := obj.GetLabels()[key] + return ok +} + // SetLabel sets the given label on the object. func SetLabel(obj metav1.Object, key, value string) { labels := obj.GetLabels() @@ -368,15 +374,40 @@ func SetLabel(obj metav1.Object, key, value string) { func SetLabels(obj metav1.Object, set map[string]string) { labels := obj.GetLabels() if labels == nil { - labels = make(map[string]string) + labels = set + } else { + for k, v := range set { + labels[k] = v + } } + obj.SetLabels(labels) +} - for k, v := range set { - labels[k] = v +// DeleteLabel deletes the label with the given key from the object. +func DeleteLabel(obj metav1.Object, key string) { + labels := obj.GetLabels() + delete(labels, key) + obj.SetLabels(labels) +} + +// DeleteLabels deletes the labels with the given keys from the object. +func DeleteLabels(obj metav1.Object, keys []string) { + labels := obj.GetLabels() + if len(labels) == 0 { + return + } + for _, key := range keys { + delete(labels, key) } obj.SetLabels(labels) } +// HasAnnotation checks if the object has an annotation with the given key. +func HasAnnotation(obj metav1.Object, key string) bool { + _, ok := obj.GetAnnotations()[key] + return ok +} + // SetAnnotation sets the given annotation on the object. func SetAnnotation(obj metav1.Object, key, value string) { annotations := obj.GetAnnotations() @@ -392,11 +423,30 @@ func SetAnnotation(obj metav1.Object, key, value string) { func SetAnnotations(obj metav1.Object, set map[string]string) { annotations := obj.GetAnnotations() if annotations == nil { - annotations = make(map[string]string) + annotations = set + } else { + for k, v := range set { + annotations[k] = v + } } + obj.SetAnnotations(annotations) +} - for k, v := range set { - annotations[k] = v +// DeleteAnnotation deletes the annotation with the given key from the object. +func DeleteAnnotation(obj metav1.Object, key string) { + annotations := obj.GetAnnotations() + delete(annotations, key) + obj.SetAnnotations(annotations) +} + +// DeleteAnnotations deletes the annotations with the given keys from the object. +func DeleteAnnotations(obj metav1.Object, keys []string) { + annotations := obj.GetAnnotations() + if len(annotations) == 0 { + return + } + for _, key := range keys { + delete(annotations, key) } obj.SetAnnotations(annotations) } diff --git a/metautils/metautils_test.go b/metautils/metautils_test.go index dea09b2..12b6b2c 100644 --- a/metautils/metautils_test.go +++ b/metautils/metautils_test.go @@ -511,6 +511,16 @@ var _ = Describe("Metautils", func() { }) }) + DescribeTable("HasLabel", + func(initLabels map[string]string, key string, expected bool) { + obj := &metav1.ObjectMeta{Labels: initLabels} + Expect(HasLabel(obj, key)).To(Equal(expected)) + }, + Entry("label present", map[string]string{"foo": ""}, "foo", true), + Entry("nil labels", nil, "foo", false), + Entry("different label present", map[string]string{"bar": ""}, "foo", false), + ) + DescribeTable("SetLabel", func(initLabels map[string]string, key, value string, expected map[string]string) { obj := &metav1.ObjectMeta{Labels: initLabels} @@ -534,6 +544,39 @@ var _ = Describe("Metautils", func() { Entry("partial other keys, same key", map[string]string{"foo": "baz", "bar": "baz"}, map[string]string{"foo": "bar"}, map[string]string{"foo": "bar", "bar": "baz"}), ) + DescribeTable("DeleteLabel", + func(initLabels map[string]string, key string, expected map[string]string) { + obj := &metav1.ObjectMeta{Labels: initLabels} + DeleteLabel(obj, key) + Expect(obj.Labels).To(Equal(expected)) + }, + Entry("key present", map[string]string{"foo": "bar"}, "foo", map[string]string{}), + Entry("different key present", map[string]string{"bar": "baz"}, "foo", map[string]string{"bar": "baz"}), + Entry("nil map", nil, "foo", nil), + ) + + DescribeTable("DeleteLabels", + func(initLabels map[string]string, keys []string, expected map[string]string) { + obj := &metav1.ObjectMeta{Labels: initLabels} + DeleteLabels(obj, keys) + Expect(obj.Labels).To(Equal(expected)) + }, + Entry("keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"foo", "bar"}, map[string]string{}), + Entry("some keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"foo"}, map[string]string{"bar": "baz"}), + Entry("no keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"qux"}, map[string]string{"foo": "bar", "bar": "baz"}), + Entry("nil map", nil, []string{"foo", "bar"}, nil), + ) + + DescribeTable("HasAnnotation", + func(initAnnotations map[string]string, key string, expected bool) { + obj := &metav1.ObjectMeta{Annotations: initAnnotations} + Expect(HasAnnotation(obj, key)).To(Equal(expected)) + }, + Entry("annotation present", map[string]string{"foo": ""}, "foo", true), + Entry("nil annotations", nil, "foo", false), + Entry("different annotation present", map[string]string{"bar": ""}, "foo", false), + ) + DescribeTable("SetAnnotation", func(initAnnotations map[string]string, key, value string, expected map[string]string) { obj := &metav1.ObjectMeta{Annotations: initAnnotations} @@ -557,6 +600,29 @@ var _ = Describe("Metautils", func() { Entry("partial other keys, same key", map[string]string{"foo": "baz", "bar": "baz"}, map[string]string{"foo": "bar"}, map[string]string{"foo": "bar", "bar": "baz"}), ) + DescribeTable("DeleteAnnotation", + func(initAnnotations map[string]string, key string, expected map[string]string) { + obj := &metav1.ObjectMeta{Annotations: initAnnotations} + DeleteAnnotation(obj, key) + Expect(obj.Annotations).To(Equal(expected)) + }, + Entry("key present", map[string]string{"foo": "bar"}, "foo", map[string]string{}), + Entry("different key present", map[string]string{"bar": "baz"}, "foo", map[string]string{"bar": "baz"}), + Entry("nil map", nil, "foo", nil), + ) + + DescribeTable("DeleteAnnotations", + func(initAnnotations map[string]string, keys []string, expected map[string]string) { + obj := &metav1.ObjectMeta{Annotations: initAnnotations} + DeleteAnnotations(obj, keys) + Expect(obj.Annotations).To(Equal(expected)) + }, + Entry("keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"foo", "bar"}, map[string]string{}), + Entry("some keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"foo"}, map[string]string{"bar": "baz"}), + Entry("no keys present", map[string]string{"foo": "bar", "bar": "baz"}, []string{"qux"}, map[string]string{"foo": "bar", "bar": "baz"}), + Entry("nil map", nil, []string{"foo", "bar"}, nil), + ) + Describe("FilterList", func() { It("should filter the list with the given function", func() { list := &corev1.SecretList{ diff --git a/mock/controller-runtime/client/doc.go b/mock/controller-runtime/client/doc.go index f23801d..15d20e0 100644 --- a/mock/controller-runtime/client/doc.go +++ b/mock/controller-runtime/client/doc.go @@ -13,6 +13,7 @@ // limitations under the License. // Package client contains mocks for controller-runtime's client package. +// //go:generate go run github.com/golang/mock/mockgen -copyright_file ../../../hack/boilerplate.go.txt -package client -destination mocks.go sigs.k8s.io/controller-runtime/pkg/client Client,FieldIndexer //go:generate go run github.com/golang/mock/mockgen -copyright_file ../../../hack/boilerplate.go.txt -package client -destination funcs.go github.com/onmetal/controller-utils/mock/controller-runtime/client IndexerFunc package client diff --git a/mock/controller-utils/clientutils/doc.go b/mock/controller-utils/clientutils/doc.go index baf1641..4654195 100644 --- a/mock/controller-utils/clientutils/doc.go +++ b/mock/controller-utils/clientutils/doc.go @@ -13,5 +13,6 @@ // limitations under the License. // Package clientutils contains mocks for the actual clientutils package. +// //go:generate go run github.com/golang/mock/mockgen -copyright_file ../../../hack/boilerplate.go.txt -package clientutils -destination=mocks.go github.com/onmetal/controller-utils/clientutils PatchProvider package clientutils