sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/internal/util/objs_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 util 18 19 import ( 20 "fmt" 21 "testing" 22 23 . "github.com/onsi/gomega" 24 appsv1 "k8s.io/api/apps/v1" 25 corev1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 28 "k8s.io/apimachinery/pkg/runtime" 29 ) 30 31 func Test_inspectImages(t *testing.T) { 32 type args struct { 33 objs []unstructured.Unstructured 34 } 35 tests := []struct { 36 name string 37 args args 38 want []string 39 wantErr bool 40 }{ 41 { 42 name: "controller without the RBAC proxy", 43 args: args{ 44 objs: []unstructured.Unstructured{ 45 { 46 Object: map[string]interface{}{ 47 "apiVersion": "apps/v1", 48 "kind": deploymentKind, 49 "spec": map[string]interface{}{ 50 "template": map[string]interface{}{ 51 "spec": map[string]interface{}{ 52 "containers": []map[string]interface{}{ 53 { 54 "name": controllerContainerName, 55 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", 56 }, 57 }, 58 }, 59 }, 60 }, 61 }, 62 }, 63 }, 64 }, 65 want: []string{"gcr.io/k8s-staging-cluster-api/cluster-api-controller:main"}, 66 wantErr: false, 67 }, 68 { 69 name: "controller with the RBAC proxy", 70 args: args{ 71 objs: []unstructured.Unstructured{ 72 { 73 Object: map[string]interface{}{ 74 "apiVersion": "apps/v1", 75 "kind": deploymentKind, 76 "spec": map[string]interface{}{ 77 "template": map[string]interface{}{ 78 "spec": map[string]interface{}{ 79 "containers": []map[string]interface{}{ 80 { 81 "name": controllerContainerName, 82 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", 83 }, 84 }, 85 }, 86 }, 87 }, 88 }, 89 }, 90 }, 91 }, 92 want: []string{"gcr.io/k8s-staging-cluster-api/cluster-api-controller:main"}, 93 wantErr: false, 94 }, 95 { 96 name: "controller with init container", 97 args: args{ 98 objs: []unstructured.Unstructured{ 99 { 100 Object: map[string]interface{}{ 101 "apiVersion": "apps/v1", 102 "kind": deploymentKind, 103 "spec": map[string]interface{}{ 104 "template": map[string]interface{}{ 105 "spec": map[string]interface{}{ 106 "containers": []map[string]interface{}{ 107 { 108 "name": controllerContainerName, 109 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", 110 }, 111 }, 112 "initContainers": []map[string]interface{}{ 113 { 114 "name": controllerContainerName, 115 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:init", 116 }, 117 }, 118 }, 119 }, 120 }, 121 }, 122 }, 123 }, 124 }, 125 want: []string{"gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", "gcr.io/k8s-staging-cluster-api/cluster-api-controller:init"}, 126 wantErr: false, 127 }, 128 { 129 name: "controller with deamonSet", 130 args: args{ 131 objs: []unstructured.Unstructured{ 132 { 133 Object: map[string]interface{}{ 134 "apiVersion": "apps/v1", 135 "kind": daemonSetKind, 136 "spec": map[string]interface{}{ 137 "template": map[string]interface{}{ 138 "spec": map[string]interface{}{ 139 "containers": []map[string]interface{}{ 140 { 141 "name": controllerContainerName, 142 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", 143 }, 144 }, 145 "initContainers": []map[string]interface{}{ 146 { 147 "name": controllerContainerName, 148 "image": "gcr.io/k8s-staging-cluster-api/cluster-api-controller:init", 149 }, 150 }, 151 }, 152 }, 153 }, 154 }, 155 }, 156 }, 157 }, 158 want: []string{"gcr.io/k8s-staging-cluster-api/cluster-api-controller:main", "gcr.io/k8s-staging-cluster-api/cluster-api-controller:init"}, 159 wantErr: false, 160 }, 161 } 162 for _, tt := range tests { 163 t.Run(tt.name, func(t *testing.T) { 164 g := NewWithT(t) 165 166 got, err := InspectImages(tt.args.objs) 167 if tt.wantErr { 168 g.Expect(err).To(HaveOccurred()) 169 return 170 } 171 172 g.Expect(err).ToNot(HaveOccurred()) 173 g.Expect(got).To(Equal(tt.want)) 174 }) 175 } 176 } 177 178 func TestFixImages(t *testing.T) { 179 type args struct { 180 objs []unstructured.Unstructured 181 alterImageFunc func(image string) (string, error) 182 } 183 tests := []struct { 184 name string 185 args args 186 want []string 187 wantErr bool 188 }{ 189 { 190 name: "fix deployment containers images", 191 args: args{ 192 objs: []unstructured.Unstructured{ 193 { 194 Object: map[string]interface{}{ 195 "apiVersion": "apps/v1", 196 "kind": deploymentKind, 197 "spec": map[string]interface{}{ 198 "template": map[string]interface{}{ 199 "spec": map[string]interface{}{ 200 "containers": []map[string]interface{}{ 201 { 202 "image": "container-image", 203 }, 204 }, 205 "initContainers": []map[string]interface{}{ 206 { 207 "image": "init-container-image", 208 }, 209 }, 210 }, 211 }, 212 }, 213 }, 214 }, 215 }, 216 alterImageFunc: func(image string) (string, error) { 217 return fmt.Sprintf("foo-%s", image), nil 218 }, 219 }, 220 want: []string{"foo-container-image", "foo-init-container-image"}, 221 wantErr: false, 222 }, 223 { 224 name: "fix daemonSet containers images", 225 args: args{ 226 objs: []unstructured.Unstructured{ 227 { 228 Object: map[string]interface{}{ 229 "apiVersion": "apps/v1", 230 "kind": daemonSetKind, 231 "spec": map[string]interface{}{ 232 "template": map[string]interface{}{ 233 "spec": map[string]interface{}{ 234 "containers": []map[string]interface{}{ 235 { 236 "image": "container-image", 237 }, 238 }, 239 "initContainers": []map[string]interface{}{ 240 { 241 "image": "init-container-image", 242 }, 243 }, 244 }, 245 }, 246 }, 247 }, 248 }, 249 }, 250 alterImageFunc: func(image string) (string, error) { 251 return fmt.Sprintf("foo-%s", image), nil 252 }, 253 }, 254 want: []string{"foo-container-image", "foo-init-container-image"}, 255 wantErr: false, 256 }, 257 } 258 for _, tt := range tests { 259 t.Run(tt.name, func(t *testing.T) { 260 g := NewWithT(t) 261 262 got, err := FixImages(tt.args.objs, tt.args.alterImageFunc) 263 if tt.wantErr { 264 g.Expect(err).To(HaveOccurred()) 265 return 266 } 267 268 g.Expect(err).ToNot(HaveOccurred()) 269 270 gotImages, err := InspectImages(got) 271 g.Expect(err).ToNot(HaveOccurred()) 272 g.Expect(gotImages).To(Equal(tt.want)) 273 }) 274 } 275 } 276 277 func TestIsDeploymentWithManager(t *testing.T) { 278 convertor := runtime.DefaultUnstructuredConverter 279 280 depManagerContainer := &appsv1.Deployment{ 281 TypeMeta: metav1.TypeMeta{ 282 Kind: "Deployment", 283 APIVersion: "apps/v1", 284 }, 285 ObjectMeta: metav1.ObjectMeta{ 286 Name: "manager-deployment", 287 }, 288 Spec: appsv1.DeploymentSpec{ 289 Template: corev1.PodTemplateSpec{ 290 Spec: corev1.PodSpec{ 291 Containers: []corev1.Container{{Name: controllerContainerName}}, 292 }, 293 }, 294 }, 295 } 296 depManagerContainerObj, err := convertor.ToUnstructured(depManagerContainer) 297 if err != nil { 298 t.Fatalf("failed to construct unstructured object of %v: %v", depManagerContainer, err) 299 } 300 301 depNOManagerContainer := &appsv1.Deployment{ 302 TypeMeta: metav1.TypeMeta{ 303 Kind: "Deployment", 304 APIVersion: "apps/v1", 305 }, 306 ObjectMeta: metav1.ObjectMeta{ 307 Name: "not-manager-deployment", 308 }, 309 Spec: appsv1.DeploymentSpec{ 310 Template: corev1.PodTemplateSpec{ 311 Spec: corev1.PodSpec{ 312 Containers: []corev1.Container{{Name: "not-manager"}}, 313 }, 314 }, 315 }, 316 } 317 depNOManagerContainerObj, err := convertor.ToUnstructured(depNOManagerContainer) 318 if err != nil { 319 t.Fatalf("failed to construct unstructured object of %v : %v", depNOManagerContainer, err) 320 } 321 322 svc := &corev1.Service{ 323 TypeMeta: metav1.TypeMeta{ 324 Kind: "Service", 325 APIVersion: "v1", 326 }, 327 ObjectMeta: metav1.ObjectMeta{ 328 Name: "test-service", 329 }, 330 } 331 svcObj, err := convertor.ToUnstructured(svc) 332 if err != nil { 333 t.Fatalf("failed to construct unstructured object of %v : %v", svc, err) 334 } 335 336 tests := []struct { 337 name string 338 obj unstructured.Unstructured 339 expected bool 340 }{ 341 { 342 name: "deployment with manager container", 343 obj: unstructured.Unstructured{Object: depManagerContainerObj}, 344 expected: true, 345 }, 346 { 347 name: "deployment without manager container", 348 obj: unstructured.Unstructured{Object: depNOManagerContainerObj}, 349 expected: false, 350 }, 351 { 352 name: "not a deployment", 353 obj: unstructured.Unstructured{Object: svcObj}, 354 expected: false, 355 }, 356 } 357 for _, test := range tests { 358 t.Run(test.name, func(t *testing.T) { 359 g := NewWithT(t) 360 actual := IsDeploymentWithManager(test.obj) 361 g.Expect(actual).To(Equal(test.expected)) 362 }) 363 } 364 }