sigs.k8s.io/cluster-api@v1.7.1/util/annotations/helpers_test.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package annotations 18 19 import ( 20 "testing" 21 22 . "github.com/onsi/gomega" 23 corev1 "k8s.io/api/core/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 26 ) 27 28 func TestAddAnnotations(t *testing.T) { 29 g := NewWithT(t) 30 31 testcases := []struct { 32 name string 33 obj metav1.Object 34 input map[string]string 35 expected map[string]string 36 changed bool 37 }{ 38 { 39 name: "should return false if no changes are made", 40 obj: &corev1.Node{ 41 ObjectMeta: metav1.ObjectMeta{ 42 Annotations: map[string]string{ 43 "foo": "bar", 44 }, 45 }, 46 Spec: corev1.NodeSpec{}, 47 Status: corev1.NodeStatus{}, 48 }, 49 input: map[string]string{ 50 "foo": "bar", 51 }, 52 expected: map[string]string{ 53 "foo": "bar", 54 }, 55 changed: false, 56 }, 57 { 58 name: "should do nothing if no annotations are provided", 59 obj: &corev1.Node{ 60 ObjectMeta: metav1.ObjectMeta{ 61 Annotations: map[string]string{ 62 "foo": "bar", 63 }, 64 }, 65 Spec: corev1.NodeSpec{}, 66 Status: corev1.NodeStatus{}, 67 }, 68 input: map[string]string{}, 69 expected: map[string]string{ 70 "foo": "bar", 71 }, 72 changed: false, 73 }, 74 { 75 name: "should do nothing if no annotations are provided and have been nil before", 76 obj: &corev1.Node{ 77 ObjectMeta: metav1.ObjectMeta{ 78 Annotations: nil, 79 }, 80 Spec: corev1.NodeSpec{}, 81 Status: corev1.NodeStatus{}, 82 }, 83 input: map[string]string{}, 84 expected: nil, 85 changed: false, 86 }, 87 { 88 name: "should return true if annotations are added", 89 obj: &corev1.Node{ 90 ObjectMeta: metav1.ObjectMeta{ 91 Annotations: map[string]string{ 92 "foo": "bar", 93 }, 94 }, 95 Spec: corev1.NodeSpec{}, 96 Status: corev1.NodeStatus{}, 97 }, 98 input: map[string]string{ 99 "thing1": "thing2", 100 "buzz": "blah", 101 }, 102 expected: map[string]string{ 103 "foo": "bar", 104 "thing1": "thing2", 105 "buzz": "blah", 106 }, 107 changed: true, 108 }, 109 { 110 name: "should return true if annotations are changed", 111 obj: &corev1.Node{ 112 ObjectMeta: metav1.ObjectMeta{ 113 Annotations: map[string]string{ 114 "foo": "bar", 115 }, 116 }, 117 Spec: corev1.NodeSpec{}, 118 Status: corev1.NodeStatus{}, 119 }, 120 input: map[string]string{ 121 "foo": "buzz", 122 }, 123 expected: map[string]string{ 124 "foo": "buzz", 125 }, 126 changed: true, 127 }, 128 { 129 name: "should return true if annotations are changed and have been nil before", 130 obj: &corev1.Node{ 131 ObjectMeta: metav1.ObjectMeta{ 132 Annotations: nil, 133 }, 134 Spec: corev1.NodeSpec{}, 135 Status: corev1.NodeStatus{}, 136 }, 137 input: map[string]string{ 138 "foo": "buzz", 139 }, 140 expected: map[string]string{ 141 "foo": "buzz", 142 }, 143 changed: true, 144 }, 145 { 146 name: "should add annotations to an empty unstructured", 147 obj: &unstructured.Unstructured{}, 148 input: map[string]string{ 149 "foo": "buzz", 150 }, 151 expected: map[string]string{ 152 "foo": "buzz", 153 }, 154 changed: true, 155 }, 156 { 157 name: "should add annotations to a non empty unstructured", 158 obj: &unstructured.Unstructured{ 159 Object: map[string]interface{}{ 160 "metadata": map[string]interface{}{ 161 "annotations": map[string]interface{}{ 162 "foo": "bar", 163 }, 164 }, 165 }, 166 }, 167 input: map[string]string{ 168 "thing1": "thing2", 169 "buzz": "blah", 170 }, 171 expected: map[string]string{ 172 "foo": "bar", 173 "thing1": "thing2", 174 "buzz": "blah", 175 }, 176 changed: true, 177 }, 178 } 179 180 for _, tc := range testcases { 181 t.Run(tc.name, func(*testing.T) { 182 res := AddAnnotations(tc.obj, tc.input) 183 g.Expect(res).To(Equal(tc.changed)) 184 g.Expect(tc.obj.GetAnnotations()).To(Equal(tc.expected)) 185 }) 186 } 187 } 188 189 func TestHasTruthyAnnotationValue(t *testing.T) { 190 tests := []struct { 191 name string 192 obj metav1.Object 193 annotationKey string 194 expected bool 195 }{ 196 { 197 name: "annotation does not exist", 198 obj: &corev1.Node{ 199 ObjectMeta: metav1.ObjectMeta{ 200 Annotations: map[string]string{ 201 "cluster.x-k8s.io/some-other-annotation": "", 202 }, 203 }, 204 Spec: corev1.NodeSpec{}, 205 Status: corev1.NodeStatus{}, 206 }, 207 annotationKey: "cluster.x-k8s.io/replicas-managed-by", 208 expected: false, 209 }, 210 { 211 name: "no val", 212 obj: &corev1.Node{ 213 ObjectMeta: metav1.ObjectMeta{ 214 Annotations: map[string]string{ 215 "cluster.x-k8s.io/replicas-managed-by": "", 216 }, 217 }, 218 Spec: corev1.NodeSpec{}, 219 Status: corev1.NodeStatus{}, 220 }, 221 annotationKey: "cluster.x-k8s.io/replicas-managed-by", 222 expected: true, 223 }, 224 { 225 name: "annotation exists, true value", 226 obj: &corev1.Node{ 227 ObjectMeta: metav1.ObjectMeta{ 228 Annotations: map[string]string{ 229 "cluster.x-k8s.io/replicas-managed-by": "true", 230 }, 231 }, 232 Spec: corev1.NodeSpec{}, 233 Status: corev1.NodeStatus{}, 234 }, 235 annotationKey: "cluster.x-k8s.io/replicas-managed-by", 236 expected: true, 237 }, 238 { 239 name: "annotation exists, random string value", 240 obj: &corev1.Node{ 241 ObjectMeta: metav1.ObjectMeta{ 242 Annotations: map[string]string{ 243 "cluster.x-k8s.io/replicas-managed-by": "foo", 244 }, 245 }, 246 Spec: corev1.NodeSpec{}, 247 Status: corev1.NodeStatus{}, 248 }, 249 annotationKey: "cluster.x-k8s.io/replicas-managed-by", 250 expected: true, 251 }, 252 { 253 name: "annotation exists, false value", 254 obj: &corev1.Node{ 255 ObjectMeta: metav1.ObjectMeta{ 256 Annotations: map[string]string{ 257 "cluster.x-k8s.io/replicas-managed-by": "false", 258 }, 259 }, 260 Spec: corev1.NodeSpec{}, 261 Status: corev1.NodeStatus{}, 262 }, 263 annotationKey: "cluster.x-k8s.io/replicas-managed-by", 264 expected: false, 265 }, 266 } 267 for _, tt := range tests { 268 tt := tt 269 t.Run(tt.name, func(t *testing.T) { 270 g := NewWithT(t) 271 ret := hasTruthyAnnotationValue(tt.obj, tt.annotationKey) 272 if tt.expected { 273 g.Expect(ret).To(BeTrue()) 274 } else { 275 g.Expect(ret).To(BeFalse()) 276 } 277 }) 278 } 279 }