sigs.k8s.io/cluster-api@v1.7.1/controlplane/kubeadm/internal/filters_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 internal 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 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 28 bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" 29 controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1" 30 ) 31 32 func TestMatchClusterConfiguration(t *testing.T) { 33 t.Run("machine without the ClusterConfiguration annotation should match (not enough information to make a decision)", func(t *testing.T) { 34 g := NewWithT(t) 35 kcp := &controlplanev1.KubeadmControlPlane{} 36 m := &clusterv1.Machine{} 37 g.Expect(matchClusterConfiguration(kcp, m)).To(BeTrue()) 38 }) 39 t.Run("machine without an invalid ClusterConfiguration annotation should not match (only solution is to rollout)", func(t *testing.T) { 40 g := NewWithT(t) 41 kcp := &controlplanev1.KubeadmControlPlane{} 42 m := &clusterv1.Machine{ 43 ObjectMeta: metav1.ObjectMeta{ 44 Annotations: map[string]string{ 45 controlplanev1.KubeadmClusterConfigurationAnnotation: "$|^^_", 46 }, 47 }, 48 } 49 g.Expect(matchClusterConfiguration(kcp, m)).To(BeFalse()) 50 }) 51 t.Run("Return true if cluster configuration matches", func(t *testing.T) { 52 g := NewWithT(t) 53 kcp := &controlplanev1.KubeadmControlPlane{ 54 Spec: controlplanev1.KubeadmControlPlaneSpec{ 55 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 56 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ 57 ClusterName: "foo", 58 }, 59 }, 60 }, 61 } 62 m := &clusterv1.Machine{ 63 ObjectMeta: metav1.ObjectMeta{ 64 Annotations: map[string]string{ 65 controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"foo\"\n}", 66 }, 67 }, 68 } 69 g.Expect(matchClusterConfiguration(kcp, m)).To(BeTrue()) 70 }) 71 t.Run("Return false if cluster configuration does not match", func(t *testing.T) { 72 g := NewWithT(t) 73 kcp := &controlplanev1.KubeadmControlPlane{ 74 Spec: controlplanev1.KubeadmControlPlaneSpec{ 75 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 76 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ 77 ClusterName: "foo", 78 }, 79 }, 80 }, 81 } 82 m := &clusterv1.Machine{ 83 ObjectMeta: metav1.ObjectMeta{ 84 Annotations: map[string]string{ 85 controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"bar\"\n}", 86 }, 87 }, 88 } 89 g.Expect(matchClusterConfiguration(kcp, m)).To(BeFalse()) 90 }) 91 t.Run("Return true if cluster configuration is nil (special case)", func(t *testing.T) { 92 g := NewWithT(t) 93 kcp := &controlplanev1.KubeadmControlPlane{ 94 Spec: controlplanev1.KubeadmControlPlaneSpec{ 95 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{}, 96 }, 97 } 98 m := &clusterv1.Machine{ 99 ObjectMeta: metav1.ObjectMeta{ 100 Annotations: map[string]string{ 101 controlplanev1.KubeadmClusterConfigurationAnnotation: "null", 102 }, 103 }, 104 } 105 g.Expect(matchClusterConfiguration(kcp, m)).To(BeTrue()) 106 }) 107 t.Run("Return true although the DNS fields are different", func(t *testing.T) { 108 g := NewWithT(t) 109 kcp := &controlplanev1.KubeadmControlPlane{ 110 Spec: controlplanev1.KubeadmControlPlaneSpec{ 111 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 112 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ 113 DNS: bootstrapv1.DNS{ 114 ImageMeta: bootstrapv1.ImageMeta{ 115 ImageTag: "v1.10.1", 116 ImageRepository: "gcr.io/capi-test", 117 }, 118 }, 119 }, 120 }, 121 }, 122 } 123 m := &clusterv1.Machine{ 124 ObjectMeta: metav1.ObjectMeta{ 125 Annotations: map[string]string{ 126 controlplanev1.KubeadmClusterConfigurationAnnotation: "{\"dns\":{\"imageRepository\":\"gcr.io/capi-test\",\"imageTag\":\"v1.9.3\"}}", 127 }, 128 }, 129 } 130 g.Expect(matchClusterConfiguration(kcp, m)).To(BeTrue()) 131 }) 132 } 133 134 func TestGetAdjustedKcpConfig(t *testing.T) { 135 t.Run("if the machine is the first control plane, kcp config should get InitConfiguration", func(t *testing.T) { 136 g := NewWithT(t) 137 kcp := &controlplanev1.KubeadmControlPlane{ 138 Spec: controlplanev1.KubeadmControlPlaneSpec{ 139 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 140 InitConfiguration: &bootstrapv1.InitConfiguration{}, 141 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 142 }, 143 }, 144 } 145 machineConfig := &bootstrapv1.KubeadmConfig{ 146 Spec: bootstrapv1.KubeadmConfigSpec{ 147 InitConfiguration: &bootstrapv1.InitConfiguration{}, // first control-plane 148 }, 149 } 150 kcpConfig := getAdjustedKcpConfig(kcp, machineConfig) 151 g.Expect(kcpConfig.InitConfiguration).ToNot(BeNil()) 152 g.Expect(kcpConfig.JoinConfiguration).To(BeNil()) 153 }) 154 t.Run("if the machine is a joining control plane, kcp config should get JoinConfiguration", func(t *testing.T) { 155 g := NewWithT(t) 156 kcp := &controlplanev1.KubeadmControlPlane{ 157 Spec: controlplanev1.KubeadmControlPlaneSpec{ 158 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 159 InitConfiguration: &bootstrapv1.InitConfiguration{}, 160 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 161 }, 162 }, 163 } 164 machineConfig := &bootstrapv1.KubeadmConfig{ 165 Spec: bootstrapv1.KubeadmConfigSpec{ 166 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, // joining control-plane 167 }, 168 } 169 kcpConfig := getAdjustedKcpConfig(kcp, machineConfig) 170 g.Expect(kcpConfig.InitConfiguration).To(BeNil()) 171 g.Expect(kcpConfig.JoinConfiguration).ToNot(BeNil()) 172 }) 173 } 174 175 func TestCleanupConfigFields(t *testing.T) { 176 t.Run("ClusterConfiguration gets removed from KcpConfig and MachineConfig", func(t *testing.T) { 177 g := NewWithT(t) 178 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 179 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 180 } 181 machineConfig := &bootstrapv1.KubeadmConfig{ 182 Spec: bootstrapv1.KubeadmConfigSpec{ 183 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 184 }, 185 } 186 cleanupConfigFields(kcpConfig, machineConfig) 187 g.Expect(kcpConfig.ClusterConfiguration).To(BeNil()) 188 g.Expect(machineConfig.Spec.ClusterConfiguration).To(BeNil()) 189 }) 190 t.Run("JoinConfiguration gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { 191 g := NewWithT(t) 192 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 193 JoinConfiguration: nil, // KCP not providing a JoinConfiguration 194 } 195 machineConfig := &bootstrapv1.KubeadmConfig{ 196 Spec: bootstrapv1.KubeadmConfigSpec{ 197 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, // Machine gets a default JoinConfiguration from CABPK 198 }, 199 } 200 cleanupConfigFields(kcpConfig, machineConfig) 201 g.Expect(kcpConfig.JoinConfiguration).To(BeNil()) 202 g.Expect(machineConfig.Spec.JoinConfiguration).To(BeNil()) 203 }) 204 t.Run("JoinConfiguration.Discovery gets removed because it is not relevant for compare", func(t *testing.T) { 205 g := NewWithT(t) 206 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 207 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 208 Discovery: bootstrapv1.Discovery{TLSBootstrapToken: "aaa"}, 209 }, 210 } 211 machineConfig := &bootstrapv1.KubeadmConfig{ 212 Spec: bootstrapv1.KubeadmConfigSpec{ 213 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 214 Discovery: bootstrapv1.Discovery{TLSBootstrapToken: "aaa"}, 215 }, 216 }, 217 } 218 cleanupConfigFields(kcpConfig, machineConfig) 219 g.Expect(kcpConfig.JoinConfiguration.Discovery).To(BeComparableTo(bootstrapv1.Discovery{})) 220 g.Expect(machineConfig.Spec.JoinConfiguration.Discovery).To(BeComparableTo(bootstrapv1.Discovery{})) 221 }) 222 t.Run("JoinConfiguration.ControlPlane gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { 223 g := NewWithT(t) 224 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 225 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 226 ControlPlane: nil, // Control plane configuration missing in KCP 227 }, 228 } 229 machineConfig := &bootstrapv1.KubeadmConfig{ 230 Spec: bootstrapv1.KubeadmConfigSpec{ 231 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 232 ControlPlane: &bootstrapv1.JoinControlPlane{}, // Machine gets a default JoinConfiguration.ControlPlane from CABPK 233 }, 234 }, 235 } 236 cleanupConfigFields(kcpConfig, machineConfig) 237 g.Expect(kcpConfig.JoinConfiguration).ToNot(BeNil()) 238 g.Expect(machineConfig.Spec.JoinConfiguration.ControlPlane).To(BeNil()) 239 }) 240 t.Run("JoinConfiguration.NodeRegistrationOptions gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { 241 g := NewWithT(t) 242 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 243 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 244 NodeRegistration: bootstrapv1.NodeRegistrationOptions{}, // NodeRegistrationOptions configuration missing in KCP 245 }, 246 } 247 machineConfig := &bootstrapv1.KubeadmConfig{ 248 Spec: bootstrapv1.KubeadmConfigSpec{ 249 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 250 NodeRegistration: bootstrapv1.NodeRegistrationOptions{Name: "test"}, // Machine gets a some JoinConfiguration.NodeRegistrationOptions 251 }, 252 }, 253 } 254 cleanupConfigFields(kcpConfig, machineConfig) 255 g.Expect(kcpConfig.JoinConfiguration).ToNot(BeNil()) 256 g.Expect(machineConfig.Spec.JoinConfiguration.NodeRegistration).To(BeComparableTo(bootstrapv1.NodeRegistrationOptions{})) 257 }) 258 t.Run("InitConfiguration.TypeMeta gets removed from MachineConfig", func(t *testing.T) { 259 g := NewWithT(t) 260 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 261 InitConfiguration: &bootstrapv1.InitConfiguration{}, 262 } 263 machineConfig := &bootstrapv1.KubeadmConfig{ 264 Spec: bootstrapv1.KubeadmConfigSpec{ 265 InitConfiguration: &bootstrapv1.InitConfiguration{ 266 TypeMeta: metav1.TypeMeta{ 267 Kind: "JoinConfiguration", 268 APIVersion: bootstrapv1.GroupVersion.String(), 269 }, 270 }, 271 }, 272 } 273 cleanupConfigFields(kcpConfig, machineConfig) 274 g.Expect(kcpConfig.InitConfiguration).ToNot(BeNil()) 275 g.Expect(machineConfig.Spec.InitConfiguration.TypeMeta).To(BeComparableTo(metav1.TypeMeta{})) 276 }) 277 t.Run("JoinConfiguration.TypeMeta gets removed from MachineConfig", func(t *testing.T) { 278 g := NewWithT(t) 279 kcpConfig := &bootstrapv1.KubeadmConfigSpec{ 280 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 281 } 282 machineConfig := &bootstrapv1.KubeadmConfig{ 283 Spec: bootstrapv1.KubeadmConfigSpec{ 284 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 285 TypeMeta: metav1.TypeMeta{ 286 Kind: "JoinConfiguration", 287 APIVersion: bootstrapv1.GroupVersion.String(), 288 }, 289 }, 290 }, 291 } 292 cleanupConfigFields(kcpConfig, machineConfig) 293 g.Expect(kcpConfig.JoinConfiguration).ToNot(BeNil()) 294 g.Expect(machineConfig.Spec.JoinConfiguration.TypeMeta).To(BeComparableTo(metav1.TypeMeta{})) 295 }) 296 } 297 298 func TestMatchInitOrJoinConfiguration(t *testing.T) { 299 t.Run("returns true if the machine does not have a bootstrap config", func(t *testing.T) { 300 g := NewWithT(t) 301 kcp := &controlplanev1.KubeadmControlPlane{} 302 g.Expect(matchInitOrJoinConfiguration(nil, kcp)).To(BeTrue()) 303 }) 304 t.Run("returns true if the there are problems reading the bootstrap config", func(t *testing.T) { 305 g := NewWithT(t) 306 kcp := &controlplanev1.KubeadmControlPlane{} 307 g.Expect(matchInitOrJoinConfiguration(nil, kcp)).To(BeTrue()) 308 }) 309 t.Run("returns true if one format is empty and the other one cloud-config", func(t *testing.T) { 310 g := NewWithT(t) 311 kcp := &controlplanev1.KubeadmControlPlane{ 312 Spec: controlplanev1.KubeadmControlPlaneSpec{ 313 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 314 Format: bootstrapv1.CloudConfig, 315 }, 316 }, 317 } 318 m := &clusterv1.Machine{ 319 TypeMeta: metav1.TypeMeta{ 320 Kind: "KubeadmConfig", 321 APIVersion: clusterv1.GroupVersion.String(), 322 }, 323 ObjectMeta: metav1.ObjectMeta{ 324 Namespace: "default", 325 Name: "test", 326 }, 327 Spec: clusterv1.MachineSpec{ 328 Bootstrap: clusterv1.Bootstrap{ 329 ConfigRef: &corev1.ObjectReference{ 330 Kind: "KubeadmConfig", 331 Namespace: "default", 332 Name: "test", 333 APIVersion: bootstrapv1.GroupVersion.String(), 334 }, 335 }, 336 }, 337 } 338 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 339 m.Name: { 340 TypeMeta: metav1.TypeMeta{ 341 Kind: "KubeadmConfig", 342 APIVersion: bootstrapv1.GroupVersion.String(), 343 }, 344 ObjectMeta: metav1.ObjectMeta{ 345 Namespace: "default", 346 Name: "test", 347 }, 348 Spec: bootstrapv1.KubeadmConfigSpec{ 349 Format: "", 350 }, 351 }, 352 } 353 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeTrue()) 354 }) 355 t.Run("returns true if InitConfiguration is equal", func(t *testing.T) { 356 g := NewWithT(t) 357 kcp := &controlplanev1.KubeadmControlPlane{ 358 Spec: controlplanev1.KubeadmControlPlaneSpec{ 359 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 360 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 361 InitConfiguration: &bootstrapv1.InitConfiguration{}, 362 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 363 }, 364 }, 365 } 366 m := &clusterv1.Machine{ 367 TypeMeta: metav1.TypeMeta{ 368 Kind: "KubeadmConfig", 369 APIVersion: clusterv1.GroupVersion.String(), 370 }, 371 ObjectMeta: metav1.ObjectMeta{ 372 Namespace: "default", 373 Name: "test", 374 }, 375 Spec: clusterv1.MachineSpec{ 376 Bootstrap: clusterv1.Bootstrap{ 377 ConfigRef: &corev1.ObjectReference{ 378 Kind: "KubeadmConfig", 379 Namespace: "default", 380 Name: "test", 381 APIVersion: bootstrapv1.GroupVersion.String(), 382 }, 383 }, 384 }, 385 } 386 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 387 m.Name: { 388 TypeMeta: metav1.TypeMeta{ 389 Kind: "KubeadmConfig", 390 APIVersion: bootstrapv1.GroupVersion.String(), 391 }, 392 ObjectMeta: metav1.ObjectMeta{ 393 Namespace: "default", 394 Name: "test", 395 }, 396 Spec: bootstrapv1.KubeadmConfigSpec{ 397 InitConfiguration: &bootstrapv1.InitConfiguration{}, 398 }, 399 }, 400 } 401 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeTrue()) 402 }) 403 t.Run("returns false if InitConfiguration is NOT equal", func(t *testing.T) { 404 g := NewWithT(t) 405 kcp := &controlplanev1.KubeadmControlPlane{ 406 Spec: controlplanev1.KubeadmControlPlaneSpec{ 407 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 408 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 409 InitConfiguration: &bootstrapv1.InitConfiguration{ 410 NodeRegistration: bootstrapv1.NodeRegistrationOptions{ 411 Name: "A new name", // This is a change 412 }, 413 }, 414 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 415 }, 416 }, 417 } 418 m := &clusterv1.Machine{ 419 TypeMeta: metav1.TypeMeta{ 420 Kind: "KubeadmConfig", 421 APIVersion: clusterv1.GroupVersion.String(), 422 }, 423 ObjectMeta: metav1.ObjectMeta{ 424 Namespace: "default", 425 Name: "test", 426 }, 427 Spec: clusterv1.MachineSpec{ 428 Bootstrap: clusterv1.Bootstrap{ 429 ConfigRef: &corev1.ObjectReference{ 430 Kind: "KubeadmConfig", 431 Namespace: "default", 432 Name: "test", 433 APIVersion: bootstrapv1.GroupVersion.String(), 434 }, 435 }, 436 }, 437 } 438 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 439 m.Name: { 440 TypeMeta: metav1.TypeMeta{ 441 Kind: "KubeadmConfig", 442 APIVersion: bootstrapv1.GroupVersion.String(), 443 }, 444 ObjectMeta: metav1.ObjectMeta{ 445 Namespace: "default", 446 Name: "test", 447 }, 448 Spec: bootstrapv1.KubeadmConfigSpec{ 449 InitConfiguration: &bootstrapv1.InitConfiguration{}, 450 }, 451 }, 452 } 453 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeFalse()) 454 }) 455 t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { 456 g := NewWithT(t) 457 kcp := &controlplanev1.KubeadmControlPlane{ 458 Spec: controlplanev1.KubeadmControlPlaneSpec{ 459 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 460 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 461 InitConfiguration: &bootstrapv1.InitConfiguration{}, 462 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 463 }, 464 }, 465 } 466 m := &clusterv1.Machine{ 467 TypeMeta: metav1.TypeMeta{ 468 Kind: "KubeadmConfig", 469 APIVersion: clusterv1.GroupVersion.String(), 470 }, 471 ObjectMeta: metav1.ObjectMeta{ 472 Namespace: "default", 473 Name: "test", 474 }, 475 Spec: clusterv1.MachineSpec{ 476 Bootstrap: clusterv1.Bootstrap{ 477 ConfigRef: &corev1.ObjectReference{ 478 Kind: "KubeadmConfig", 479 Namespace: "default", 480 Name: "test", 481 APIVersion: bootstrapv1.GroupVersion.String(), 482 }, 483 }, 484 }, 485 } 486 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 487 m.Name: { 488 TypeMeta: metav1.TypeMeta{ 489 Kind: "KubeadmConfig", 490 APIVersion: bootstrapv1.GroupVersion.String(), 491 }, 492 ObjectMeta: metav1.ObjectMeta{ 493 Namespace: "default", 494 Name: "test", 495 }, 496 Spec: bootstrapv1.KubeadmConfigSpec{ 497 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 498 }, 499 }, 500 } 501 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeTrue()) 502 }) 503 t.Run("returns false if JoinConfiguration is NOT equal", func(t *testing.T) { 504 g := NewWithT(t) 505 kcp := &controlplanev1.KubeadmControlPlane{ 506 Spec: controlplanev1.KubeadmControlPlaneSpec{ 507 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 508 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 509 InitConfiguration: &bootstrapv1.InitConfiguration{}, 510 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 511 NodeRegistration: bootstrapv1.NodeRegistrationOptions{ 512 Name: "A new name", // This is a change 513 }, 514 }, 515 }, 516 }, 517 } 518 m := &clusterv1.Machine{ 519 TypeMeta: metav1.TypeMeta{ 520 Kind: "KubeadmConfig", 521 APIVersion: clusterv1.GroupVersion.String(), 522 }, 523 ObjectMeta: metav1.ObjectMeta{ 524 Namespace: "default", 525 Name: "test", 526 }, 527 Spec: clusterv1.MachineSpec{ 528 Bootstrap: clusterv1.Bootstrap{ 529 ConfigRef: &corev1.ObjectReference{ 530 Kind: "KubeadmConfig", 531 Namespace: "default", 532 Name: "test", 533 APIVersion: bootstrapv1.GroupVersion.String(), 534 }, 535 }, 536 }, 537 } 538 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 539 m.Name: { 540 TypeMeta: metav1.TypeMeta{ 541 Kind: "KubeadmConfig", 542 APIVersion: bootstrapv1.GroupVersion.String(), 543 }, 544 ObjectMeta: metav1.ObjectMeta{ 545 Namespace: "default", 546 Name: "test", 547 }, 548 Spec: bootstrapv1.KubeadmConfigSpec{ 549 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 550 }, 551 }, 552 } 553 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeFalse()) 554 }) 555 t.Run("returns false if some other configurations are not equal", func(t *testing.T) { 556 g := NewWithT(t) 557 kcp := &controlplanev1.KubeadmControlPlane{ 558 Spec: controlplanev1.KubeadmControlPlaneSpec{ 559 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 560 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 561 InitConfiguration: &bootstrapv1.InitConfiguration{}, 562 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 563 Files: []bootstrapv1.File{}, // This is a change 564 }, 565 }, 566 } 567 m := &clusterv1.Machine{ 568 TypeMeta: metav1.TypeMeta{ 569 Kind: "KubeadmConfig", 570 APIVersion: clusterv1.GroupVersion.String(), 571 }, 572 ObjectMeta: metav1.ObjectMeta{ 573 Namespace: "default", 574 Name: "test", 575 }, 576 Spec: clusterv1.MachineSpec{ 577 Bootstrap: clusterv1.Bootstrap{ 578 ConfigRef: &corev1.ObjectReference{ 579 Kind: "KubeadmConfig", 580 Namespace: "default", 581 Name: "test", 582 APIVersion: bootstrapv1.GroupVersion.String(), 583 }, 584 }, 585 }, 586 } 587 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 588 m.Name: { 589 TypeMeta: metav1.TypeMeta{ 590 Kind: "KubeadmConfig", 591 APIVersion: bootstrapv1.GroupVersion.String(), 592 }, 593 ObjectMeta: metav1.ObjectMeta{ 594 Namespace: "default", 595 Name: "test", 596 }, 597 Spec: bootstrapv1.KubeadmConfigSpec{ 598 InitConfiguration: &bootstrapv1.InitConfiguration{}, 599 }, 600 }, 601 } 602 g.Expect(matchInitOrJoinConfiguration(machineConfigs[m.Name], kcp)).To(BeFalse()) 603 }) 604 } 605 606 func TestMatchesKubeadmBootstrapConfig(t *testing.T) { 607 t.Run("returns true if ClusterConfiguration is equal", func(t *testing.T) { 608 g := NewWithT(t) 609 kcp := &controlplanev1.KubeadmControlPlane{ 610 Spec: controlplanev1.KubeadmControlPlaneSpec{ 611 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 612 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ 613 ClusterName: "foo", 614 }, 615 }, 616 }, 617 } 618 m := &clusterv1.Machine{ 619 ObjectMeta: metav1.ObjectMeta{ 620 Annotations: map[string]string{ 621 controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"foo\"\n}", 622 }, 623 }, 624 } 625 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 626 m.Name: {}, 627 } 628 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 629 g.Expect(match).To(BeTrue()) 630 g.Expect(reason).To(BeEmpty()) 631 }) 632 t.Run("returns false if ClusterConfiguration is NOT equal", func(t *testing.T) { 633 g := NewWithT(t) 634 kcp := &controlplanev1.KubeadmControlPlane{ 635 Spec: controlplanev1.KubeadmControlPlaneSpec{ 636 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 637 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ 638 ClusterName: "foo", 639 }, 640 }, 641 }, 642 } 643 m := &clusterv1.Machine{ 644 ObjectMeta: metav1.ObjectMeta{ 645 Annotations: map[string]string{ 646 controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"bar\"\n}", 647 }, 648 }, 649 } 650 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 651 m.Name: {}, 652 } 653 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 654 g.Expect(match).To(BeFalse()) 655 g.Expect(reason).To(Equal("Machine ClusterConfiguration is outdated")) 656 }) 657 t.Run("returns true if InitConfiguration is equal", func(t *testing.T) { 658 g := NewWithT(t) 659 kcp := &controlplanev1.KubeadmControlPlane{ 660 Spec: controlplanev1.KubeadmControlPlaneSpec{ 661 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 662 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 663 InitConfiguration: &bootstrapv1.InitConfiguration{}, 664 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 665 }, 666 }, 667 } 668 m := &clusterv1.Machine{ 669 TypeMeta: metav1.TypeMeta{ 670 Kind: "KubeadmConfig", 671 APIVersion: clusterv1.GroupVersion.String(), 672 }, 673 ObjectMeta: metav1.ObjectMeta{ 674 Namespace: "default", 675 Name: "test", 676 }, 677 Spec: clusterv1.MachineSpec{ 678 Bootstrap: clusterv1.Bootstrap{ 679 ConfigRef: &corev1.ObjectReference{ 680 Kind: "KubeadmConfig", 681 Namespace: "default", 682 Name: "test", 683 APIVersion: bootstrapv1.GroupVersion.String(), 684 }, 685 }, 686 }, 687 } 688 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 689 m.Name: { 690 TypeMeta: metav1.TypeMeta{ 691 Kind: "KubeadmConfig", 692 APIVersion: bootstrapv1.GroupVersion.String(), 693 }, 694 ObjectMeta: metav1.ObjectMeta{ 695 Namespace: "default", 696 Name: "test", 697 }, 698 Spec: bootstrapv1.KubeadmConfigSpec{ 699 InitConfiguration: &bootstrapv1.InitConfiguration{}, 700 }, 701 }, 702 } 703 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 704 g.Expect(match).To(BeTrue()) 705 g.Expect(reason).To(BeEmpty()) 706 }) 707 t.Run("returns false if InitConfiguration is NOT equal", func(t *testing.T) { 708 g := NewWithT(t) 709 kcp := &controlplanev1.KubeadmControlPlane{ 710 Spec: controlplanev1.KubeadmControlPlaneSpec{ 711 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 712 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 713 InitConfiguration: &bootstrapv1.InitConfiguration{ 714 NodeRegistration: bootstrapv1.NodeRegistrationOptions{ 715 Name: "foo", // This is a change 716 }, 717 }, 718 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 719 }, 720 }, 721 } 722 m := &clusterv1.Machine{ 723 TypeMeta: metav1.TypeMeta{ 724 Kind: "KubeadmConfig", 725 APIVersion: clusterv1.GroupVersion.String(), 726 }, 727 ObjectMeta: metav1.ObjectMeta{ 728 Namespace: "default", 729 Name: "test", 730 }, 731 Spec: clusterv1.MachineSpec{ 732 Bootstrap: clusterv1.Bootstrap{ 733 ConfigRef: &corev1.ObjectReference{ 734 Kind: "KubeadmConfig", 735 Namespace: "default", 736 Name: "test", 737 APIVersion: bootstrapv1.GroupVersion.String(), 738 }, 739 }, 740 }, 741 } 742 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 743 m.Name: { 744 TypeMeta: metav1.TypeMeta{ 745 Kind: "KubeadmConfig", 746 APIVersion: bootstrapv1.GroupVersion.String(), 747 }, 748 ObjectMeta: metav1.ObjectMeta{ 749 Namespace: "default", 750 Name: "test", 751 }, 752 Spec: bootstrapv1.KubeadmConfigSpec{ 753 InitConfiguration: &bootstrapv1.InitConfiguration{}, 754 }, 755 }, 756 } 757 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 758 g.Expect(match).To(BeFalse()) 759 g.Expect(reason).To(Equal("Machine InitConfiguration or JoinConfiguration are outdated")) 760 }) 761 t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { 762 g := NewWithT(t) 763 kcp := &controlplanev1.KubeadmControlPlane{ 764 Spec: controlplanev1.KubeadmControlPlaneSpec{ 765 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 766 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 767 InitConfiguration: &bootstrapv1.InitConfiguration{}, 768 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 769 }, 770 }, 771 } 772 m := &clusterv1.Machine{ 773 TypeMeta: metav1.TypeMeta{ 774 Kind: "KubeadmConfig", 775 APIVersion: clusterv1.GroupVersion.String(), 776 }, 777 ObjectMeta: metav1.ObjectMeta{ 778 Namespace: "default", 779 Name: "test", 780 }, 781 Spec: clusterv1.MachineSpec{ 782 Bootstrap: clusterv1.Bootstrap{ 783 ConfigRef: &corev1.ObjectReference{ 784 Kind: "KubeadmConfig", 785 Namespace: "default", 786 Name: "test", 787 APIVersion: bootstrapv1.GroupVersion.String(), 788 }, 789 }, 790 }, 791 } 792 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 793 m.Name: { 794 TypeMeta: metav1.TypeMeta{ 795 Kind: "KubeadmConfig", 796 APIVersion: bootstrapv1.GroupVersion.String(), 797 }, 798 ObjectMeta: metav1.ObjectMeta{ 799 Namespace: "default", 800 Name: "test", 801 }, 802 Spec: bootstrapv1.KubeadmConfigSpec{ 803 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 804 }, 805 }, 806 } 807 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 808 g.Expect(match).To(BeTrue()) 809 g.Expect(reason).To(BeEmpty()) 810 }) 811 t.Run("returns false if JoinConfiguration is NOT equal", func(t *testing.T) { 812 g := NewWithT(t) 813 kcp := &controlplanev1.KubeadmControlPlane{ 814 Spec: controlplanev1.KubeadmControlPlaneSpec{ 815 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 816 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 817 InitConfiguration: &bootstrapv1.InitConfiguration{}, 818 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 819 NodeRegistration: bootstrapv1.NodeRegistrationOptions{ 820 Name: "foo", // This is a change 821 }, 822 }, 823 }, 824 }, 825 } 826 m := &clusterv1.Machine{ 827 TypeMeta: metav1.TypeMeta{ 828 Kind: "KubeadmConfig", 829 APIVersion: clusterv1.GroupVersion.String(), 830 }, 831 ObjectMeta: metav1.ObjectMeta{ 832 Namespace: "default", 833 Name: "test", 834 }, 835 Spec: clusterv1.MachineSpec{ 836 Bootstrap: clusterv1.Bootstrap{ 837 ConfigRef: &corev1.ObjectReference{ 838 Kind: "KubeadmConfig", 839 Namespace: "default", 840 Name: "test", 841 APIVersion: bootstrapv1.GroupVersion.String(), 842 }, 843 }, 844 }, 845 } 846 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 847 m.Name: { 848 TypeMeta: metav1.TypeMeta{ 849 Kind: "KubeadmConfig", 850 APIVersion: bootstrapv1.GroupVersion.String(), 851 }, 852 ObjectMeta: metav1.ObjectMeta{ 853 Namespace: "default", 854 Name: "test", 855 }, 856 Spec: bootstrapv1.KubeadmConfigSpec{ 857 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 858 }, 859 }, 860 } 861 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 862 g.Expect(match).To(BeFalse()) 863 g.Expect(reason).To(Equal("Machine InitConfiguration or JoinConfiguration are outdated")) 864 }) 865 t.Run("returns false if some other configurations are not equal", func(t *testing.T) { 866 g := NewWithT(t) 867 kcp := &controlplanev1.KubeadmControlPlane{ 868 Spec: controlplanev1.KubeadmControlPlaneSpec{ 869 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 870 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 871 InitConfiguration: &bootstrapv1.InitConfiguration{}, 872 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 873 Files: []bootstrapv1.File{}, // This is a change 874 }, 875 }, 876 } 877 m := &clusterv1.Machine{ 878 TypeMeta: metav1.TypeMeta{ 879 Kind: "KubeadmConfig", 880 APIVersion: clusterv1.GroupVersion.String(), 881 }, 882 ObjectMeta: metav1.ObjectMeta{ 883 Namespace: "default", 884 Name: "test", 885 }, 886 Spec: clusterv1.MachineSpec{ 887 Bootstrap: clusterv1.Bootstrap{ 888 ConfigRef: &corev1.ObjectReference{ 889 Kind: "KubeadmConfig", 890 Namespace: "default", 891 Name: "test", 892 APIVersion: bootstrapv1.GroupVersion.String(), 893 }, 894 }, 895 }, 896 } 897 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 898 m.Name: { 899 TypeMeta: metav1.TypeMeta{ 900 Kind: "KubeadmConfig", 901 APIVersion: bootstrapv1.GroupVersion.String(), 902 }, 903 ObjectMeta: metav1.ObjectMeta{ 904 Namespace: "default", 905 Name: "test", 906 }, 907 Spec: bootstrapv1.KubeadmConfigSpec{ 908 InitConfiguration: &bootstrapv1.InitConfiguration{}, 909 }, 910 }, 911 } 912 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 913 g.Expect(match).To(BeFalse()) 914 g.Expect(reason).To(Equal("Machine InitConfiguration or JoinConfiguration are outdated")) 915 }) 916 t.Run("should match on labels and annotations", func(t *testing.T) { 917 kcp := &controlplanev1.KubeadmControlPlane{ 918 Spec: controlplanev1.KubeadmControlPlaneSpec{ 919 MachineTemplate: controlplanev1.KubeadmControlPlaneMachineTemplate{ 920 ObjectMeta: clusterv1.ObjectMeta{ 921 Annotations: map[string]string{ 922 "test": "annotation", 923 }, 924 Labels: map[string]string{ 925 "test": "labels", 926 }, 927 }, 928 }, 929 KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ 930 ClusterConfiguration: &bootstrapv1.ClusterConfiguration{}, 931 InitConfiguration: &bootstrapv1.InitConfiguration{}, 932 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 933 }, 934 }, 935 } 936 m := &clusterv1.Machine{ 937 TypeMeta: metav1.TypeMeta{ 938 Kind: "KubeadmConfig", 939 APIVersion: clusterv1.GroupVersion.String(), 940 }, 941 ObjectMeta: metav1.ObjectMeta{ 942 Namespace: "default", 943 Name: "test", 944 }, 945 Spec: clusterv1.MachineSpec{ 946 Bootstrap: clusterv1.Bootstrap{ 947 ConfigRef: &corev1.ObjectReference{ 948 Kind: "KubeadmConfig", 949 Namespace: "default", 950 Name: "test", 951 APIVersion: bootstrapv1.GroupVersion.String(), 952 }, 953 }, 954 }, 955 } 956 machineConfigs := map[string]*bootstrapv1.KubeadmConfig{ 957 m.Name: { 958 TypeMeta: metav1.TypeMeta{ 959 Kind: "KubeadmConfig", 960 APIVersion: bootstrapv1.GroupVersion.String(), 961 }, 962 ObjectMeta: metav1.ObjectMeta{ 963 Namespace: "default", 964 Name: "test", 965 }, 966 Spec: bootstrapv1.KubeadmConfigSpec{ 967 JoinConfiguration: &bootstrapv1.JoinConfiguration{}, 968 }, 969 }, 970 } 971 972 t.Run("by returning true if neither labels or annotations match", func(t *testing.T) { 973 g := NewWithT(t) 974 machineConfigs[m.Name].Annotations = nil 975 machineConfigs[m.Name].Labels = nil 976 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 977 g.Expect(match).To(BeTrue()) 978 g.Expect(reason).To(BeEmpty()) 979 }) 980 981 t.Run("by returning true if only labels don't match", func(t *testing.T) { 982 g := NewWithT(t) 983 machineConfigs[m.Name].Annotations = kcp.Spec.MachineTemplate.ObjectMeta.Annotations 984 machineConfigs[m.Name].Labels = nil 985 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 986 g.Expect(match).To(BeTrue()) 987 g.Expect(reason).To(BeEmpty()) 988 }) 989 990 t.Run("by returning true if only annotations don't match", func(t *testing.T) { 991 g := NewWithT(t) 992 machineConfigs[m.Name].Annotations = nil 993 machineConfigs[m.Name].Labels = kcp.Spec.MachineTemplate.ObjectMeta.Labels 994 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 995 g.Expect(match).To(BeTrue()) 996 g.Expect(reason).To(BeEmpty()) 997 }) 998 999 t.Run("by returning true if both labels and annotations match", func(t *testing.T) { 1000 g := NewWithT(t) 1001 machineConfigs[m.Name].Labels = kcp.Spec.MachineTemplate.ObjectMeta.Labels 1002 machineConfigs[m.Name].Annotations = kcp.Spec.MachineTemplate.ObjectMeta.Annotations 1003 reason, match := matchesKubeadmBootstrapConfig(machineConfigs, kcp, m) 1004 g.Expect(match).To(BeTrue()) 1005 g.Expect(reason).To(BeEmpty()) 1006 }) 1007 }) 1008 } 1009 1010 func TestMatchesTemplateClonedFrom(t *testing.T) { 1011 t.Run("nil machine returns false", func(t *testing.T) { 1012 g := NewWithT(t) 1013 reason, match := matchesTemplateClonedFrom(nil, nil, nil) 1014 g.Expect(match).To(BeFalse()) 1015 g.Expect(reason).To(Equal("Machine cannot be compared with KCP.spec.machineTemplate.infrastructureRef: Machine is nil")) 1016 }) 1017 1018 t.Run("returns true if machine not found", func(t *testing.T) { 1019 g := NewWithT(t) 1020 kcp := &controlplanev1.KubeadmControlPlane{} 1021 machine := &clusterv1.Machine{ 1022 Spec: clusterv1.MachineSpec{ 1023 InfrastructureRef: corev1.ObjectReference{ 1024 Kind: "KubeadmConfig", 1025 Namespace: "default", 1026 Name: "test", 1027 APIVersion: bootstrapv1.GroupVersion.String(), 1028 }, 1029 }, 1030 } 1031 reason, match := matchesTemplateClonedFrom(map[string]*unstructured.Unstructured{}, kcp, machine) 1032 g.Expect(match).To(BeTrue()) 1033 g.Expect(reason).To(BeEmpty()) 1034 }) 1035 1036 t.Run("matches labels or annotations", func(t *testing.T) { 1037 kcp := &controlplanev1.KubeadmControlPlane{ 1038 ObjectMeta: metav1.ObjectMeta{ 1039 Namespace: "default", 1040 }, 1041 Spec: controlplanev1.KubeadmControlPlaneSpec{ 1042 MachineTemplate: controlplanev1.KubeadmControlPlaneMachineTemplate{ 1043 ObjectMeta: clusterv1.ObjectMeta{ 1044 Annotations: map[string]string{ 1045 "test": "annotation", 1046 }, 1047 Labels: map[string]string{ 1048 "test": "labels", 1049 }, 1050 }, 1051 InfrastructureRef: corev1.ObjectReference{ 1052 Kind: "GenericMachineTemplate", 1053 Namespace: "default", 1054 Name: "infra-foo", 1055 APIVersion: "generic.io/v1", 1056 }, 1057 }, 1058 }, 1059 } 1060 m := &clusterv1.Machine{ 1061 Spec: clusterv1.MachineSpec{ 1062 InfrastructureRef: corev1.ObjectReference{ 1063 Kind: "GenericMachine", 1064 Namespace: "default", 1065 Name: "infra-foo", 1066 APIVersion: "generic.io/v1", 1067 }, 1068 }, 1069 } 1070 1071 infraConfigs := map[string]*unstructured.Unstructured{ 1072 m.Name: { 1073 Object: map[string]interface{}{ 1074 "kind": "InfrastructureMachine", 1075 "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", 1076 "metadata": map[string]interface{}{ 1077 "name": "infra-config1", 1078 "namespace": "default", 1079 }, 1080 }, 1081 }, 1082 } 1083 1084 t.Run("by returning true if neither labels or annotations match", func(t *testing.T) { 1085 g := NewWithT(t) 1086 infraConfigs[m.Name].SetAnnotations(map[string]string{ 1087 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1088 clusterv1.TemplateClonedFromGroupKindAnnotation: "GenericMachineTemplate.generic.io", 1089 }) 1090 infraConfigs[m.Name].SetLabels(nil) 1091 reason, match := matchesTemplateClonedFrom(infraConfigs, kcp, m) 1092 g.Expect(match).To(BeTrue()) 1093 g.Expect(reason).To(BeEmpty()) 1094 }) 1095 1096 t.Run("by returning true if only labels don't match", func(t *testing.T) { 1097 g := NewWithT(t) 1098 infraConfigs[m.Name].SetAnnotations(map[string]string{ 1099 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1100 clusterv1.TemplateClonedFromGroupKindAnnotation: "GenericMachineTemplate.generic.io", 1101 "test": "annotation", 1102 }) 1103 infraConfigs[m.Name].SetLabels(nil) 1104 reason, match := matchesTemplateClonedFrom(infraConfigs, kcp, m) 1105 g.Expect(match).To(BeTrue()) 1106 g.Expect(reason).To(BeEmpty()) 1107 }) 1108 1109 t.Run("by returning true if only annotations don't match", func(t *testing.T) { 1110 g := NewWithT(t) 1111 infraConfigs[m.Name].SetAnnotations(map[string]string{ 1112 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1113 clusterv1.TemplateClonedFromGroupKindAnnotation: "GenericMachineTemplate.generic.io", 1114 }) 1115 infraConfigs[m.Name].SetLabels(kcp.Spec.MachineTemplate.ObjectMeta.Labels) 1116 reason, match := matchesTemplateClonedFrom(infraConfigs, kcp, m) 1117 g.Expect(match).To(BeTrue()) 1118 g.Expect(reason).To(BeEmpty()) 1119 }) 1120 1121 t.Run("by returning true if both labels and annotations match", func(t *testing.T) { 1122 g := NewWithT(t) 1123 infraConfigs[m.Name].SetAnnotations(map[string]string{ 1124 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1125 clusterv1.TemplateClonedFromGroupKindAnnotation: "GenericMachineTemplate.generic.io", 1126 "test": "annotation", 1127 }) 1128 infraConfigs[m.Name].SetLabels(kcp.Spec.MachineTemplate.ObjectMeta.Labels) 1129 reason, match := matchesTemplateClonedFrom(infraConfigs, kcp, m) 1130 g.Expect(match).To(BeTrue()) 1131 g.Expect(reason).To(BeEmpty()) 1132 }) 1133 }) 1134 } 1135 1136 func TestMatchesTemplateClonedFrom_WithClonedFromAnnotations(t *testing.T) { 1137 kcp := &controlplanev1.KubeadmControlPlane{ 1138 ObjectMeta: metav1.ObjectMeta{ 1139 Namespace: "default", 1140 }, 1141 Spec: controlplanev1.KubeadmControlPlaneSpec{ 1142 MachineTemplate: controlplanev1.KubeadmControlPlaneMachineTemplate{ 1143 InfrastructureRef: corev1.ObjectReference{ 1144 Kind: "GenericMachineTemplate", 1145 Namespace: "default", 1146 Name: "infra-foo", 1147 APIVersion: "generic.io/v1", 1148 }, 1149 }, 1150 }, 1151 } 1152 machine := &clusterv1.Machine{ 1153 Spec: clusterv1.MachineSpec{ 1154 InfrastructureRef: corev1.ObjectReference{ 1155 APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", 1156 Kind: "InfrastructureMachine", 1157 Name: "infra-config1", 1158 Namespace: "default", 1159 }, 1160 }, 1161 } 1162 tests := []struct { 1163 name string 1164 annotations map[string]interface{} 1165 expectMatch bool 1166 expectReason string 1167 }{ 1168 { 1169 name: "returns true if annotations don't exist", 1170 annotations: map[string]interface{}{}, 1171 expectMatch: true, 1172 }, 1173 { 1174 name: "returns false if annotations don't match anything", 1175 annotations: map[string]interface{}{ 1176 clusterv1.TemplateClonedFromNameAnnotation: "barfoo1", 1177 clusterv1.TemplateClonedFromGroupKindAnnotation: "barfoo2", 1178 }, 1179 expectMatch: false, 1180 expectReason: "Infrastructure template on KCP rotated from barfoo2 barfoo1 to GenericMachineTemplate.generic.io infra-foo", 1181 }, 1182 { 1183 name: "returns false if TemplateClonedFromNameAnnotation matches but TemplateClonedFromGroupKindAnnotation doesn't", 1184 annotations: map[string]interface{}{ 1185 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1186 clusterv1.TemplateClonedFromGroupKindAnnotation: "barfoo2", 1187 }, 1188 expectMatch: false, 1189 expectReason: "Infrastructure template on KCP rotated from barfoo2 infra-foo to GenericMachineTemplate.generic.io infra-foo", 1190 }, 1191 { 1192 name: "returns true if both annotations match", 1193 annotations: map[string]interface{}{ 1194 clusterv1.TemplateClonedFromNameAnnotation: "infra-foo", 1195 clusterv1.TemplateClonedFromGroupKindAnnotation: "GenericMachineTemplate.generic.io", 1196 }, 1197 expectMatch: true, 1198 }, 1199 } 1200 1201 for _, tt := range tests { 1202 t.Run(tt.name, func(t *testing.T) { 1203 g := NewWithT(t) 1204 infraConfigs := map[string]*unstructured.Unstructured{ 1205 machine.Name: { 1206 Object: map[string]interface{}{ 1207 "kind": "InfrastructureMachine", 1208 "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", 1209 "metadata": map[string]interface{}{ 1210 "name": "infra-config1", 1211 "namespace": "default", 1212 "annotations": tt.annotations, 1213 }, 1214 }, 1215 }, 1216 } 1217 reason, match := matchesTemplateClonedFrom(infraConfigs, kcp, machine) 1218 g.Expect(match).To(Equal(tt.expectMatch)) 1219 g.Expect(reason).To(Equal(tt.expectReason)) 1220 }) 1221 } 1222 }