sigs.k8s.io/cluster-api-provider-azure@v1.17.0/api/v1beta1/azuremanagedcontrolplane_webhook_test.go (about) 1 /* 2 Copyright 2023 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 v1beta1 18 19 import ( 20 "context" 21 "testing" 22 23 . "github.com/onsi/gomega" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/util/validation/field" 26 utilfeature "k8s.io/component-base/featuregate/testing" 27 "k8s.io/utils/ptr" 28 "sigs.k8s.io/cluster-api-provider-azure/feature" 29 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 30 capifeature "sigs.k8s.io/cluster-api/feature" 31 ) 32 33 func TestDefaultingWebhook(t *testing.T) { 34 g := NewWithT(t) 35 36 t.Logf("Testing amcp defaulting webhook with no baseline") 37 amcp := &AzureManagedControlPlane{ 38 ObjectMeta: metav1.ObjectMeta{ 39 Name: "fooName", 40 Labels: map[string]string{ 41 clusterv1.ClusterNameLabel: "fooCluster", 42 }, 43 }, 44 Spec: AzureManagedControlPlaneSpec{ 45 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 46 Location: "fooLocation", 47 Version: "1.17.5", 48 Extensions: []AKSExtension{ 49 { 50 Name: "test-extension", 51 Plan: &ExtensionPlan{ 52 Product: "test-product", 53 Publisher: "test-publisher", 54 }, 55 }, 56 }, 57 }, 58 SSHPublicKey: ptr.To(""), 59 }, 60 } 61 mcpw := &azureManagedControlPlaneWebhook{} 62 err := mcpw.Default(context.Background(), amcp) 63 g.Expect(err).NotTo(HaveOccurred()) 64 g.Expect(amcp.Spec.ResourceGroupName).To(Equal("fooCluster")) 65 g.Expect(amcp.Spec.NetworkPlugin).To(Equal(ptr.To(AzureNetworkPluginName))) 66 g.Expect(amcp.Spec.LoadBalancerSKU).To(Equal(ptr.To("Standard"))) 67 g.Expect(amcp.Spec.Version).To(Equal("v1.17.5")) 68 g.Expect(*amcp.Spec.SSHPublicKey).NotTo(BeEmpty()) 69 g.Expect(amcp.Spec.NodeResourceGroupName).To(Equal("MC_fooCluster_fooName_fooLocation")) 70 g.Expect(amcp.Spec.VirtualNetwork.Name).To(Equal("fooName")) 71 g.Expect(amcp.Spec.VirtualNetwork.CIDRBlock).To(Equal(defaultAKSVnetCIDR)) 72 g.Expect(amcp.Spec.VirtualNetwork.Subnet.Name).To(Equal("fooName")) 73 g.Expect(amcp.Spec.VirtualNetwork.Subnet.CIDRBlock).To(Equal(defaultAKSNodeSubnetCIDR)) 74 g.Expect(amcp.Spec.SKU.Tier).To(Equal(FreeManagedControlPlaneTier)) 75 g.Expect(amcp.Spec.Identity.Type).To(Equal(ManagedControlPlaneIdentityTypeSystemAssigned)) 76 g.Expect(*amcp.Spec.OIDCIssuerProfile.Enabled).To(BeFalse()) 77 g.Expect(amcp.Spec.DNSPrefix).NotTo(BeNil()) 78 g.Expect(*amcp.Spec.DNSPrefix).To(Equal(amcp.Name)) 79 g.Expect(amcp.Spec.Extensions[0].Plan.Name).To(Equal("fooName-test-product")) 80 g.Expect(amcp.Spec.EnablePreviewFeatures).NotTo(BeNil()) 81 g.Expect(*amcp.Spec.EnablePreviewFeatures).To(BeFalse()) 82 83 t.Logf("Testing amcp defaulting webhook with baseline") 84 netPlug := "kubenet" 85 netPol := "azure" 86 amcp.Spec.NetworkPlugin = &netPlug 87 amcp.Spec.NetworkPolicy = &netPol 88 amcp.Spec.Version = "9.99.99" 89 amcp.Spec.SSHPublicKey = nil 90 amcp.Spec.ResourceGroupName = "fooRg" 91 amcp.Spec.NodeResourceGroupName = "fooNodeRg" 92 amcp.Spec.VirtualNetwork.Name = "fooVnetName" 93 amcp.Spec.VirtualNetwork.Subnet.Name = "fooSubnetName" 94 amcp.Spec.SKU.Tier = PaidManagedControlPlaneTier 95 amcp.Spec.OIDCIssuerProfile = &OIDCIssuerProfile{ 96 Enabled: ptr.To(true), 97 } 98 amcp.Spec.DNSPrefix = ptr.To("test-prefix") 99 amcp.Spec.FleetsMember = &FleetsMember{} 100 amcp.Spec.AutoUpgradeProfile = &ManagedClusterAutoUpgradeProfile{ 101 UpgradeChannel: ptr.To(UpgradeChannelPatch), 102 } 103 amcp.Spec.SecurityProfile = &ManagedClusterSecurityProfile{ 104 AzureKeyVaultKms: &AzureKeyVaultKms{ 105 Enabled: true, 106 }, 107 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 108 Enabled: true, 109 IntervalHours: ptr.To(48), 110 }, 111 } 112 amcp.Spec.EnablePreviewFeatures = ptr.To(true) 113 114 err = mcpw.Default(context.Background(), amcp) 115 g.Expect(err).NotTo(HaveOccurred()) 116 g.Expect(*amcp.Spec.NetworkPlugin).To(Equal(netPlug)) 117 g.Expect(*amcp.Spec.NetworkPolicy).To(Equal(netPol)) 118 g.Expect(amcp.Spec.Version).To(Equal("v9.99.99")) 119 g.Expect(amcp.Spec.SSHPublicKey).To(BeNil()) 120 g.Expect(amcp.Spec.ResourceGroupName).To(Equal("fooRg")) 121 g.Expect(amcp.Spec.NodeResourceGroupName).To(Equal("fooNodeRg")) 122 g.Expect(amcp.Spec.VirtualNetwork.Name).To(Equal("fooVnetName")) 123 g.Expect(amcp.Spec.VirtualNetwork.Subnet.Name).To(Equal("fooSubnetName")) 124 g.Expect(amcp.Spec.SKU.Tier).To(Equal(StandardManagedControlPlaneTier)) 125 g.Expect(*amcp.Spec.OIDCIssuerProfile.Enabled).To(BeTrue()) 126 g.Expect(amcp.Spec.DNSPrefix).NotTo(BeNil()) 127 g.Expect(*amcp.Spec.DNSPrefix).To(Equal("test-prefix")) 128 g.Expect(amcp.Spec.FleetsMember.Name).To(Equal("fooCluster")) 129 g.Expect(amcp.Spec.AutoUpgradeProfile).NotTo(BeNil()) 130 g.Expect(amcp.Spec.AutoUpgradeProfile.UpgradeChannel).NotTo(BeNil()) 131 g.Expect(*amcp.Spec.AutoUpgradeProfile.UpgradeChannel).To(Equal(UpgradeChannelPatch)) 132 g.Expect(amcp.Spec.SecurityProfile).NotTo(BeNil()) 133 g.Expect(amcp.Spec.SecurityProfile.AzureKeyVaultKms).NotTo(BeNil()) 134 g.Expect(amcp.Spec.SecurityProfile.ImageCleaner).NotTo(BeNil()) 135 g.Expect(amcp.Spec.SecurityProfile.ImageCleaner.IntervalHours).NotTo(BeNil()) 136 g.Expect(*amcp.Spec.SecurityProfile.ImageCleaner.IntervalHours).To(Equal(48)) 137 g.Expect(amcp.Spec.EnablePreviewFeatures).NotTo(BeNil()) 138 g.Expect(*amcp.Spec.EnablePreviewFeatures).To(BeTrue()) 139 140 t.Logf("Testing amcp defaulting webhook with overlay") 141 amcp = &AzureManagedControlPlane{ 142 ObjectMeta: metav1.ObjectMeta{ 143 Name: "fooName", 144 }, 145 Spec: AzureManagedControlPlaneSpec{ 146 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 147 ResourceGroupName: "fooRg", 148 Location: "fooLocation", 149 Version: "1.17.5", 150 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 151 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 152 UpgradeChannel: ptr.To(UpgradeChannelRapid), 153 }, 154 SecurityProfile: &ManagedClusterSecurityProfile{ 155 Defender: &ManagedClusterSecurityProfileDefender{ 156 LogAnalyticsWorkspaceResourceID: "not empty", 157 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 158 Enabled: true, 159 }, 160 }, 161 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 162 Enabled: true, 163 }, 164 }, 165 }, 166 SSHPublicKey: ptr.To(""), 167 }, 168 } 169 err = mcpw.Default(context.Background(), amcp) 170 g.Expect(err).NotTo(HaveOccurred()) 171 g.Expect(amcp.Spec.VirtualNetwork.CIDRBlock).To(Equal(defaultAKSVnetCIDRForOverlay)) 172 g.Expect(amcp.Spec.VirtualNetwork.Subnet.CIDRBlock).To(Equal(defaultAKSNodeSubnetCIDRForOverlay)) 173 g.Expect(amcp.Spec.AutoUpgradeProfile).NotTo(BeNil()) 174 g.Expect(amcp.Spec.AutoUpgradeProfile.UpgradeChannel).NotTo(BeNil()) 175 g.Expect(*amcp.Spec.AutoUpgradeProfile.UpgradeChannel).To(Equal(UpgradeChannelRapid)) 176 } 177 178 func TestValidateVersion(t *testing.T) { 179 tests := []struct { 180 name string 181 version string 182 expectErr bool 183 }{ 184 { 185 name: "Invalid Version", 186 version: "honk", 187 expectErr: true, 188 }, 189 { 190 name: "not following the Kubernetes Version pattern: missing leading v", 191 version: "1.19.0", 192 expectErr: true, 193 }, 194 { 195 name: "Version not set", 196 version: "", 197 expectErr: true, 198 }, 199 { 200 name: "Valid Version", 201 version: "v1.17.8", 202 expectErr: false, 203 }, 204 } 205 206 for _, tt := range tests { 207 tt := tt 208 t.Run(tt.name, func(t *testing.T) { 209 g := NewWithT(t) 210 allErrs := validateVersion(tt.version, field.NewPath("spec").Child("Version")) 211 if tt.expectErr { 212 g.Expect(allErrs).NotTo(BeNil()) 213 } else { 214 g.Expect(allErrs).To(BeNil()) 215 } 216 }) 217 } 218 } 219 220 func TestValidateLoadBalancerProfile(t *testing.T) { 221 tests := []struct { 222 name string 223 profile *LoadBalancerProfile 224 expectedErr field.Error 225 }{ 226 { 227 name: "Valid LoadBalancerProfile", 228 profile: &LoadBalancerProfile{ 229 ManagedOutboundIPs: ptr.To(10), 230 AllocatedOutboundPorts: ptr.To(1000), 231 IdleTimeoutInMinutes: ptr.To(60), 232 }, 233 }, 234 { 235 name: "Invalid LoadBalancerProfile.ManagedOutboundIPs", 236 profile: &LoadBalancerProfile{ 237 ManagedOutboundIPs: ptr.To(200), 238 }, 239 expectedErr: field.Error{ 240 Type: field.ErrorTypeInvalid, 241 Field: "spec.loadBalancerProfile.ManagedOutboundIPs", 242 BadValue: ptr.To(200), 243 Detail: "value should be in between 1 and 100", 244 }, 245 }, 246 { 247 name: "Invalid LoadBalancerProfile.IdleTimeoutInMinutes", 248 profile: &LoadBalancerProfile{ 249 IdleTimeoutInMinutes: ptr.To(600), 250 }, 251 expectedErr: field.Error{ 252 Type: field.ErrorTypeInvalid, 253 Field: "spec.loadBalancerProfile.IdleTimeoutInMinutes", 254 BadValue: ptr.To(600), 255 Detail: "value should be in between 4 and 120", 256 }, 257 }, 258 { 259 name: "LoadBalancerProfile must specify at most one of ManagedOutboundIPs, OutboundIPPrefixes and OutboundIPs", 260 profile: &LoadBalancerProfile{ 261 ManagedOutboundIPs: ptr.To(1), 262 OutboundIPs: []string{ 263 "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo-bar/providers/Microsoft.Network/publicIPAddresses/my-public-ip", 264 }, 265 }, 266 expectedErr: field.Error{ 267 Type: field.ErrorTypeForbidden, 268 Field: "spec.loadBalancerProfile", 269 BadValue: ptr.To(2), 270 Detail: "load balancer profile must specify at most one of ManagedOutboundIPs, OutboundIPPrefixes and OutboundIPs", 271 }, 272 }, 273 } 274 for _, tt := range tests { 275 tt := tt 276 t.Run(tt.name, func(t *testing.T) { 277 g := NewWithT(t) 278 allErrs := validateLoadBalancerProfile(tt.profile, field.NewPath("spec").Child("loadBalancerProfile")) 279 if tt.expectedErr != (field.Error{}) { 280 g.Expect(allErrs).To(ContainElement(MatchError(tt.expectedErr.Error()))) 281 } else { 282 g.Expect(allErrs).To(BeNil()) 283 } 284 }) 285 } 286 } 287 288 func TestValidateAutoScalerProfile(t *testing.T) { 289 tests := []struct { 290 name string 291 profile *AutoScalerProfile 292 expectErr bool 293 }{ 294 { 295 name: "Valid AutoScalerProfile", 296 profile: &AutoScalerProfile{ 297 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsFalse))), 298 Expander: (*Expander)(ptr.To(string(ExpanderRandom))), 299 MaxEmptyBulkDelete: ptr.To("10"), 300 MaxGracefulTerminationSec: ptr.To("600"), 301 MaxNodeProvisionTime: ptr.To("10m"), 302 MaxTotalUnreadyPercentage: ptr.To("45"), 303 NewPodScaleUpDelay: ptr.To("10m"), 304 OkTotalUnreadyCount: ptr.To("3"), 305 ScanInterval: ptr.To("60s"), 306 ScaleDownDelayAfterAdd: ptr.To("10m"), 307 ScaleDownDelayAfterDelete: ptr.To("10s"), 308 ScaleDownDelayAfterFailure: ptr.To("10m"), 309 ScaleDownUnneededTime: ptr.To("10m"), 310 ScaleDownUnreadyTime: ptr.To("10m"), 311 ScaleDownUtilizationThreshold: ptr.To("0.5"), 312 SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(ptr.To(string(SkipNodesWithLocalStorageTrue))), 313 SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(ptr.To(string(SkipNodesWithSystemPodsTrue))), 314 }, 315 expectErr: false, 316 }, 317 { 318 name: "Testing valid AutoScalerProfile.ExpanderRandom", 319 profile: &AutoScalerProfile{ 320 Expander: (*Expander)(ptr.To(string(ExpanderRandom))), 321 }, 322 expectErr: false, 323 }, 324 { 325 name: "Testing valid AutoScalerProfile.ExpanderLeastWaste", 326 profile: &AutoScalerProfile{ 327 Expander: (*Expander)(ptr.To(string(ExpanderLeastWaste))), 328 }, 329 expectErr: false, 330 }, 331 { 332 name: "Testing valid AutoScalerProfile.ExpanderMostPods", 333 profile: &AutoScalerProfile{ 334 Expander: (*Expander)(ptr.To(string(ExpanderMostPods))), 335 }, 336 expectErr: false, 337 }, 338 { 339 name: "Testing valid AutoScalerProfile.ExpanderPriority", 340 profile: &AutoScalerProfile{ 341 Expander: (*Expander)(ptr.To(string(ExpanderPriority))), 342 }, 343 expectErr: false, 344 }, 345 { 346 name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsTrue", 347 profile: &AutoScalerProfile{ 348 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsTrue))), 349 }, 350 expectErr: false, 351 }, 352 { 353 name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsFalse", 354 profile: &AutoScalerProfile{ 355 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsFalse))), 356 }, 357 expectErr: false, 358 }, 359 { 360 name: "Testing invalid AutoScalerProfile.MaxEmptyBulkDelete", 361 profile: &AutoScalerProfile{ 362 MaxEmptyBulkDelete: ptr.To("invalid"), 363 }, 364 expectErr: true, 365 }, 366 { 367 name: "Testing invalid AutoScalerProfile.MaxGracefulTerminationSec", 368 profile: &AutoScalerProfile{ 369 MaxGracefulTerminationSec: ptr.To("invalid"), 370 }, 371 expectErr: true, 372 }, 373 { 374 name: "Testing invalid AutoScalerProfile.MaxNodeProvisionTime", 375 profile: &AutoScalerProfile{ 376 MaxNodeProvisionTime: ptr.To("invalid"), 377 }, 378 expectErr: true, 379 }, 380 { 381 name: "Testing invalid AutoScalerProfile.MaxTotalUnreadyPercentage", 382 profile: &AutoScalerProfile{ 383 MaxTotalUnreadyPercentage: ptr.To("invalid"), 384 }, 385 expectErr: true, 386 }, 387 { 388 name: "Testing invalid AutoScalerProfile.NewPodScaleUpDelay", 389 profile: &AutoScalerProfile{ 390 NewPodScaleUpDelay: ptr.To("invalid"), 391 }, 392 expectErr: true, 393 }, 394 { 395 name: "Testing invalid AutoScalerProfile.OkTotalUnreadyCount", 396 profile: &AutoScalerProfile{ 397 OkTotalUnreadyCount: ptr.To("invalid"), 398 }, 399 expectErr: true, 400 }, 401 { 402 name: "Testing invalid AutoScalerProfile.ScanInterval", 403 profile: &AutoScalerProfile{ 404 ScanInterval: ptr.To("invalid"), 405 }, 406 expectErr: true, 407 }, 408 { 409 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterAdd", 410 profile: &AutoScalerProfile{ 411 ScaleDownDelayAfterAdd: ptr.To("invalid"), 412 }, 413 expectErr: true, 414 }, 415 { 416 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterDelete", 417 profile: &AutoScalerProfile{ 418 ScaleDownDelayAfterDelete: ptr.To("invalid"), 419 }, 420 expectErr: true, 421 }, 422 { 423 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterFailure", 424 profile: &AutoScalerProfile{ 425 ScaleDownDelayAfterFailure: ptr.To("invalid"), 426 }, 427 expectErr: true, 428 }, 429 { 430 name: "Testing invalid AutoScalerProfile.ScaleDownUnneededTime", 431 profile: &AutoScalerProfile{ 432 ScaleDownUnneededTime: ptr.To("invalid"), 433 }, 434 expectErr: true, 435 }, 436 { 437 name: "Testing invalid AutoScalerProfile.ScaleDownUnreadyTime", 438 profile: &AutoScalerProfile{ 439 ScaleDownUnreadyTime: ptr.To("invalid"), 440 }, 441 expectErr: true, 442 }, 443 { 444 name: "Testing invalid AutoScalerProfile.ScaleDownUtilizationThreshold", 445 profile: &AutoScalerProfile{ 446 ScaleDownUtilizationThreshold: ptr.To("invalid"), 447 }, 448 expectErr: true, 449 }, 450 { 451 name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageTrue", 452 profile: &AutoScalerProfile{ 453 SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(ptr.To(string(SkipNodesWithLocalStorageTrue))), 454 }, 455 expectErr: false, 456 }, 457 { 458 name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageFalse", 459 profile: &AutoScalerProfile{ 460 SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(ptr.To(string(SkipNodesWithSystemPodsFalse))), 461 }, 462 expectErr: false, 463 }, 464 } 465 466 for _, tt := range tests { 467 tt := tt 468 t.Run(tt.name, func(t *testing.T) { 469 g := NewWithT(t) 470 allErrs := validateAutoScalerProfile(tt.profile, field.NewPath("spec").Child("autoScalerProfile")) 471 if tt.expectErr { 472 g.Expect(allErrs).NotTo(BeNil()) 473 } else { 474 g.Expect(allErrs).To(BeNil()) 475 } 476 }) 477 } 478 } 479 480 func TestValidatingWebhook(t *testing.T) { 481 tests := []struct { 482 name string 483 amcp AzureManagedControlPlane 484 expectErr bool 485 }{ 486 { 487 name: "Testing valid DNSServiceIP", 488 amcp: AzureManagedControlPlane{ 489 ObjectMeta: getAMCPMetaData(), 490 Spec: AzureManagedControlPlaneSpec{ 491 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 492 DNSServiceIP: ptr.To("192.168.0.10"), 493 Version: "v1.17.8", 494 }, 495 }, 496 }, 497 expectErr: false, 498 }, 499 { 500 name: "Testing invalid DNSServiceIP", 501 amcp: AzureManagedControlPlane{ 502 ObjectMeta: getAMCPMetaData(), 503 Spec: AzureManagedControlPlaneSpec{ 504 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 505 DNSServiceIP: ptr.To("192.168.0.10.3"), 506 Version: "v1.17.8", 507 }, 508 }, 509 }, 510 expectErr: true, 511 }, 512 { 513 name: "Testing invalid DNSServiceIP", 514 amcp: AzureManagedControlPlane{ 515 ObjectMeta: getAMCPMetaData(), 516 Spec: AzureManagedControlPlaneSpec{ 517 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 518 DNSServiceIP: ptr.To("192.168.0.11"), 519 Version: "v1.17.8", 520 }, 521 }, 522 }, 523 expectErr: true, 524 }, 525 { 526 name: "Testing empty DNSServiceIP", 527 amcp: AzureManagedControlPlane{ 528 ObjectMeta: getAMCPMetaData(), 529 Spec: AzureManagedControlPlaneSpec{ 530 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 531 Version: "v1.17.8", 532 }, 533 }, 534 }, 535 expectErr: false, 536 }, 537 { 538 name: "Invalid Version", 539 amcp: AzureManagedControlPlane{ 540 ObjectMeta: getAMCPMetaData(), 541 Spec: AzureManagedControlPlaneSpec{ 542 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 543 DNSServiceIP: ptr.To("192.168.0.10"), 544 Version: "honk", 545 }, 546 }, 547 }, 548 expectErr: true, 549 }, 550 { 551 name: "not following the Kubernetes Version pattern", 552 amcp: AzureManagedControlPlane{ 553 ObjectMeta: getAMCPMetaData(), 554 Spec: AzureManagedControlPlaneSpec{ 555 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 556 DNSServiceIP: ptr.To("192.168.0.10"), 557 Version: "1.19.0", 558 }, 559 }, 560 }, 561 expectErr: true, 562 }, 563 { 564 name: "Version not set", 565 amcp: AzureManagedControlPlane{ 566 ObjectMeta: getAMCPMetaData(), 567 Spec: AzureManagedControlPlaneSpec{ 568 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 569 DNSServiceIP: ptr.To("192.168.0.10"), 570 Version: "", 571 }, 572 }, 573 }, 574 expectErr: true, 575 }, 576 { 577 name: "Valid Version", 578 amcp: AzureManagedControlPlane{ 579 ObjectMeta: getAMCPMetaData(), 580 Spec: AzureManagedControlPlaneSpec{ 581 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 582 DNSServiceIP: ptr.To("192.168.0.10"), 583 Version: "v1.17.8", 584 }, 585 }, 586 }, 587 expectErr: false, 588 }, 589 { 590 name: "Valid Managed AADProfile", 591 amcp: AzureManagedControlPlane{ 592 ObjectMeta: getAMCPMetaData(), 593 Spec: AzureManagedControlPlaneSpec{ 594 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 595 Version: "v1.21.2", 596 AADProfile: &AADProfile{ 597 Managed: true, 598 AdminGroupObjectIDs: []string{ 599 "616077a8-5db7-4c98-b856-b34619afg75h", 600 }, 601 }, 602 }, 603 }, 604 }, 605 expectErr: false, 606 }, 607 { 608 name: "Valid LoadBalancerProfile", 609 amcp: AzureManagedControlPlane{ 610 ObjectMeta: getAMCPMetaData(), 611 Spec: AzureManagedControlPlaneSpec{ 612 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 613 Version: "v1.21.2", 614 LoadBalancerProfile: &LoadBalancerProfile{ 615 ManagedOutboundIPs: ptr.To(10), 616 AllocatedOutboundPorts: ptr.To(1000), 617 IdleTimeoutInMinutes: ptr.To(60), 618 }, 619 }, 620 }, 621 }, 622 expectErr: false, 623 }, 624 { 625 name: "Invalid LoadBalancerProfile.ManagedOutboundIPs", 626 amcp: AzureManagedControlPlane{ 627 ObjectMeta: getAMCPMetaData(), 628 Spec: AzureManagedControlPlaneSpec{ 629 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 630 Version: "v1.21.2", 631 LoadBalancerProfile: &LoadBalancerProfile{ 632 ManagedOutboundIPs: ptr.To(200), 633 }, 634 }, 635 }, 636 }, 637 expectErr: true, 638 }, 639 { 640 name: "Invalid LoadBalancerProfile.AllocatedOutboundPorts", 641 amcp: AzureManagedControlPlane{ 642 ObjectMeta: getAMCPMetaData(), 643 Spec: AzureManagedControlPlaneSpec{ 644 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 645 Version: "v1.21.2", 646 LoadBalancerProfile: &LoadBalancerProfile{ 647 AllocatedOutboundPorts: ptr.To(80000), 648 }, 649 }, 650 }, 651 }, 652 expectErr: true, 653 }, 654 { 655 name: "Invalid LoadBalancerProfile.IdleTimeoutInMinutes", 656 amcp: AzureManagedControlPlane{ 657 ObjectMeta: getAMCPMetaData(), 658 Spec: AzureManagedControlPlaneSpec{ 659 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 660 Version: "v1.21.2", 661 LoadBalancerProfile: &LoadBalancerProfile{ 662 IdleTimeoutInMinutes: ptr.To(600), 663 }, 664 }, 665 }, 666 }, 667 expectErr: true, 668 }, 669 { 670 name: "LoadBalancerProfile must specify at most one of ManagedOutboundIPs, OutboundIPPrefixes and OutboundIPs", 671 amcp: AzureManagedControlPlane{ 672 ObjectMeta: getAMCPMetaData(), 673 Spec: AzureManagedControlPlaneSpec{ 674 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 675 Version: "v1.21.2", 676 LoadBalancerProfile: &LoadBalancerProfile{ 677 ManagedOutboundIPs: ptr.To(1), 678 OutboundIPs: []string{ 679 "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo-bar/providers/Microsoft.Network/publicIPAddresses/my-public-ip", 680 }, 681 }, 682 }, 683 }, 684 }, 685 expectErr: true, 686 }, 687 { 688 name: "Invalid CIDR for AuthorizedIPRanges", 689 amcp: AzureManagedControlPlane{ 690 ObjectMeta: getAMCPMetaData(), 691 Spec: AzureManagedControlPlaneSpec{ 692 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 693 Version: "v1.21.2", 694 APIServerAccessProfile: &APIServerAccessProfile{ 695 AuthorizedIPRanges: []string{"1.2.3.400/32"}, 696 }, 697 }, 698 }, 699 }, 700 expectErr: true, 701 }, 702 { 703 name: "Testing valid AutoScalerProfile", 704 amcp: AzureManagedControlPlane{ 705 ObjectMeta: getAMCPMetaData(), 706 Spec: AzureManagedControlPlaneSpec{ 707 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 708 Version: "v1.24.1", 709 AutoScalerProfile: &AutoScalerProfile{ 710 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsFalse))), 711 Expander: (*Expander)(ptr.To(string(ExpanderRandom))), 712 MaxEmptyBulkDelete: ptr.To("10"), 713 MaxGracefulTerminationSec: ptr.To("600"), 714 MaxNodeProvisionTime: ptr.To("10m"), 715 MaxTotalUnreadyPercentage: ptr.To("45"), 716 NewPodScaleUpDelay: ptr.To("10m"), 717 OkTotalUnreadyCount: ptr.To("3"), 718 ScanInterval: ptr.To("60s"), 719 ScaleDownDelayAfterAdd: ptr.To("10m"), 720 ScaleDownDelayAfterDelete: ptr.To("10s"), 721 ScaleDownDelayAfterFailure: ptr.To("10m"), 722 ScaleDownUnneededTime: ptr.To("10m"), 723 ScaleDownUnreadyTime: ptr.To("10m"), 724 ScaleDownUtilizationThreshold: ptr.To("0.5"), 725 SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(ptr.To(string(SkipNodesWithLocalStorageTrue))), 726 SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(ptr.To(string(SkipNodesWithSystemPodsTrue))), 727 }, 728 }, 729 }, 730 }, 731 expectErr: false, 732 }, 733 { 734 name: "Testing valid AutoScalerProfile.ExpanderRandom", 735 amcp: AzureManagedControlPlane{ 736 ObjectMeta: getAMCPMetaData(), 737 Spec: AzureManagedControlPlaneSpec{ 738 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 739 Version: "v1.24.1", 740 AutoScalerProfile: &AutoScalerProfile{ 741 Expander: (*Expander)(ptr.To(string(ExpanderRandom))), 742 }, 743 }, 744 }, 745 }, 746 expectErr: false, 747 }, 748 { 749 name: "Testing valid AutoScalerProfile.ExpanderLeastWaste", 750 amcp: AzureManagedControlPlane{ 751 ObjectMeta: getAMCPMetaData(), 752 Spec: AzureManagedControlPlaneSpec{ 753 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 754 Version: "v1.24.1", 755 AutoScalerProfile: &AutoScalerProfile{ 756 Expander: (*Expander)(ptr.To(string(ExpanderLeastWaste))), 757 }, 758 }, 759 }, 760 }, 761 expectErr: false, 762 }, 763 { 764 name: "Testing valid AutoScalerProfile.ExpanderMostPods", 765 amcp: AzureManagedControlPlane{ 766 ObjectMeta: getAMCPMetaData(), 767 Spec: AzureManagedControlPlaneSpec{ 768 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 769 Version: "v1.24.1", 770 AutoScalerProfile: &AutoScalerProfile{ 771 Expander: (*Expander)(ptr.To(string(ExpanderMostPods))), 772 }, 773 }, 774 }, 775 }, 776 expectErr: false, 777 }, 778 { 779 name: "Testing valid AutoScalerProfile.ExpanderPriority", 780 amcp: AzureManagedControlPlane{ 781 ObjectMeta: getAMCPMetaData(), 782 Spec: AzureManagedControlPlaneSpec{ 783 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 784 Version: "v1.24.1", 785 AutoScalerProfile: &AutoScalerProfile{ 786 Expander: (*Expander)(ptr.To(string(ExpanderPriority))), 787 }, 788 }, 789 }, 790 }, 791 expectErr: false, 792 }, 793 { 794 name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsTrue", 795 amcp: AzureManagedControlPlane{ 796 ObjectMeta: getAMCPMetaData(), 797 Spec: AzureManagedControlPlaneSpec{ 798 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 799 Version: "v1.24.1", 800 AutoScalerProfile: &AutoScalerProfile{ 801 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsTrue))), 802 }, 803 }, 804 }, 805 }, 806 expectErr: false, 807 }, 808 { 809 name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsFalse", 810 amcp: AzureManagedControlPlane{ 811 ObjectMeta: getAMCPMetaData(), 812 Spec: AzureManagedControlPlaneSpec{ 813 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 814 Version: "v1.24.1", 815 AutoScalerProfile: &AutoScalerProfile{ 816 BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(ptr.To(string(BalanceSimilarNodeGroupsFalse))), 817 }, 818 }, 819 }, 820 }, 821 expectErr: false, 822 }, 823 { 824 name: "Testing invalid AutoScalerProfile.MaxEmptyBulkDelete", 825 amcp: AzureManagedControlPlane{ 826 ObjectMeta: getAMCPMetaData(), 827 Spec: AzureManagedControlPlaneSpec{ 828 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 829 Version: "v1.24.1", 830 AutoScalerProfile: &AutoScalerProfile{ 831 MaxEmptyBulkDelete: ptr.To("invalid"), 832 }, 833 }, 834 }, 835 }, 836 expectErr: true, 837 }, 838 { 839 name: "Testing invalid AutoScalerProfile.MaxGracefulTerminationSec", 840 amcp: AzureManagedControlPlane{ 841 ObjectMeta: getAMCPMetaData(), 842 Spec: AzureManagedControlPlaneSpec{ 843 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 844 Version: "v1.24.1", 845 AutoScalerProfile: &AutoScalerProfile{ 846 MaxGracefulTerminationSec: ptr.To("invalid"), 847 }, 848 }, 849 }, 850 }, 851 expectErr: true, 852 }, 853 { 854 name: "Testing invalid AutoScalerProfile.MaxNodeProvisionTime", 855 amcp: AzureManagedControlPlane{ 856 ObjectMeta: getAMCPMetaData(), 857 Spec: AzureManagedControlPlaneSpec{ 858 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 859 Version: "v1.24.1", 860 AutoScalerProfile: &AutoScalerProfile{ 861 MaxNodeProvisionTime: ptr.To("invalid"), 862 }, 863 }, 864 }, 865 }, 866 expectErr: true, 867 }, 868 { 869 name: "Testing invalid AutoScalerProfile.MaxTotalUnreadyPercentage", 870 amcp: AzureManagedControlPlane{ 871 ObjectMeta: getAMCPMetaData(), 872 Spec: AzureManagedControlPlaneSpec{ 873 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 874 Version: "v1.24.1", 875 AutoScalerProfile: &AutoScalerProfile{ 876 MaxTotalUnreadyPercentage: ptr.To("invalid"), 877 }, 878 }, 879 }, 880 }, 881 expectErr: true, 882 }, 883 { 884 name: "Testing invalid AutoScalerProfile.NewPodScaleUpDelay", 885 amcp: AzureManagedControlPlane{ 886 ObjectMeta: getAMCPMetaData(), 887 Spec: AzureManagedControlPlaneSpec{ 888 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 889 Version: "v1.24.1", 890 AutoScalerProfile: &AutoScalerProfile{ 891 NewPodScaleUpDelay: ptr.To("invalid"), 892 }, 893 }, 894 }, 895 }, 896 expectErr: true, 897 }, 898 { 899 name: "Testing invalid AutoScalerProfile.OkTotalUnreadyCount", 900 amcp: AzureManagedControlPlane{ 901 ObjectMeta: getAMCPMetaData(), 902 Spec: AzureManagedControlPlaneSpec{ 903 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 904 Version: "v1.24.1", 905 AutoScalerProfile: &AutoScalerProfile{ 906 OkTotalUnreadyCount: ptr.To("invalid"), 907 }, 908 }, 909 }, 910 }, 911 expectErr: true, 912 }, 913 { 914 name: "Testing invalid AutoScalerProfile.ScanInterval", 915 amcp: AzureManagedControlPlane{ 916 ObjectMeta: getAMCPMetaData(), 917 Spec: AzureManagedControlPlaneSpec{ 918 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 919 Version: "v1.24.1", 920 AutoScalerProfile: &AutoScalerProfile{ 921 ScanInterval: ptr.To("invalid"), 922 }, 923 }, 924 }, 925 }, 926 expectErr: true, 927 }, 928 { 929 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterAdd", 930 amcp: AzureManagedControlPlane{ 931 ObjectMeta: getAMCPMetaData(), 932 Spec: AzureManagedControlPlaneSpec{ 933 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 934 Version: "v1.24.1", 935 AutoScalerProfile: &AutoScalerProfile{ 936 ScaleDownDelayAfterAdd: ptr.To("invalid"), 937 }, 938 }, 939 }, 940 }, 941 expectErr: true, 942 }, 943 { 944 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterDelete", 945 amcp: AzureManagedControlPlane{ 946 ObjectMeta: getAMCPMetaData(), 947 Spec: AzureManagedControlPlaneSpec{ 948 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 949 Version: "v1.24.1", 950 AutoScalerProfile: &AutoScalerProfile{ 951 ScaleDownDelayAfterDelete: ptr.To("invalid"), 952 }, 953 }, 954 }, 955 }, 956 expectErr: true, 957 }, 958 { 959 name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterFailure", 960 amcp: AzureManagedControlPlane{ 961 ObjectMeta: getAMCPMetaData(), 962 Spec: AzureManagedControlPlaneSpec{ 963 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 964 Version: "v1.24.1", 965 AutoScalerProfile: &AutoScalerProfile{ 966 ScaleDownDelayAfterFailure: ptr.To("invalid"), 967 }, 968 }, 969 }, 970 }, 971 expectErr: true, 972 }, 973 { 974 name: "Testing invalid AutoScalerProfile.ScaleDownUnneededTime", 975 amcp: AzureManagedControlPlane{ 976 ObjectMeta: getAMCPMetaData(), 977 Spec: AzureManagedControlPlaneSpec{ 978 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 979 Version: "v1.24.1", 980 AutoScalerProfile: &AutoScalerProfile{ 981 ScaleDownUnneededTime: ptr.To("invalid"), 982 }, 983 }, 984 }, 985 }, 986 expectErr: true, 987 }, 988 { 989 name: "Testing invalid AutoScalerProfile.ScaleDownUnreadyTime", 990 amcp: AzureManagedControlPlane{ 991 ObjectMeta: getAMCPMetaData(), 992 Spec: AzureManagedControlPlaneSpec{ 993 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 994 Version: "v1.24.1", 995 AutoScalerProfile: &AutoScalerProfile{ 996 ScaleDownUnreadyTime: ptr.To("invalid"), 997 }, 998 }, 999 }, 1000 }, 1001 expectErr: true, 1002 }, 1003 { 1004 name: "Testing invalid AutoScalerProfile.ScaleDownUtilizationThreshold", 1005 amcp: AzureManagedControlPlane{ 1006 ObjectMeta: getAMCPMetaData(), 1007 Spec: AzureManagedControlPlaneSpec{ 1008 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1009 Version: "v1.24.1", 1010 AutoScalerProfile: &AutoScalerProfile{ 1011 ScaleDownUtilizationThreshold: ptr.To("invalid"), 1012 }, 1013 }, 1014 }, 1015 }, 1016 expectErr: true, 1017 }, 1018 { 1019 name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageTrue", 1020 amcp: AzureManagedControlPlane{ 1021 ObjectMeta: getAMCPMetaData(), 1022 Spec: AzureManagedControlPlaneSpec{ 1023 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1024 Version: "v1.24.1", 1025 AutoScalerProfile: &AutoScalerProfile{ 1026 SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(ptr.To(string(SkipNodesWithLocalStorageTrue))), 1027 }, 1028 }, 1029 }, 1030 }, 1031 expectErr: false, 1032 }, 1033 { 1034 name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageFalse", 1035 amcp: AzureManagedControlPlane{ 1036 ObjectMeta: getAMCPMetaData(), 1037 Spec: AzureManagedControlPlaneSpec{ 1038 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1039 Version: "v1.24.1", 1040 AutoScalerProfile: &AutoScalerProfile{ 1041 SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(ptr.To(string(SkipNodesWithLocalStorageFalse))), 1042 }, 1043 }, 1044 }, 1045 }, 1046 expectErr: false, 1047 }, 1048 { 1049 name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsTrue", 1050 amcp: AzureManagedControlPlane{ 1051 ObjectMeta: getAMCPMetaData(), 1052 Spec: AzureManagedControlPlaneSpec{ 1053 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1054 Version: "v1.24.1", 1055 AutoScalerProfile: &AutoScalerProfile{ 1056 SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(ptr.To(string(SkipNodesWithSystemPodsTrue))), 1057 }, 1058 }, 1059 }, 1060 }, 1061 expectErr: false, 1062 }, 1063 { 1064 name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsFalse", 1065 amcp: AzureManagedControlPlane{ 1066 ObjectMeta: getAMCPMetaData(), 1067 Spec: AzureManagedControlPlaneSpec{ 1068 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1069 Version: "v1.24.1", 1070 AutoScalerProfile: &AutoScalerProfile{ 1071 SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(ptr.To(string(SkipNodesWithSystemPodsFalse))), 1072 }, 1073 }, 1074 }, 1075 }, 1076 expectErr: false, 1077 }, 1078 { 1079 name: "Testing valid Identity: SystemAssigned", 1080 amcp: AzureManagedControlPlane{ 1081 ObjectMeta: getAMCPMetaData(), 1082 Spec: AzureManagedControlPlaneSpec{ 1083 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1084 Version: "v1.24.1", 1085 Identity: &Identity{ 1086 Type: ManagedControlPlaneIdentityTypeSystemAssigned, 1087 }, 1088 }, 1089 }, 1090 }, 1091 expectErr: false, 1092 }, 1093 { 1094 name: "Testing valid Identity: UserAssigned", 1095 amcp: AzureManagedControlPlane{ 1096 ObjectMeta: getAMCPMetaData(), 1097 Spec: AzureManagedControlPlaneSpec{ 1098 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1099 Version: "v1.24.1", 1100 Identity: &Identity{ 1101 Type: ManagedControlPlaneIdentityTypeUserAssigned, 1102 UserAssignedIdentityResourceID: "/resource/id", 1103 }, 1104 }, 1105 }, 1106 }, 1107 expectErr: false, 1108 }, 1109 { 1110 name: "Testing invalid Identity: SystemAssigned with UserAssigned values", 1111 amcp: AzureManagedControlPlane{ 1112 ObjectMeta: getAMCPMetaData(), 1113 Spec: AzureManagedControlPlaneSpec{ 1114 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1115 Version: "v1.24.1", 1116 Identity: &Identity{ 1117 Type: ManagedControlPlaneIdentityTypeSystemAssigned, 1118 UserAssignedIdentityResourceID: "/resource/id", 1119 }, 1120 }, 1121 }, 1122 }, 1123 expectErr: true, 1124 }, 1125 { 1126 name: "Testing invalid Identity: UserAssigned with missing properties", 1127 amcp: AzureManagedControlPlane{ 1128 ObjectMeta: getAMCPMetaData(), 1129 Spec: AzureManagedControlPlaneSpec{ 1130 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1131 Version: "v1.24.1", 1132 Identity: &Identity{ 1133 Type: ManagedControlPlaneIdentityTypeUserAssigned, 1134 }, 1135 }, 1136 }, 1137 }, 1138 expectErr: true, 1139 }, 1140 { 1141 name: "overlay cannot be used with kubenet", 1142 amcp: AzureManagedControlPlane{ 1143 ObjectMeta: getAMCPMetaData(), 1144 Spec: AzureManagedControlPlaneSpec{ 1145 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1146 Version: "v1.24.1", 1147 NetworkPlugin: ptr.To("kubenet"), 1148 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 1149 }, 1150 }, 1151 }, 1152 expectErr: true, 1153 }, 1154 { 1155 name: "overlay can be used with azure", 1156 amcp: AzureManagedControlPlane{ 1157 ObjectMeta: getAMCPMetaData(), 1158 Spec: AzureManagedControlPlaneSpec{ 1159 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1160 Version: "v1.24.1", 1161 NetworkPlugin: ptr.To("azure"), 1162 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 1163 }, 1164 }, 1165 }, 1166 expectErr: false, 1167 }, 1168 { 1169 name: "Testing valid AKS Extension", 1170 amcp: AzureManagedControlPlane{ 1171 ObjectMeta: getAMCPMetaData(), 1172 Spec: AzureManagedControlPlaneSpec{ 1173 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1174 Version: "v1.17.8", 1175 Extensions: []AKSExtension{ 1176 { 1177 Name: "extension1", 1178 ExtensionType: ptr.To("test-type"), 1179 Plan: &ExtensionPlan{ 1180 Name: "test-plan", 1181 Product: "test-product", 1182 Publisher: "test-publisher", 1183 }, 1184 }, 1185 }, 1186 }, 1187 }, 1188 }, 1189 expectErr: false, 1190 }, 1191 { 1192 name: "Testing invalid AKS Extension: version given when AutoUpgradeMinorVersion is true", 1193 amcp: AzureManagedControlPlane{ 1194 ObjectMeta: getAMCPMetaData(), 1195 Spec: AzureManagedControlPlaneSpec{ 1196 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1197 Version: "v1.17.8", 1198 Extensions: []AKSExtension{ 1199 { 1200 Name: "extension1", 1201 ExtensionType: ptr.To("test-type"), 1202 Version: ptr.To("1.0.0"), 1203 AutoUpgradeMinorVersion: ptr.To(true), 1204 Plan: &ExtensionPlan{ 1205 Name: "test-plan", 1206 Product: "test-product", 1207 Publisher: "test-publisher", 1208 }, 1209 }, 1210 }, 1211 }, 1212 }, 1213 }, 1214 expectErr: true, 1215 }, 1216 { 1217 name: "Testing invalid AKS Extension: missing plan.product and plan.publisher", 1218 amcp: AzureManagedControlPlane{ 1219 ObjectMeta: getAMCPMetaData(), 1220 Spec: AzureManagedControlPlaneSpec{ 1221 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1222 Version: "v1.17.8", 1223 Extensions: []AKSExtension{ 1224 { 1225 Name: "extension1", 1226 ExtensionType: ptr.To("test-type"), 1227 Version: ptr.To("1.0.0"), 1228 AutoUpgradeMinorVersion: ptr.To(true), 1229 Plan: &ExtensionPlan{ 1230 Name: "test-plan", 1231 }, 1232 }, 1233 }, 1234 }, 1235 }, 1236 }, 1237 expectErr: true, 1238 }, 1239 { 1240 name: "Test invalid AzureKeyVaultKms", 1241 amcp: AzureManagedControlPlane{ 1242 Spec: AzureManagedControlPlaneSpec{ 1243 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1244 Version: "v1.17.8", 1245 SecurityProfile: &ManagedClusterSecurityProfile{ 1246 AzureKeyVaultKms: &AzureKeyVaultKms{ 1247 Enabled: true, 1248 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 1249 }, 1250 }, 1251 }, 1252 }, 1253 }, 1254 expectErr: true, 1255 }, 1256 { 1257 name: "Valid NetworkDataplane: cilium", 1258 amcp: AzureManagedControlPlane{ 1259 ObjectMeta: getAMCPMetaData(), 1260 Spec: AzureManagedControlPlaneSpec{ 1261 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1262 Version: "v1.17.8", 1263 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 1264 NetworkDataplane: ptr.To(NetworkDataplaneTypeCilium), 1265 NetworkPolicy: ptr.To("cilium"), 1266 }, 1267 }, 1268 }, 1269 expectErr: false, 1270 }, 1271 { 1272 name: "Testing invalid NetworkDataplane: cilium dataplane requires overlay network plugin mode", 1273 amcp: AzureManagedControlPlane{ 1274 ObjectMeta: getAMCPMetaData(), 1275 Spec: AzureManagedControlPlaneSpec{ 1276 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1277 Version: "v1.17.8", 1278 NetworkPluginMode: nil, 1279 NetworkDataplane: ptr.To(NetworkDataplaneTypeCilium), 1280 NetworkPolicy: ptr.To("cilium"), 1281 }, 1282 }, 1283 }, 1284 expectErr: true, 1285 }, 1286 { 1287 name: "Test valid AzureKeyVaultKms", 1288 amcp: AzureManagedControlPlane{ 1289 Spec: AzureManagedControlPlaneSpec{ 1290 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1291 Version: "v1.17.8", 1292 Identity: &Identity{ 1293 Type: ManagedControlPlaneIdentityTypeUserAssigned, 1294 UserAssignedIdentityResourceID: "not empty", 1295 }, 1296 SecurityProfile: &ManagedClusterSecurityProfile{ 1297 AzureKeyVaultKms: &AzureKeyVaultKms{ 1298 Enabled: true, 1299 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 1300 KeyVaultResourceID: ptr.To("0000-0000-0000-000"), 1301 }, 1302 }, 1303 }, 1304 }, 1305 }, 1306 expectErr: false, 1307 }, 1308 { 1309 name: "Test valid AzureKeyVaultKms", 1310 amcp: AzureManagedControlPlane{ 1311 Spec: AzureManagedControlPlaneSpec{ 1312 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1313 Version: "v1.17.8", 1314 Identity: &Identity{ 1315 Type: ManagedControlPlaneIdentityTypeUserAssigned, 1316 UserAssignedIdentityResourceID: "not empty", 1317 }, 1318 SecurityProfile: &ManagedClusterSecurityProfile{ 1319 AzureKeyVaultKms: &AzureKeyVaultKms{ 1320 Enabled: true, 1321 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 1322 }, 1323 }, 1324 }, 1325 }, 1326 }, 1327 expectErr: false, 1328 }, 1329 { 1330 name: "Testing invalid NetworkDataplane: cilium dataplane requires network policy to be cilium", 1331 amcp: AzureManagedControlPlane{ 1332 ObjectMeta: getAMCPMetaData(), 1333 Spec: AzureManagedControlPlaneSpec{ 1334 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1335 Version: "v1.17.8", 1336 NetworkPluginMode: nil, 1337 NetworkDataplane: ptr.To(NetworkDataplaneTypeCilium), 1338 NetworkPolicy: ptr.To("azure"), 1339 }, 1340 }, 1341 }, 1342 expectErr: true, 1343 }, 1344 { 1345 name: "Testing invalid NetworkPolicy: cilium network policy can only be used with cilium network dataplane", 1346 amcp: AzureManagedControlPlane{ 1347 ObjectMeta: getAMCPMetaData(), 1348 Spec: AzureManagedControlPlaneSpec{ 1349 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1350 Version: "v1.17.8", 1351 NetworkPluginMode: nil, 1352 NetworkDataplane: ptr.To(NetworkDataplaneTypeAzure), 1353 NetworkPolicy: ptr.To("cilium"), 1354 }, 1355 }, 1356 }, 1357 expectErr: true, 1358 }, 1359 { 1360 name: "Testing valid FleetsMember", 1361 amcp: AzureManagedControlPlane{ 1362 ObjectMeta: getAMCPMetaData(), 1363 Spec: AzureManagedControlPlaneSpec{ 1364 FleetsMember: &FleetsMember{ 1365 Name: "fleetmember1", 1366 }, 1367 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1368 Version: "v1.17.8", 1369 }, 1370 }, 1371 }, 1372 expectErr: false, 1373 }, 1374 { 1375 name: "Testing invalid FleetsMember: Fleets member name cannot contain capital letters", 1376 amcp: AzureManagedControlPlane{ 1377 ObjectMeta: getAMCPMetaData(), 1378 Spec: AzureManagedControlPlaneSpec{ 1379 FleetsMember: &FleetsMember{ 1380 Name: "FleetMember1", 1381 }, 1382 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1383 Version: "v1.17.8", 1384 }, 1385 }, 1386 }, 1387 expectErr: true, 1388 }, 1389 } 1390 1391 for _, tt := range tests { 1392 tt := tt 1393 // client is used to fetch the AzureManagedControlPlane, we do not want to return an error on client.Get 1394 client := mockClient{ReturnError: false} 1395 t.Run(tt.name, func(t *testing.T) { 1396 g := NewWithT(t) 1397 mcpw := &azureManagedControlPlaneWebhook{ 1398 Client: client, 1399 } 1400 _, err := mcpw.ValidateCreate(context.Background(), &tt.amcp) 1401 if tt.expectErr { 1402 g.Expect(err).To(HaveOccurred()) 1403 } else { 1404 g.Expect(err).NotTo(HaveOccurred()) 1405 } 1406 }) 1407 } 1408 } 1409 1410 func TestAzureManagedControlPlane_ValidateCreate(t *testing.T) { 1411 tests := []struct { 1412 name string 1413 amcp *AzureManagedControlPlane 1414 wantErr bool 1415 errorLen int 1416 }{ 1417 { 1418 name: "all valid", 1419 amcp: getKnownValidAzureManagedControlPlane(), 1420 wantErr: false, 1421 }, 1422 { 1423 name: "invalid DNSServiceIP", 1424 amcp: createAzureManagedControlPlane("192.168.0.10.3", "v1.18.0", generateSSHPublicKey(true)), 1425 wantErr: true, 1426 errorLen: 1, 1427 }, 1428 { 1429 name: "invalid DNSServiceIP", 1430 amcp: createAzureManagedControlPlane("192.168.0.11", "v1.18.0", generateSSHPublicKey(true)), 1431 wantErr: true, 1432 errorLen: 1, 1433 }, 1434 { 1435 name: "invalid sshKey", 1436 amcp: createAzureManagedControlPlane("192.168.0.10", "v1.18.0", generateSSHPublicKey(false)), 1437 wantErr: true, 1438 errorLen: 1, 1439 }, 1440 { 1441 name: "invalid sshKey with a simple text and invalid DNSServiceIP", 1442 amcp: createAzureManagedControlPlane("192.168.0.10.3", "v1.18.0", "invalid_sshkey_honk"), 1443 wantErr: true, 1444 errorLen: 2, 1445 }, 1446 { 1447 name: "invalid version", 1448 amcp: createAzureManagedControlPlane("192.168.0.10", "honk.version", generateSSHPublicKey(true)), 1449 wantErr: true, 1450 errorLen: 1, 1451 }, 1452 { 1453 name: "Testing inValid DNSPrefix for starting with invalid characters", 1454 amcp: &AzureManagedControlPlane{ 1455 Spec: AzureManagedControlPlaneSpec{ 1456 DNSPrefix: ptr.To("-thisi$"), 1457 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1458 Version: "v1.17.8", 1459 }, 1460 }, 1461 }, 1462 wantErr: true, 1463 }, 1464 { 1465 name: "Testing inValid DNSPrefix with more then 54 characters", 1466 amcp: &AzureManagedControlPlane{ 1467 Spec: AzureManagedControlPlaneSpec{ 1468 DNSPrefix: ptr.To("thisisaverylong$^clusternameconsistingofmorethan54characterswhichshouldbeinvalid"), 1469 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1470 Version: "v1.17.8", 1471 }, 1472 }, 1473 }, 1474 wantErr: true, 1475 }, 1476 { 1477 name: "Testing inValid DNSPrefix with underscore", 1478 amcp: &AzureManagedControlPlane{ 1479 Spec: AzureManagedControlPlaneSpec{ 1480 DNSPrefix: ptr.To("no_underscore"), 1481 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1482 Version: "v1.17.8", 1483 }, 1484 }, 1485 }, 1486 wantErr: true, 1487 }, 1488 { 1489 name: "Testing inValid DNSPrefix with special characters", 1490 amcp: &AzureManagedControlPlane{ 1491 Spec: AzureManagedControlPlaneSpec{ 1492 DNSPrefix: ptr.To("no-dollar$@%"), 1493 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1494 Version: "v1.17.8", 1495 }, 1496 }, 1497 }, 1498 wantErr: true, 1499 }, 1500 { 1501 name: "Testing Valid DNSPrefix with hyphen characters", 1502 amcp: &AzureManagedControlPlane{ 1503 Spec: AzureManagedControlPlaneSpec{ 1504 DNSPrefix: ptr.To("hyphen-allowed"), 1505 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1506 Version: "v1.17.8", 1507 }, 1508 }, 1509 }, 1510 wantErr: false, 1511 }, 1512 { 1513 name: "Testing Valid DNSPrefix with hyphen characters", 1514 amcp: &AzureManagedControlPlane{ 1515 Spec: AzureManagedControlPlaneSpec{ 1516 DNSPrefix: ptr.To("palette-test07"), 1517 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1518 Version: "v1.17.8", 1519 }, 1520 }, 1521 }, 1522 wantErr: false, 1523 }, 1524 { 1525 name: "Testing valid DNSPrefix ", 1526 amcp: &AzureManagedControlPlane{ 1527 Spec: AzureManagedControlPlaneSpec{ 1528 DNSPrefix: ptr.To("thisisavlerylongclu7l0sternam3leconsistingofmorethan54"), 1529 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1530 Version: "v1.17.8", 1531 }, 1532 }, 1533 }, 1534 wantErr: false, 1535 }, 1536 { 1537 name: "invalid name with microsoft", 1538 amcp: &AzureManagedControlPlane{ 1539 ObjectMeta: metav1.ObjectMeta{ 1540 Name: "microsoft-cluster", 1541 }, 1542 Spec: AzureManagedControlPlaneSpec{ 1543 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 1544 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1545 DNSServiceIP: ptr.To("192.168.0.10"), 1546 Version: "v1.23.5", 1547 }, 1548 }, 1549 }, 1550 wantErr: true, 1551 errorLen: 1, 1552 }, 1553 { 1554 name: "invalid name with windows", 1555 amcp: &AzureManagedControlPlane{ 1556 ObjectMeta: metav1.ObjectMeta{ 1557 Name: "a-windows-cluster", 1558 }, 1559 Spec: AzureManagedControlPlaneSpec{ 1560 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 1561 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1562 DNSServiceIP: ptr.To("192.168.0.10"), 1563 Version: "v1.23.5", 1564 }, 1565 }, 1566 }, 1567 wantErr: true, 1568 errorLen: 1, 1569 }, 1570 { 1571 name: "set Spec.ControlPlaneEndpoint.Host during create (clusterctl move scenario)", 1572 amcp: &AzureManagedControlPlane{ 1573 Spec: AzureManagedControlPlaneSpec{ 1574 ControlPlaneEndpoint: clusterv1.APIEndpoint{ 1575 Host: "my-host", 1576 }, 1577 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 1578 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1579 DNSServiceIP: ptr.To("192.168.0.10"), 1580 Version: "v1.18.0", 1581 AADProfile: &AADProfile{ 1582 Managed: true, 1583 AdminGroupObjectIDs: []string{ 1584 "616077a8-5db7-4c98-b856-b34619afg75h", 1585 }, 1586 }, 1587 }, 1588 }, 1589 }, 1590 wantErr: false, 1591 }, 1592 { 1593 name: "can set Spec.ControlPlaneEndpoint.Port during create (clusterctl move scenario)", 1594 amcp: &AzureManagedControlPlane{ 1595 Spec: AzureManagedControlPlaneSpec{ 1596 ControlPlaneEndpoint: clusterv1.APIEndpoint{ 1597 Port: 444, 1598 }, 1599 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 1600 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1601 DNSServiceIP: ptr.To("192.168.0.10"), 1602 Version: "v1.18.0", 1603 AADProfile: &AADProfile{ 1604 Managed: true, 1605 AdminGroupObjectIDs: []string{ 1606 "616077a8-5db7-4c98-b856-b34619afg75h", 1607 }, 1608 }, 1609 }, 1610 }, 1611 }, 1612 wantErr: false, 1613 }, 1614 { 1615 name: "DisableLocalAccounts cannot be set for non AAD clusters", 1616 amcp: &AzureManagedControlPlane{ 1617 Spec: AzureManagedControlPlaneSpec{ 1618 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1619 Version: "v1.21.2", 1620 DisableLocalAccounts: ptr.To[bool](true), 1621 }, 1622 }, 1623 }, 1624 wantErr: true, 1625 }, 1626 { 1627 name: "DisableLocalAccounts can be set for AAD clusters", 1628 amcp: &AzureManagedControlPlane{ 1629 Spec: AzureManagedControlPlaneSpec{ 1630 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1631 Version: "v1.21.2", 1632 AADProfile: &AADProfile{ 1633 Managed: true, 1634 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 1635 }, 1636 DisableLocalAccounts: ptr.To[bool](true), 1637 }, 1638 }, 1639 }, 1640 wantErr: false, 1641 }, 1642 } 1643 client := mockClient{ReturnError: false} 1644 for _, tc := range tests { 1645 t.Run(tc.name, func(t *testing.T) { 1646 g := NewWithT(t) 1647 mcpw := &azureManagedControlPlaneWebhook{ 1648 Client: client, 1649 } 1650 _, err := mcpw.ValidateCreate(context.Background(), tc.amcp) 1651 if tc.wantErr { 1652 g.Expect(err).To(HaveOccurred()) 1653 if tc.errorLen > 0 { 1654 g.Expect(err).To(HaveLen(tc.errorLen)) 1655 } 1656 } else { 1657 g.Expect(err).NotTo(HaveOccurred()) 1658 } 1659 }) 1660 } 1661 } 1662 1663 func TestAzureManagedControlPlane_ValidateCreateFailure(t *testing.T) { 1664 tests := []struct { 1665 name string 1666 amcp *AzureManagedControlPlane 1667 featureGateEnabled *bool 1668 expectError bool 1669 }{ 1670 { 1671 name: "feature gate explicitly disabled", 1672 amcp: getKnownValidAzureManagedControlPlane(), 1673 featureGateEnabled: ptr.To(false), 1674 expectError: true, 1675 }, 1676 { 1677 name: "feature gate implicitly enabled", 1678 amcp: getKnownValidAzureManagedControlPlane(), 1679 featureGateEnabled: nil, 1680 expectError: false, 1681 }, 1682 } 1683 client := mockClient{ReturnError: false} 1684 for _, tc := range tests { 1685 t.Run(tc.name, func(t *testing.T) { 1686 g := NewWithT(t) 1687 if tc.featureGateEnabled != nil { 1688 defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, capifeature.MachinePool, *tc.featureGateEnabled)() 1689 } 1690 mcpw := &azureManagedControlPlaneWebhook{ 1691 Client: client, 1692 } 1693 _, err := mcpw.ValidateCreate(context.Background(), tc.amcp) 1694 if tc.expectError { 1695 g.Expect(err).To(HaveOccurred()) 1696 } else { 1697 g.Expect(err).NotTo(HaveOccurred()) 1698 } 1699 }) 1700 } 1701 } 1702 1703 func TestAzureManagedControlPlane_ValidateUpdate(t *testing.T) { 1704 commonSSHKey := generateSSHPublicKey(true) 1705 tests := []struct { 1706 name string 1707 oldAMCP *AzureManagedControlPlane 1708 amcp *AzureManagedControlPlane 1709 wantErr bool 1710 }{ 1711 { 1712 name: "can't add a SSHPublicKey to an existing AzureManagedControlPlane", 1713 oldAMCP: createAzureManagedControlPlane("192.168.0.10", "v1.18.0", ""), 1714 amcp: createAzureManagedControlPlane("192.168.0.10", "v1.18.0", generateSSHPublicKey(true)), 1715 wantErr: true, 1716 }, 1717 { 1718 name: "same SSHPublicKey is valid", 1719 oldAMCP: createAzureManagedControlPlane("192.168.0.10", "v1.18.0", commonSSHKey), 1720 amcp: createAzureManagedControlPlane("192.168.0.10", "v1.18.0", commonSSHKey), 1721 wantErr: false, 1722 }, 1723 { 1724 name: "AzureManagedControlPlane with invalid serviceIP", 1725 oldAMCP: createAzureManagedControlPlane("", "v1.18.0", ""), 1726 amcp: createAzureManagedControlPlane("192.168.0.10.3", "v1.18.0", generateSSHPublicKey(true)), 1727 wantErr: true, 1728 }, 1729 { 1730 name: "AzureManagedControlPlane with invalid serviceIP", 1731 oldAMCP: createAzureManagedControlPlane("", "v1.18.0", ""), 1732 amcp: createAzureManagedControlPlane("192.168.0.11", "v1.18.0", generateSSHPublicKey(true)), 1733 wantErr: true, 1734 }, 1735 { 1736 name: "AzureManagedControlPlane with invalid version", 1737 oldAMCP: createAzureManagedControlPlane("", "v1.18.0", ""), 1738 amcp: createAzureManagedControlPlane("192.168.0.10", "1.999.9", generateSSHPublicKey(true)), 1739 wantErr: true, 1740 }, 1741 { 1742 name: "AzureManagedControlPlane AddonProfiles is mutable", 1743 oldAMCP: &AzureManagedControlPlane{ 1744 Spec: AzureManagedControlPlaneSpec{ 1745 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1746 Version: "v1.18.0", 1747 }, 1748 }, 1749 }, 1750 amcp: &AzureManagedControlPlane{ 1751 Spec: AzureManagedControlPlaneSpec{ 1752 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1753 Version: "v1.18.0", 1754 AddonProfiles: []AddonProfile{ 1755 { 1756 Name: "first-addon-profile", 1757 Enabled: true, 1758 }, 1759 }, 1760 }, 1761 }, 1762 }, 1763 wantErr: false, 1764 }, 1765 { 1766 name: "AzureManagedControlPlane AddonProfiles can be disabled", 1767 oldAMCP: &AzureManagedControlPlane{ 1768 Spec: AzureManagedControlPlaneSpec{ 1769 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1770 AddonProfiles: []AddonProfile{ 1771 { 1772 Name: "first-addon-profile", 1773 Enabled: true, 1774 }, 1775 }, 1776 Version: "v1.18.0", 1777 }, 1778 }, 1779 }, 1780 amcp: &AzureManagedControlPlane{ 1781 Spec: AzureManagedControlPlaneSpec{ 1782 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1783 Version: "v1.18.0", 1784 AddonProfiles: []AddonProfile{ 1785 { 1786 Name: "first-addon-profile", 1787 Enabled: false, 1788 }, 1789 }, 1790 }, 1791 }, 1792 }, 1793 wantErr: false, 1794 }, 1795 { 1796 name: "AzureManagedControlPlane AddonProfiles cannot update to empty array", 1797 oldAMCP: &AzureManagedControlPlane{ 1798 Spec: AzureManagedControlPlaneSpec{ 1799 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1800 AddonProfiles: []AddonProfile{ 1801 { 1802 Name: "first-addon-profile", 1803 Enabled: true, 1804 }, 1805 }, 1806 Version: "v1.18.0", 1807 }, 1808 }, 1809 }, 1810 amcp: &AzureManagedControlPlane{ 1811 Spec: AzureManagedControlPlaneSpec{ 1812 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1813 Version: "v1.18.0", 1814 }, 1815 }, 1816 }, 1817 wantErr: true, 1818 }, 1819 { 1820 name: "AzureManagedControlPlane AddonProfiles cannot be completely removed", 1821 oldAMCP: &AzureManagedControlPlane{ 1822 Spec: AzureManagedControlPlaneSpec{ 1823 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1824 AddonProfiles: []AddonProfile{ 1825 { 1826 Name: "first-addon-profile", 1827 Enabled: true, 1828 }, 1829 { 1830 Name: "second-addon-profile", 1831 Enabled: true, 1832 }, 1833 }, 1834 Version: "v1.18.0", 1835 }, 1836 }, 1837 }, 1838 amcp: &AzureManagedControlPlane{ 1839 Spec: AzureManagedControlPlaneSpec{ 1840 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1841 AddonProfiles: []AddonProfile{ 1842 { 1843 Name: "first-addon-profile", 1844 Enabled: true, 1845 }, 1846 }, 1847 Version: "v1.18.0", 1848 }, 1849 }, 1850 }, 1851 wantErr: true, 1852 }, 1853 { 1854 name: "AzureManagedControlPlane invalid version downgrade change", 1855 oldAMCP: &AzureManagedControlPlane{ 1856 Spec: AzureManagedControlPlaneSpec{ 1857 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1858 Version: "v1.18.0", 1859 }, 1860 }, 1861 }, 1862 amcp: &AzureManagedControlPlane{ 1863 Spec: AzureManagedControlPlaneSpec{ 1864 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1865 Version: "v1.17.0", 1866 }, 1867 }, 1868 }, 1869 wantErr: true, 1870 }, 1871 { 1872 name: "AzureManagedControlPlane invalid version downgrade change", 1873 oldAMCP: &AzureManagedControlPlane{ 1874 Spec: AzureManagedControlPlaneSpec{ 1875 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1876 Version: "v1.18.0", 1877 }, 1878 }, 1879 Status: AzureManagedControlPlaneStatus{ 1880 AutoUpgradeVersion: "v1.18.3", 1881 }, 1882 }, 1883 amcp: &AzureManagedControlPlane{ 1884 Spec: AzureManagedControlPlaneSpec{ 1885 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1886 Version: "v1.18.1", 1887 }, 1888 }, 1889 }, 1890 wantErr: true, 1891 }, 1892 { 1893 name: "AzureManagedControlPlane Autoupgrade cannot be set to nil", 1894 oldAMCP: &AzureManagedControlPlane{ 1895 Spec: AzureManagedControlPlaneSpec{ 1896 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1897 DNSServiceIP: ptr.To("192.168.0.10"), 1898 SubscriptionID: "212ec1q8", 1899 Version: "v1.18.0", 1900 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 1901 UpgradeChannel: ptr.To(UpgradeChannelStable), 1902 }, 1903 }, 1904 }, 1905 }, 1906 amcp: &AzureManagedControlPlane{ 1907 Spec: AzureManagedControlPlaneSpec{ 1908 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1909 DNSServiceIP: ptr.To("192.168.0.10"), 1910 SubscriptionID: "212ec1q8", 1911 Version: "v1.18.0", 1912 }, 1913 }, 1914 }, 1915 wantErr: true, 1916 }, 1917 { 1918 name: "AzureManagedControlPlane Autoupgrade cannot be set to nil", 1919 oldAMCP: &AzureManagedControlPlane{ 1920 Spec: AzureManagedControlPlaneSpec{ 1921 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1922 DNSServiceIP: ptr.To("192.168.0.10"), 1923 SubscriptionID: "212ec1q8", 1924 Version: "v1.18.0", 1925 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 1926 UpgradeChannel: ptr.To(UpgradeChannelStable), 1927 }, 1928 }, 1929 }, 1930 }, 1931 amcp: &AzureManagedControlPlane{ 1932 Spec: AzureManagedControlPlaneSpec{ 1933 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1934 DNSServiceIP: ptr.To("192.168.0.10"), 1935 SubscriptionID: "212ec1q8", 1936 Version: "v1.18.0", 1937 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{}, 1938 }, 1939 }, 1940 }, 1941 wantErr: true, 1942 }, 1943 { 1944 name: "AzureManagedControlPlane Autoupgrade is mutable", 1945 oldAMCP: &AzureManagedControlPlane{ 1946 Spec: AzureManagedControlPlaneSpec{ 1947 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1948 DNSServiceIP: ptr.To("192.168.0.10"), 1949 SubscriptionID: "212ec1q8", 1950 Version: "v1.18.0", 1951 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 1952 UpgradeChannel: ptr.To(UpgradeChannelStable), 1953 }, 1954 }, 1955 }, 1956 }, 1957 amcp: &AzureManagedControlPlane{ 1958 Spec: AzureManagedControlPlaneSpec{ 1959 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1960 DNSServiceIP: ptr.To("192.168.0.10"), 1961 SubscriptionID: "212ec1q8", 1962 Version: "v1.18.0", 1963 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 1964 UpgradeChannel: ptr.To(UpgradeChannelNone), 1965 }, 1966 }, 1967 }, 1968 }, 1969 wantErr: false, 1970 }, 1971 { 1972 name: "AzureManagedControlPlane SubscriptionID is immutable", 1973 oldAMCP: &AzureManagedControlPlane{ 1974 Spec: AzureManagedControlPlaneSpec{ 1975 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1976 DNSServiceIP: ptr.To("192.168.0.10"), 1977 SubscriptionID: "212ec1q8", 1978 Version: "v1.18.0", 1979 }, 1980 }, 1981 }, 1982 amcp: &AzureManagedControlPlane{ 1983 Spec: AzureManagedControlPlaneSpec{ 1984 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1985 DNSServiceIP: ptr.To("192.168.0.10"), 1986 SubscriptionID: "212ec1q9", 1987 Version: "v1.18.0", 1988 }, 1989 }, 1990 }, 1991 wantErr: true, 1992 }, 1993 { 1994 name: "AzureManagedControlPlane ResourceGroupName is immutable", 1995 oldAMCP: &AzureManagedControlPlane{ 1996 Spec: AzureManagedControlPlaneSpec{ 1997 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 1998 DNSServiceIP: ptr.To("192.168.0.10"), 1999 Version: "v1.18.0", 2000 ResourceGroupName: "hello-1", 2001 }, 2002 }, 2003 }, 2004 amcp: &AzureManagedControlPlane{ 2005 Spec: AzureManagedControlPlaneSpec{ 2006 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2007 DNSServiceIP: ptr.To("192.168.0.10"), 2008 Version: "v1.18.0", 2009 ResourceGroupName: "hello-2", 2010 }, 2011 }, 2012 }, 2013 wantErr: true, 2014 }, 2015 { 2016 name: "AzureManagedControlPlane NodeResourceGroupName is immutable", 2017 oldAMCP: &AzureManagedControlPlane{ 2018 Spec: AzureManagedControlPlaneSpec{ 2019 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2020 DNSServiceIP: ptr.To("192.168.0.10"), 2021 Version: "v1.18.0", 2022 }, 2023 NodeResourceGroupName: "hello-1", 2024 }, 2025 }, 2026 amcp: &AzureManagedControlPlane{ 2027 Spec: AzureManagedControlPlaneSpec{ 2028 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2029 DNSServiceIP: ptr.To("192.168.0.10"), 2030 Version: "v1.18.0", 2031 }, 2032 NodeResourceGroupName: "hello-2", 2033 }, 2034 }, 2035 wantErr: true, 2036 }, 2037 { 2038 name: "AzureManagedControlPlane Location is immutable", 2039 oldAMCP: &AzureManagedControlPlane{ 2040 Spec: AzureManagedControlPlaneSpec{ 2041 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2042 DNSServiceIP: ptr.To("192.168.0.10"), 2043 Location: "westeurope", 2044 Version: "v1.18.0", 2045 }, 2046 }, 2047 }, 2048 amcp: &AzureManagedControlPlane{ 2049 Spec: AzureManagedControlPlaneSpec{ 2050 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2051 DNSServiceIP: ptr.To("192.168.0.10"), 2052 Location: "eastus", 2053 Version: "v1.18.0", 2054 }, 2055 }, 2056 }, 2057 wantErr: true, 2058 }, 2059 { 2060 name: "AzureManagedControlPlane SSHPublicKey is immutable", 2061 oldAMCP: &AzureManagedControlPlane{ 2062 Spec: AzureManagedControlPlaneSpec{ 2063 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2064 DNSServiceIP: ptr.To("192.168.0.10"), 2065 Version: "v1.18.0", 2066 }, 2067 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 2068 }, 2069 }, 2070 amcp: &AzureManagedControlPlane{ 2071 Spec: AzureManagedControlPlaneSpec{ 2072 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2073 DNSServiceIP: ptr.To("192.168.0.10"), 2074 Version: "v1.18.0", 2075 }, 2076 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 2077 }, 2078 }, 2079 wantErr: true, 2080 }, 2081 { 2082 name: "AzureManagedControlPlane DNSServiceIP is immutable", 2083 oldAMCP: &AzureManagedControlPlane{ 2084 Spec: AzureManagedControlPlaneSpec{ 2085 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2086 DNSServiceIP: ptr.To("192.168.0.10"), 2087 Version: "v1.18.0", 2088 }, 2089 }, 2090 }, 2091 amcp: &AzureManagedControlPlane{ 2092 Spec: AzureManagedControlPlaneSpec{ 2093 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2094 DNSServiceIP: ptr.To("192.168.1.1"), 2095 Version: "v1.18.0", 2096 }, 2097 }, 2098 }, 2099 wantErr: true, 2100 }, 2101 { 2102 name: "AzureManagedControlPlane DNSServiceIP is immutable, unsetting is not allowed", 2103 oldAMCP: &AzureManagedControlPlane{ 2104 Spec: AzureManagedControlPlaneSpec{ 2105 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2106 DNSServiceIP: ptr.To("192.168.0.10"), 2107 Version: "v1.18.0", 2108 }, 2109 }, 2110 }, 2111 amcp: &AzureManagedControlPlane{ 2112 Spec: AzureManagedControlPlaneSpec{ 2113 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2114 Version: "v1.18.0", 2115 }, 2116 }, 2117 }, 2118 wantErr: true, 2119 }, 2120 { 2121 name: "AzureManagedControlPlane NetworkPlugin is immutable", 2122 oldAMCP: &AzureManagedControlPlane{ 2123 Spec: AzureManagedControlPlaneSpec{ 2124 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2125 DNSServiceIP: ptr.To("192.168.0.10"), 2126 NetworkPlugin: ptr.To("azure"), 2127 Version: "v1.18.0", 2128 }, 2129 }, 2130 }, 2131 amcp: &AzureManagedControlPlane{ 2132 Spec: AzureManagedControlPlaneSpec{ 2133 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2134 DNSServiceIP: ptr.To("192.168.0.10"), 2135 NetworkPlugin: ptr.To("kubenet"), 2136 Version: "v1.18.0", 2137 }, 2138 }, 2139 }, 2140 wantErr: true, 2141 }, 2142 { 2143 name: "AzureManagedControlPlane NetworkPlugin is immutable, unsetting is not allowed", 2144 oldAMCP: &AzureManagedControlPlane{ 2145 Spec: AzureManagedControlPlaneSpec{ 2146 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2147 DNSServiceIP: ptr.To("192.168.0.10"), 2148 NetworkPlugin: ptr.To("azure"), 2149 Version: "v1.18.0", 2150 }, 2151 }, 2152 }, 2153 amcp: &AzureManagedControlPlane{ 2154 Spec: AzureManagedControlPlaneSpec{ 2155 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2156 DNSServiceIP: ptr.To("192.168.0.10"), 2157 Version: "v1.18.0", 2158 }, 2159 }, 2160 }, 2161 wantErr: true, 2162 }, 2163 { 2164 name: "AzureManagedControlPlane NetworkPolicy is immutable", 2165 oldAMCP: &AzureManagedControlPlane{ 2166 Spec: AzureManagedControlPlaneSpec{ 2167 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2168 DNSServiceIP: ptr.To("192.168.0.10"), 2169 NetworkPolicy: ptr.To("azure"), 2170 Version: "v1.18.0", 2171 }, 2172 }, 2173 }, 2174 amcp: &AzureManagedControlPlane{ 2175 Spec: AzureManagedControlPlaneSpec{ 2176 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2177 DNSServiceIP: ptr.To("192.168.0.10"), 2178 NetworkPolicy: ptr.To("calico"), 2179 Version: "v1.18.0", 2180 }, 2181 }, 2182 }, 2183 wantErr: true, 2184 }, 2185 { 2186 name: "AzureManagedControlPlane NetworkPolicy is immutable, unsetting is not allowed", 2187 oldAMCP: &AzureManagedControlPlane{ 2188 Spec: AzureManagedControlPlaneSpec{ 2189 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2190 DNSServiceIP: ptr.To("192.168.0.10"), 2191 NetworkPolicy: ptr.To("azure"), 2192 Version: "v1.18.0", 2193 }, 2194 }, 2195 }, 2196 amcp: &AzureManagedControlPlane{ 2197 Spec: AzureManagedControlPlaneSpec{ 2198 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2199 DNSServiceIP: ptr.To("192.168.0.10"), 2200 Version: "v1.18.0", 2201 }, 2202 }, 2203 }, 2204 wantErr: true, 2205 }, 2206 { 2207 name: "AzureManagedControlPlane NetworkPolicy is immutable", 2208 oldAMCP: &AzureManagedControlPlane{ 2209 Spec: AzureManagedControlPlaneSpec{ 2210 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2211 DNSServiceIP: ptr.To("192.168.0.10"), 2212 NetworkDataplane: ptr.To(NetworkDataplaneTypeCilium), 2213 Version: "v1.18.0", 2214 }, 2215 }, 2216 }, 2217 amcp: &AzureManagedControlPlane{ 2218 Spec: AzureManagedControlPlaneSpec{ 2219 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2220 DNSServiceIP: ptr.To("192.168.0.10"), 2221 NetworkDataplane: ptr.To(NetworkDataplaneTypeAzure), 2222 Version: "v1.18.0", 2223 }, 2224 }, 2225 }, 2226 wantErr: true, 2227 }, 2228 { 2229 name: "AzureManagedControlPlane NetworkDataplane is immutable, unsetting is not allowed", 2230 oldAMCP: &AzureManagedControlPlane{ 2231 Spec: AzureManagedControlPlaneSpec{ 2232 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2233 DNSServiceIP: ptr.To("192.168.0.10"), 2234 NetworkDataplane: ptr.To(NetworkDataplaneTypeCilium), 2235 Version: "v1.18.0", 2236 }, 2237 }, 2238 }, 2239 amcp: &AzureManagedControlPlane{ 2240 Spec: AzureManagedControlPlaneSpec{ 2241 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2242 DNSServiceIP: ptr.To("192.168.0.10"), 2243 Version: "v1.18.0", 2244 }, 2245 }, 2246 }, 2247 wantErr: true, 2248 }, 2249 { 2250 name: "AzureManagedControlPlane LoadBalancerSKU is immutable", 2251 oldAMCP: &AzureManagedControlPlane{ 2252 Spec: AzureManagedControlPlaneSpec{ 2253 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2254 DNSServiceIP: ptr.To("192.168.0.10"), 2255 LoadBalancerSKU: ptr.To("Standard"), 2256 Version: "v1.18.0", 2257 }, 2258 }, 2259 }, 2260 amcp: &AzureManagedControlPlane{ 2261 Spec: AzureManagedControlPlaneSpec{ 2262 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2263 DNSServiceIP: ptr.To("192.168.0.10"), 2264 LoadBalancerSKU: ptr.To(LoadBalancerSKUBasic), 2265 Version: "v1.18.0", 2266 }, 2267 }, 2268 }, 2269 wantErr: true, 2270 }, 2271 { 2272 name: "AzureManagedControlPlane LoadBalancerSKU is immutable, unsetting is not allowed", 2273 oldAMCP: &AzureManagedControlPlane{ 2274 Spec: AzureManagedControlPlaneSpec{ 2275 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2276 DNSServiceIP: ptr.To("192.168.0.10"), 2277 LoadBalancerSKU: ptr.To(LoadBalancerSKUStandard), 2278 Version: "v1.18.0", 2279 }, 2280 }, 2281 }, 2282 amcp: &AzureManagedControlPlane{ 2283 Spec: AzureManagedControlPlaneSpec{ 2284 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2285 DNSServiceIP: ptr.To("192.168.0.10"), 2286 Version: "v1.18.0", 2287 }, 2288 }, 2289 }, 2290 wantErr: true, 2291 }, 2292 { 2293 name: "AzureManagedControlPlane ManagedAad can be set after cluster creation", 2294 oldAMCP: &AzureManagedControlPlane{ 2295 Spec: AzureManagedControlPlaneSpec{ 2296 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2297 Version: "v1.18.0", 2298 }, 2299 }, 2300 }, 2301 amcp: &AzureManagedControlPlane{ 2302 Spec: AzureManagedControlPlaneSpec{ 2303 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2304 Version: "v1.18.0", 2305 AADProfile: &AADProfile{ 2306 Managed: true, 2307 AdminGroupObjectIDs: []string{ 2308 "616077a8-5db7-4c98-b856-b34619afg75h", 2309 }, 2310 }, 2311 }, 2312 }, 2313 }, 2314 wantErr: false, 2315 }, 2316 { 2317 name: "AzureManagedControlPlane ManagedAad cannot be disabled", 2318 oldAMCP: &AzureManagedControlPlane{ 2319 Spec: AzureManagedControlPlaneSpec{ 2320 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2321 Version: "v1.18.0", 2322 AADProfile: &AADProfile{ 2323 Managed: true, 2324 AdminGroupObjectIDs: []string{ 2325 "616077a8-5db7-4c98-b856-b34619afg75h", 2326 }, 2327 }, 2328 }, 2329 }, 2330 }, 2331 amcp: &AzureManagedControlPlane{ 2332 Spec: AzureManagedControlPlaneSpec{ 2333 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2334 Version: "v1.18.0", 2335 AADProfile: &AADProfile{}, 2336 }, 2337 }, 2338 }, 2339 wantErr: true, 2340 }, 2341 { 2342 name: "AzureManagedControlPlane managed field cannot set to false", 2343 oldAMCP: &AzureManagedControlPlane{ 2344 Spec: AzureManagedControlPlaneSpec{ 2345 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2346 Version: "v1.18.0", 2347 AADProfile: &AADProfile{ 2348 Managed: true, 2349 AdminGroupObjectIDs: []string{ 2350 "616077a8-5db7-4c98-b856-b34619afg75h", 2351 }, 2352 }, 2353 }, 2354 }, 2355 }, 2356 amcp: &AzureManagedControlPlane{ 2357 Spec: AzureManagedControlPlaneSpec{ 2358 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2359 Version: "v1.18.0", 2360 AADProfile: &AADProfile{ 2361 Managed: false, 2362 AdminGroupObjectIDs: []string{ 2363 "616077a8-5db7-4c98-b856-b34619afg75h", 2364 }, 2365 }, 2366 }, 2367 }, 2368 }, 2369 wantErr: true, 2370 }, 2371 { 2372 name: "AzureManagedControlPlane adminGroupObjectIDs cannot set to empty", 2373 oldAMCP: &AzureManagedControlPlane{ 2374 Spec: AzureManagedControlPlaneSpec{ 2375 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2376 Version: "v1.18.0", 2377 AADProfile: &AADProfile{ 2378 Managed: true, 2379 AdminGroupObjectIDs: []string{ 2380 "616077a8-5db7-4c98-b856-b34619afg75h", 2381 }, 2382 }, 2383 }, 2384 }, 2385 }, 2386 amcp: &AzureManagedControlPlane{ 2387 Spec: AzureManagedControlPlaneSpec{ 2388 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2389 Version: "v1.18.0", 2390 AADProfile: &AADProfile{ 2391 Managed: true, 2392 AdminGroupObjectIDs: []string{}, 2393 }, 2394 }, 2395 }, 2396 }, 2397 wantErr: true, 2398 }, 2399 { 2400 name: "AzureManagedControlPlane ManagedAad cannot be disabled", 2401 oldAMCP: &AzureManagedControlPlane{ 2402 Spec: AzureManagedControlPlaneSpec{ 2403 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2404 Version: "v1.18.0", 2405 AADProfile: &AADProfile{ 2406 Managed: true, 2407 AdminGroupObjectIDs: []string{ 2408 "616077a8-5db7-4c98-b856-b34619afg75h", 2409 }, 2410 }, 2411 }, 2412 }, 2413 }, 2414 amcp: &AzureManagedControlPlane{ 2415 Spec: AzureManagedControlPlaneSpec{ 2416 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2417 Version: "v1.18.0", 2418 }, 2419 }, 2420 }, 2421 wantErr: true, 2422 }, 2423 { 2424 name: "AzureManagedControlPlane EnablePrivateCluster is immutable", 2425 oldAMCP: &AzureManagedControlPlane{ 2426 Spec: AzureManagedControlPlaneSpec{ 2427 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2428 DNSServiceIP: ptr.To("192.168.0.10"), 2429 Version: "v1.18.0", 2430 }, 2431 }, 2432 }, 2433 amcp: &AzureManagedControlPlane{ 2434 Spec: AzureManagedControlPlaneSpec{ 2435 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2436 DNSServiceIP: ptr.To("192.168.0.10"), 2437 Version: "v1.18.0", 2438 APIServerAccessProfile: &APIServerAccessProfile{ 2439 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 2440 EnablePrivateCluster: ptr.To(true), 2441 }, 2442 }, 2443 }, 2444 }, 2445 }, 2446 wantErr: true, 2447 }, 2448 { 2449 name: "AzureManagedControlPlane AuthorizedIPRanges is mutable", 2450 oldAMCP: &AzureManagedControlPlane{ 2451 Spec: AzureManagedControlPlaneSpec{ 2452 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2453 DNSServiceIP: ptr.To("192.168.0.10"), 2454 Version: "v1.18.0", 2455 }, 2456 }, 2457 }, 2458 amcp: &AzureManagedControlPlane{ 2459 Spec: AzureManagedControlPlaneSpec{ 2460 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2461 DNSServiceIP: ptr.To("192.168.0.10"), 2462 Version: "v1.18.0", 2463 APIServerAccessProfile: &APIServerAccessProfile{ 2464 AuthorizedIPRanges: []string{"192.168.0.1/32"}, 2465 }, 2466 }, 2467 }, 2468 }, 2469 wantErr: false, 2470 }, 2471 { 2472 name: "AzureManagedControlPlane.VirtualNetwork Name is mutable", 2473 oldAMCP: &AzureManagedControlPlane{ 2474 ObjectMeta: metav1.ObjectMeta{ 2475 Name: "test-cluster", 2476 }, 2477 Spec: AzureManagedControlPlaneSpec{ 2478 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2479 DNSServiceIP: ptr.To("192.168.0.10"), 2480 Version: "v1.18.0", 2481 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 2482 Name: "test-network", 2483 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 2484 CIDRBlock: "10.0.0.0/8", 2485 Subnet: ManagedControlPlaneSubnet{ 2486 Name: "test-subnet", 2487 CIDRBlock: "10.0.2.0/24", 2488 }, 2489 }, 2490 ResourceGroup: "test-rg", 2491 }, 2492 }, 2493 }, 2494 }, 2495 amcp: &AzureManagedControlPlane{ 2496 ObjectMeta: metav1.ObjectMeta{ 2497 Name: "test-cluster", 2498 }, 2499 Spec: AzureManagedControlPlaneSpec{ 2500 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2501 DNSServiceIP: ptr.To("192.168.0.10"), 2502 Version: "v1.18.0", 2503 }, 2504 }, 2505 }, 2506 wantErr: true, 2507 }, 2508 { 2509 name: "AzureManagedControlPlane.VirtualNetwork Name is mutable", 2510 oldAMCP: &AzureManagedControlPlane{ 2511 ObjectMeta: metav1.ObjectMeta{ 2512 Name: "test-cluster", 2513 }, 2514 Spec: AzureManagedControlPlaneSpec{ 2515 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2516 DNSServiceIP: ptr.To("192.168.0.10"), 2517 Version: "v1.18.0", 2518 }, 2519 }, 2520 }, 2521 amcp: &AzureManagedControlPlane{ 2522 ObjectMeta: metav1.ObjectMeta{ 2523 Name: "test-cluster", 2524 }, 2525 Spec: AzureManagedControlPlaneSpec{ 2526 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2527 DNSServiceIP: ptr.To("192.168.0.10"), 2528 Version: "v1.18.0", 2529 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 2530 Name: "test-network", 2531 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 2532 CIDRBlock: "10.0.0.0/8", 2533 Subnet: ManagedControlPlaneSubnet{ 2534 Name: "test-subnet", 2535 CIDRBlock: "10.0.2.0/24", 2536 }, 2537 }, 2538 ResourceGroup: "test-rg", 2539 }, 2540 }, 2541 }, 2542 }, 2543 wantErr: true, 2544 }, 2545 { 2546 name: "AzureManagedControlPlane.VirtualNetwork Name is mutable", 2547 oldAMCP: &AzureManagedControlPlane{ 2548 ObjectMeta: metav1.ObjectMeta{ 2549 Name: "test-cluster", 2550 }, 2551 Spec: AzureManagedControlPlaneSpec{ 2552 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2553 DNSServiceIP: ptr.To("192.168.0.10"), 2554 Version: "v1.18.0", 2555 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 2556 Name: "test-network", 2557 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 2558 CIDRBlock: "10.0.0.0/8", 2559 Subnet: ManagedControlPlaneSubnet{ 2560 Name: "test-subnet", 2561 CIDRBlock: "10.0.2.0/24", 2562 }, 2563 }, 2564 ResourceGroup: "test-rg", 2565 }, 2566 }, 2567 }, 2568 }, 2569 amcp: &AzureManagedControlPlane{ 2570 ObjectMeta: metav1.ObjectMeta{ 2571 Name: "test-cluster", 2572 }, 2573 Spec: AzureManagedControlPlaneSpec{ 2574 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2575 DNSServiceIP: ptr.To("192.168.0.10"), 2576 Version: "v1.18.0", 2577 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 2578 Name: "test-network", 2579 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 2580 CIDRBlock: "10.0.0.0/8", 2581 Subnet: ManagedControlPlaneSubnet{ 2582 Name: "test-subnet", 2583 CIDRBlock: "10.0.2.0/24", 2584 }, 2585 }, 2586 ResourceGroup: "test-rg", 2587 }, 2588 }, 2589 }, 2590 }, 2591 wantErr: false, 2592 }, 2593 { 2594 name: "OutboundType update", 2595 oldAMCP: &AzureManagedControlPlane{ 2596 ObjectMeta: metav1.ObjectMeta{ 2597 Name: "test-cluster", 2598 }, 2599 Spec: AzureManagedControlPlaneSpec{ 2600 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2601 OutboundType: (*ManagedControlPlaneOutboundType)(ptr.To(string(ManagedControlPlaneOutboundTypeUserDefinedRouting))), 2602 }, 2603 }, 2604 }, 2605 amcp: &AzureManagedControlPlane{ 2606 ObjectMeta: metav1.ObjectMeta{ 2607 Name: "test-cluster", 2608 }, 2609 Spec: AzureManagedControlPlaneSpec{ 2610 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2611 OutboundType: (*ManagedControlPlaneOutboundType)(ptr.To(string(ManagedControlPlaneOutboundTypeLoadBalancer))), 2612 }, 2613 }, 2614 }, 2615 wantErr: true, 2616 }, 2617 { 2618 name: "AzureManagedControlPlane HTTPProxyConfig is immutable", 2619 oldAMCP: &AzureManagedControlPlane{ 2620 ObjectMeta: metav1.ObjectMeta{ 2621 Name: "test-cluster", 2622 }, 2623 Spec: AzureManagedControlPlaneSpec{ 2624 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2625 HTTPProxyConfig: &HTTPProxyConfig{ 2626 HTTPProxy: ptr.To("http://1.2.3.4:8080"), 2627 HTTPSProxy: ptr.To("https://5.6.7.8:8443"), 2628 NoProxy: []string{"endpoint1", "endpoint2"}, 2629 TrustedCA: ptr.To("ca"), 2630 }, 2631 }, 2632 }, 2633 }, 2634 amcp: &AzureManagedControlPlane{ 2635 ObjectMeta: metav1.ObjectMeta{ 2636 Name: "test-cluster", 2637 }, 2638 Spec: AzureManagedControlPlaneSpec{ 2639 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2640 HTTPProxyConfig: &HTTPProxyConfig{ 2641 HTTPProxy: ptr.To("http://10.20.3.4:8080"), 2642 HTTPSProxy: ptr.To("https://5.6.7.8:8443"), 2643 NoProxy: []string{"endpoint1", "endpoint2"}, 2644 TrustedCA: ptr.To("ca"), 2645 }, 2646 }, 2647 }, 2648 }, 2649 wantErr: true, 2650 }, 2651 { 2652 name: "NetworkPluginMode cannot change to \"overlay\" when NetworkPolicy is set", 2653 oldAMCP: &AzureManagedControlPlane{ 2654 ObjectMeta: metav1.ObjectMeta{ 2655 Name: "test-cluster", 2656 }, 2657 Spec: AzureManagedControlPlaneSpec{ 2658 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2659 NetworkPolicy: ptr.To("anything"), 2660 NetworkPluginMode: nil, 2661 }, 2662 }, 2663 }, 2664 amcp: &AzureManagedControlPlane{ 2665 ObjectMeta: metav1.ObjectMeta{ 2666 Name: "test-cluster", 2667 }, 2668 Spec: AzureManagedControlPlaneSpec{ 2669 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2670 NetworkPolicy: ptr.To("anything"), 2671 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 2672 }, 2673 }, 2674 }, 2675 wantErr: true, 2676 }, 2677 { 2678 name: "NetworkPluginMode can change to \"overlay\" when NetworkPolicy is not set", 2679 oldAMCP: &AzureManagedControlPlane{ 2680 ObjectMeta: metav1.ObjectMeta{ 2681 Name: "test-cluster", 2682 }, 2683 Spec: AzureManagedControlPlaneSpec{ 2684 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2685 NetworkPolicy: nil, 2686 NetworkPluginMode: nil, 2687 }, 2688 }, 2689 }, 2690 amcp: &AzureManagedControlPlane{ 2691 ObjectMeta: metav1.ObjectMeta{ 2692 Name: "test-cluster", 2693 }, 2694 Spec: AzureManagedControlPlaneSpec{ 2695 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2696 Version: "v0.0.0", 2697 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 2698 }, 2699 }, 2700 }, 2701 wantErr: false, 2702 }, 2703 { 2704 name: "NetworkPolicy is allowed when NetworkPluginMode is not changed", 2705 oldAMCP: &AzureManagedControlPlane{ 2706 ObjectMeta: metav1.ObjectMeta{ 2707 Name: "test-cluster", 2708 }, 2709 Spec: AzureManagedControlPlaneSpec{ 2710 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2711 NetworkPolicy: ptr.To("anything"), 2712 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 2713 }, 2714 }, 2715 }, 2716 amcp: &AzureManagedControlPlane{ 2717 ObjectMeta: metav1.ObjectMeta{ 2718 Name: "test-cluster", 2719 }, 2720 Spec: AzureManagedControlPlaneSpec{ 2721 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2722 NetworkPolicy: ptr.To("anything"), 2723 Version: "v0.0.0", 2724 NetworkPluginMode: ptr.To(NetworkPluginModeOverlay), 2725 }, 2726 }, 2727 }, 2728 wantErr: false, 2729 }, 2730 { 2731 name: "AzureManagedControlPlane OIDCIssuerProfile.Enabled false -> false OK", 2732 oldAMCP: &AzureManagedControlPlane{ 2733 ObjectMeta: metav1.ObjectMeta{ 2734 Name: "test-cluster", 2735 }, 2736 Spec: AzureManagedControlPlaneSpec{ 2737 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2738 OIDCIssuerProfile: &OIDCIssuerProfile{ 2739 Enabled: ptr.To(false), 2740 }, 2741 }, 2742 }, 2743 }, 2744 amcp: &AzureManagedControlPlane{ 2745 ObjectMeta: metav1.ObjectMeta{ 2746 Name: "test-cluster", 2747 }, 2748 Spec: AzureManagedControlPlaneSpec{ 2749 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2750 Version: "v0.0.0", 2751 OIDCIssuerProfile: &OIDCIssuerProfile{ 2752 Enabled: ptr.To(false), 2753 }, 2754 }, 2755 }, 2756 }, 2757 wantErr: false, 2758 }, 2759 { 2760 name: "AzureManagedControlPlane OIDCIssuerProfile.Enabled false -> true OK", 2761 oldAMCP: &AzureManagedControlPlane{ 2762 ObjectMeta: metav1.ObjectMeta{ 2763 Name: "test-cluster", 2764 }, 2765 Spec: AzureManagedControlPlaneSpec{ 2766 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2767 OIDCIssuerProfile: &OIDCIssuerProfile{ 2768 Enabled: ptr.To(false), 2769 }, 2770 }, 2771 }, 2772 }, 2773 amcp: &AzureManagedControlPlane{ 2774 ObjectMeta: metav1.ObjectMeta{ 2775 Name: "test-cluster", 2776 }, 2777 Spec: AzureManagedControlPlaneSpec{ 2778 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2779 Version: "v0.0.0", 2780 OIDCIssuerProfile: &OIDCIssuerProfile{ 2781 Enabled: ptr.To(true), 2782 }, 2783 }, 2784 }, 2785 }, 2786 wantErr: false, 2787 }, 2788 { 2789 name: "AzureManagedControlPlane OIDCIssuerProfile.Enabled true -> false err", 2790 oldAMCP: &AzureManagedControlPlane{ 2791 ObjectMeta: metav1.ObjectMeta{ 2792 Name: "test-cluster", 2793 }, 2794 Spec: AzureManagedControlPlaneSpec{ 2795 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2796 OIDCIssuerProfile: &OIDCIssuerProfile{ 2797 Enabled: ptr.To(true), 2798 }, 2799 }, 2800 }, 2801 }, 2802 amcp: &AzureManagedControlPlane{ 2803 ObjectMeta: metav1.ObjectMeta{ 2804 Name: "test-cluster", 2805 }, 2806 Spec: AzureManagedControlPlaneSpec{ 2807 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2808 Version: "v0.0.0", 2809 OIDCIssuerProfile: &OIDCIssuerProfile{ 2810 Enabled: ptr.To(false), 2811 }, 2812 }, 2813 }, 2814 }, 2815 wantErr: true, 2816 }, 2817 { 2818 name: "AzureManagedControlPlane OIDCIssuerProfile.Enabled true -> true OK", 2819 oldAMCP: &AzureManagedControlPlane{ 2820 ObjectMeta: metav1.ObjectMeta{ 2821 Name: "test-cluster", 2822 }, 2823 Spec: AzureManagedControlPlaneSpec{ 2824 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2825 OIDCIssuerProfile: &OIDCIssuerProfile{ 2826 Enabled: ptr.To(true), 2827 }, 2828 }, 2829 }, 2830 }, 2831 amcp: &AzureManagedControlPlane{ 2832 ObjectMeta: metav1.ObjectMeta{ 2833 Name: "test-cluster", 2834 }, 2835 Spec: AzureManagedControlPlaneSpec{ 2836 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2837 Version: "v0.0.0", 2838 OIDCIssuerProfile: &OIDCIssuerProfile{ 2839 Enabled: ptr.To(true), 2840 }, 2841 }, 2842 }, 2843 }, 2844 wantErr: false, 2845 }, 2846 { 2847 name: "AzureManagedControlPlane DNSPrefix is immutable error", 2848 oldAMCP: &AzureManagedControlPlane{ 2849 Spec: AzureManagedControlPlaneSpec{ 2850 DNSPrefix: ptr.To("capz-aks-1"), 2851 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2852 Version: "v1.18.0", 2853 }, 2854 }, 2855 }, 2856 amcp: &AzureManagedControlPlane{ 2857 Spec: AzureManagedControlPlaneSpec{ 2858 DNSPrefix: ptr.To("capz-aks"), 2859 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2860 Version: "v1.18.0", 2861 }, 2862 }, 2863 }, 2864 wantErr: true, 2865 }, 2866 { 2867 name: "AzureManagedControlPlane DNSPrefix is immutable no error", 2868 oldAMCP: &AzureManagedControlPlane{ 2869 Spec: AzureManagedControlPlaneSpec{ 2870 DNSPrefix: ptr.To("capz-aks"), 2871 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2872 Version: "v1.18.0", 2873 }, 2874 }, 2875 }, 2876 amcp: &AzureManagedControlPlane{ 2877 Spec: AzureManagedControlPlaneSpec{ 2878 DNSPrefix: ptr.To("capz-aks"), 2879 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2880 Version: "v1.18.0", 2881 }, 2882 }, 2883 }, 2884 wantErr: false, 2885 }, 2886 { 2887 name: "DisableLocalAccounts can be set only for AAD enabled clusters", 2888 oldAMCP: &AzureManagedControlPlane{ 2889 ObjectMeta: metav1.ObjectMeta{ 2890 Name: "test-cluster", 2891 }, 2892 Spec: AzureManagedControlPlaneSpec{ 2893 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2894 Version: "v1.18.0", 2895 AADProfile: &AADProfile{ 2896 Managed: true, 2897 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2898 }, 2899 }, 2900 }, 2901 }, 2902 amcp: &AzureManagedControlPlane{ 2903 ObjectMeta: metav1.ObjectMeta{ 2904 Name: "test-cluster", 2905 }, 2906 Spec: AzureManagedControlPlaneSpec{ 2907 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2908 Version: "v1.18.0", 2909 AADProfile: &AADProfile{ 2910 Managed: true, 2911 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2912 }, 2913 DisableLocalAccounts: ptr.To[bool](true), 2914 }, 2915 }, 2916 }, 2917 wantErr: false, 2918 }, 2919 { 2920 name: "DisableLocalAccounts cannot be disabled", 2921 oldAMCP: &AzureManagedControlPlane{ 2922 ObjectMeta: metav1.ObjectMeta{ 2923 Name: "test-cluster", 2924 }, 2925 Spec: AzureManagedControlPlaneSpec{ 2926 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2927 Version: "v1.18.0", 2928 AADProfile: &AADProfile{ 2929 Managed: true, 2930 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2931 }, 2932 DisableLocalAccounts: ptr.To[bool](true), 2933 }, 2934 }, 2935 }, 2936 amcp: &AzureManagedControlPlane{ 2937 ObjectMeta: metav1.ObjectMeta{ 2938 Name: "test-cluster", 2939 }, 2940 Spec: AzureManagedControlPlaneSpec{ 2941 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2942 Version: "v1.18.0", 2943 AADProfile: &AADProfile{ 2944 Managed: true, 2945 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2946 }, 2947 }, 2948 }, 2949 }, 2950 wantErr: true, 2951 }, 2952 { 2953 name: "DisableLocalAccounts cannot be disabled", 2954 oldAMCP: &AzureManagedControlPlane{ 2955 ObjectMeta: metav1.ObjectMeta{ 2956 Name: "test-cluster", 2957 }, 2958 Spec: AzureManagedControlPlaneSpec{ 2959 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2960 Version: "v1.18.0", 2961 AADProfile: &AADProfile{ 2962 Managed: true, 2963 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2964 }, 2965 DisableLocalAccounts: ptr.To[bool](true), 2966 }, 2967 }, 2968 }, 2969 amcp: &AzureManagedControlPlane{ 2970 ObjectMeta: metav1.ObjectMeta{ 2971 Name: "test-cluster", 2972 }, 2973 Spec: AzureManagedControlPlaneSpec{ 2974 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2975 Version: "v1.18.0", 2976 AADProfile: &AADProfile{ 2977 Managed: true, 2978 AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"}, 2979 }, 2980 DisableLocalAccounts: ptr.To[bool](false), 2981 }, 2982 }, 2983 }, 2984 wantErr: true, 2985 }, 2986 { 2987 name: "AzureManagedControlPlane DNSPrefix is immutable error nil -> capz-aks", 2988 oldAMCP: &AzureManagedControlPlane{ 2989 Spec: AzureManagedControlPlaneSpec{ 2990 DNSPrefix: nil, 2991 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 2992 Version: "v1.18.0", 2993 }, 2994 }, 2995 }, 2996 amcp: &AzureManagedControlPlane{ 2997 Spec: AzureManagedControlPlaneSpec{ 2998 DNSPrefix: ptr.To("capz-aks"), 2999 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3000 Version: "v1.18.0", 3001 }, 3002 }, 3003 }, 3004 wantErr: true, 3005 }, 3006 { 3007 name: "AzureManagedControlPlane DNSPrefix can be updated from nil when resource name matches", 3008 oldAMCP: &AzureManagedControlPlane{ 3009 ObjectMeta: metav1.ObjectMeta{ 3010 Name: "capz-aks", 3011 }, 3012 Spec: AzureManagedControlPlaneSpec{ 3013 DNSPrefix: nil, 3014 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3015 Version: "v1.18.0", 3016 }, 3017 }, 3018 }, 3019 amcp: &AzureManagedControlPlane{ 3020 Spec: AzureManagedControlPlaneSpec{ 3021 DNSPrefix: ptr.To("capz-aks"), 3022 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3023 Version: "v1.18.0", 3024 }, 3025 }, 3026 }, 3027 wantErr: false, 3028 }, 3029 { 3030 name: "DisableLocalAccounts cannot be set for non AAD clusters", 3031 oldAMCP: &AzureManagedControlPlane{ 3032 ObjectMeta: metav1.ObjectMeta{ 3033 Name: "test-cluster", 3034 }, 3035 Spec: AzureManagedControlPlaneSpec{ 3036 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3037 Version: "v1.18.0", 3038 }, 3039 }, 3040 }, 3041 amcp: &AzureManagedControlPlane{ 3042 ObjectMeta: metav1.ObjectMeta{ 3043 Name: "test-cluster", 3044 }, 3045 Spec: AzureManagedControlPlaneSpec{ 3046 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3047 Version: "v1.18.0", 3048 DisableLocalAccounts: ptr.To[bool](true), 3049 }, 3050 }, 3051 }, 3052 wantErr: true, 3053 }, 3054 { 3055 name: "AzureManagedControlPlane DNSPrefix is immutable error nil -> empty", 3056 oldAMCP: &AzureManagedControlPlane{ 3057 Spec: AzureManagedControlPlaneSpec{ 3058 DNSPrefix: nil, 3059 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3060 Version: "v1.18.0", 3061 }, 3062 }, 3063 }, 3064 amcp: &AzureManagedControlPlane{ 3065 Spec: AzureManagedControlPlaneSpec{ 3066 DNSPrefix: ptr.To(""), 3067 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3068 Version: "v1.18.0", 3069 }, 3070 }, 3071 }, 3072 wantErr: true, 3073 }, 3074 { 3075 name: "AzureManagedControlPlane DNSPrefix is immutable no error nil -> nil", 3076 oldAMCP: &AzureManagedControlPlane{ 3077 Spec: AzureManagedControlPlaneSpec{ 3078 DNSPrefix: nil, 3079 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3080 Version: "v1.18.0", 3081 }, 3082 }, 3083 }, 3084 amcp: &AzureManagedControlPlane{ 3085 Spec: AzureManagedControlPlaneSpec{ 3086 DNSPrefix: nil, 3087 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3088 Version: "v1.18.0", 3089 }, 3090 }, 3091 }, 3092 wantErr: false, 3093 }, 3094 { 3095 name: "AzureManagedControlPlane AKSExtensions ConfigurationSettings and AutoUpgradeMinorVersion are mutable", 3096 oldAMCP: &AzureManagedControlPlane{ 3097 Spec: AzureManagedControlPlaneSpec{ 3098 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3099 Version: "v1.18.0", 3100 Extensions: []AKSExtension{ 3101 { 3102 Name: "extension1", 3103 AutoUpgradeMinorVersion: ptr.To(false), 3104 ConfigurationSettings: map[string]string{ 3105 "key1": "value1", 3106 }, 3107 Plan: &ExtensionPlan{ 3108 Name: "planName", 3109 Product: "planProduct", 3110 Publisher: "planPublisher", 3111 }, 3112 }, 3113 }, 3114 }, 3115 }, 3116 }, 3117 amcp: &AzureManagedControlPlane{ 3118 Spec: AzureManagedControlPlaneSpec{ 3119 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3120 Version: "v1.18.0", 3121 Extensions: []AKSExtension{ 3122 { 3123 Name: "extension1", 3124 AutoUpgradeMinorVersion: ptr.To(true), 3125 ConfigurationSettings: map[string]string{ 3126 "key1": "value1", 3127 "key2": "value2", 3128 }, 3129 Plan: &ExtensionPlan{ 3130 Name: "planName", 3131 Product: "planProduct", 3132 Publisher: "planPublisher", 3133 }, 3134 }, 3135 }, 3136 }, 3137 }, 3138 }, 3139 wantErr: false, 3140 }, 3141 { 3142 name: "AzureManagedControlPlane all other fields are immutable", 3143 oldAMCP: &AzureManagedControlPlane{ 3144 Spec: AzureManagedControlPlaneSpec{ 3145 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3146 Version: "v1.18.0", 3147 Extensions: []AKSExtension{ 3148 { 3149 Name: "extension1", 3150 AKSAssignedIdentityType: AKSAssignedIdentitySystemAssigned, 3151 ExtensionType: ptr.To("extensionType"), 3152 Plan: &ExtensionPlan{ 3153 Name: "planName", 3154 Product: "planProduct", 3155 Publisher: "planPublisher", 3156 }, 3157 Scope: &ExtensionScope{ 3158 ScopeType: "Cluster", 3159 ReleaseNamespace: "default", 3160 }, 3161 ReleaseTrain: ptr.To("releaseTrain"), 3162 Version: ptr.To("v1.0.0"), 3163 }, 3164 }, 3165 }, 3166 }, 3167 }, 3168 amcp: &AzureManagedControlPlane{ 3169 Spec: AzureManagedControlPlaneSpec{ 3170 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3171 Version: "v1.18.0", 3172 Extensions: []AKSExtension{ 3173 { 3174 Name: "extension2", 3175 AKSAssignedIdentityType: AKSAssignedIdentityUserAssigned, 3176 ExtensionType: ptr.To("extensionType1"), 3177 Plan: &ExtensionPlan{ 3178 Name: "planName1", 3179 Product: "planProduct1", 3180 Publisher: "planPublisher1", 3181 }, 3182 Scope: &ExtensionScope{ 3183 ScopeType: "Namespace", 3184 ReleaseNamespace: "default", 3185 }, 3186 ReleaseTrain: ptr.To("releaseTrain1"), 3187 Version: ptr.To("v1.1.0"), 3188 }, 3189 }, 3190 }, 3191 }, 3192 }, 3193 wantErr: true, 3194 }, 3195 } 3196 client := mockClient{ReturnError: false} 3197 for _, tc := range tests { 3198 t.Run(tc.name, func(t *testing.T) { 3199 g := NewWithT(t) 3200 mcpw := &azureManagedControlPlaneWebhook{ 3201 Client: client, 3202 } 3203 _, err := mcpw.ValidateUpdate(context.Background(), tc.oldAMCP, tc.amcp) 3204 if tc.wantErr { 3205 g.Expect(err).To(HaveOccurred()) 3206 } else { 3207 g.Expect(err).NotTo(HaveOccurred()) 3208 } 3209 }) 3210 } 3211 } 3212 3213 func createAzureManagedControlPlane(serviceIP, version, sshKey string) *AzureManagedControlPlane { 3214 return &AzureManagedControlPlane{ 3215 ObjectMeta: getAMCPMetaData(), 3216 Spec: AzureManagedControlPlaneSpec{ 3217 SSHPublicKey: &sshKey, 3218 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3219 DNSServiceIP: ptr.To(serviceIP), 3220 Version: version, 3221 }, 3222 }, 3223 } 3224 } 3225 3226 func getKnownValidAzureManagedControlPlane() *AzureManagedControlPlane { 3227 return &AzureManagedControlPlane{ 3228 ObjectMeta: getAMCPMetaData(), 3229 Spec: AzureManagedControlPlaneSpec{ 3230 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3231 DNSServiceIP: ptr.To("192.168.0.10"), 3232 Version: "v1.18.0", 3233 AADProfile: &AADProfile{ 3234 Managed: true, 3235 AdminGroupObjectIDs: []string{ 3236 "616077a8-5db7-4c98-b856-b34619afg75h", 3237 }, 3238 }, 3239 }, 3240 SSHPublicKey: ptr.To(generateSSHPublicKey(true)), 3241 }, 3242 } 3243 } 3244 3245 func getAMCPMetaData() metav1.ObjectMeta { 3246 return metav1.ObjectMeta{ 3247 Name: "test-AMCP", 3248 Labels: map[string]string{ 3249 "cluster.x-k8s.io/cluster-name": "test-cluster", 3250 }, 3251 Namespace: "default", 3252 } 3253 } 3254 3255 func TestAzureManagedClusterSecurityProfileValidateCreate(t *testing.T) { 3256 testsCreate := []struct { 3257 name string 3258 amcp *AzureManagedControlPlane 3259 wantErr string 3260 }{ 3261 { 3262 name: "Cannot enable Workload Identity without enabling OIDC issuer", 3263 amcp: &AzureManagedControlPlane{ 3264 Spec: AzureManagedControlPlaneSpec{ 3265 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3266 Version: "v1.17.8", 3267 SecurityProfile: &ManagedClusterSecurityProfile{ 3268 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3269 Enabled: true, 3270 }, 3271 }, 3272 }, 3273 }, 3274 }, 3275 wantErr: "spec.securityProfile.workloadIdentity: Invalid value: v1beta1.ManagedClusterSecurityProfileWorkloadIdentity{Enabled:true}: Spec.SecurityProfile.WorkloadIdentity cannot be enabled when Spec.OIDCIssuerProfile is disabled", 3276 }, 3277 { 3278 name: "Cannot enable AzureKms without user assigned identity", 3279 amcp: &AzureManagedControlPlane{ 3280 Spec: AzureManagedControlPlaneSpec{ 3281 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3282 Version: "v1.17.8", 3283 SecurityProfile: &ManagedClusterSecurityProfile{ 3284 AzureKeyVaultKms: &AzureKeyVaultKms{ 3285 Enabled: true, 3286 }, 3287 }, 3288 }, 3289 }, 3290 }, 3291 wantErr: "spec.securityProfile.azureKeyVaultKms.keyVaultResourceID: Invalid value: \"null\": Spec.SecurityProfile.AzureKeyVaultKms can be set only when Spec.Identity.Type is UserAssigned", 3292 }, 3293 { 3294 name: "When AzureKms.KeyVaultNetworkAccess is private AzureKeyVaultKms.KeyVaultResourceID cannot be empty", 3295 amcp: &AzureManagedControlPlane{ 3296 Spec: AzureManagedControlPlaneSpec{ 3297 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3298 Identity: &Identity{ 3299 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3300 UserAssignedIdentityResourceID: "not empty", 3301 }, 3302 Version: "v1.17.8", 3303 SecurityProfile: &ManagedClusterSecurityProfile{ 3304 AzureKeyVaultKms: &AzureKeyVaultKms{ 3305 Enabled: true, 3306 KeyID: "not empty", 3307 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 3308 }, 3309 }, 3310 }, 3311 }, 3312 }, 3313 wantErr: "spec.securityProfile.azureKeyVaultKms.keyVaultResourceID: Invalid value: \"null\": Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID cannot be empty when Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess is Private", 3314 }, 3315 { 3316 name: "When AzureKms.KeyVaultNetworkAccess is public AzureKeyVaultKms.KeyVaultResourceID should be empty", 3317 amcp: &AzureManagedControlPlane{ 3318 Spec: AzureManagedControlPlaneSpec{ 3319 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3320 Version: "v1.17.8", 3321 Identity: &Identity{ 3322 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3323 UserAssignedIdentityResourceID: "not empty", 3324 }, 3325 SecurityProfile: &ManagedClusterSecurityProfile{ 3326 AzureKeyVaultKms: &AzureKeyVaultKms{ 3327 Enabled: true, 3328 KeyID: "not empty", 3329 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3330 KeyVaultResourceID: ptr.To("not empty"), 3331 }, 3332 }, 3333 }, 3334 }, 3335 }, 3336 wantErr: "spec.securityProfile.azureKeyVaultKms.keyVaultResourceID: Invalid value: \"not empty\": Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID should be empty when Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess is Public", 3337 }, 3338 { 3339 name: "Valid profile", 3340 amcp: &AzureManagedControlPlane{ 3341 Spec: AzureManagedControlPlaneSpec{ 3342 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3343 Version: "v1.17.8", 3344 Identity: &Identity{ 3345 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3346 UserAssignedIdentityResourceID: "not empty", 3347 }, 3348 OIDCIssuerProfile: &OIDCIssuerProfile{ 3349 Enabled: ptr.To(true), 3350 }, 3351 SecurityProfile: &ManagedClusterSecurityProfile{ 3352 AzureKeyVaultKms: &AzureKeyVaultKms{ 3353 Enabled: true, 3354 KeyID: "not empty", 3355 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3356 }, 3357 Defender: &ManagedClusterSecurityProfileDefender{ 3358 LogAnalyticsWorkspaceResourceID: "not empty", 3359 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 3360 Enabled: true, 3361 }, 3362 }, 3363 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3364 Enabled: true, 3365 }, 3366 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3367 Enabled: true, 3368 IntervalHours: ptr.To(24), 3369 }, 3370 }, 3371 }, 3372 }, 3373 }, 3374 wantErr: "", 3375 }, 3376 } 3377 client := mockClient{ReturnError: false} 3378 for _, tc := range testsCreate { 3379 t.Run(tc.name, func(t *testing.T) { 3380 g := NewWithT(t) 3381 mcpw := &azureManagedControlPlaneWebhook{ 3382 Client: client, 3383 } 3384 _, err := mcpw.ValidateCreate(context.Background(), tc.amcp) 3385 if tc.wantErr != "" { 3386 g.Expect(err).To(HaveOccurred()) 3387 g.Expect(err.Error()).To(Equal(tc.wantErr)) 3388 } else { 3389 g.Expect(err).NotTo(HaveOccurred()) 3390 } 3391 }) 3392 } 3393 } 3394 3395 func TestAzureClusterSecurityProfileValidateUpdate(t *testing.T) { 3396 tests := []struct { 3397 name string 3398 oldAMCP *AzureManagedControlPlane 3399 amcp *AzureManagedControlPlane 3400 wantErr string 3401 }{ 3402 { 3403 name: "AzureManagedControlPlane SecurityProfile.Defender is mutable", 3404 oldAMCP: &AzureManagedControlPlane{ 3405 Spec: AzureManagedControlPlaneSpec{ 3406 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3407 Version: "v1.18.0", 3408 }, 3409 }, 3410 }, 3411 amcp: &AzureManagedControlPlane{ 3412 Spec: AzureManagedControlPlaneSpec{ 3413 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3414 Version: "v1.18.0", 3415 SecurityProfile: &ManagedClusterSecurityProfile{ 3416 Defender: &ManagedClusterSecurityProfileDefender{ 3417 LogAnalyticsWorkspaceResourceID: "0000-0000-0000-0000", 3418 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 3419 Enabled: true, 3420 }, 3421 }, 3422 }, 3423 }, 3424 }, 3425 }, 3426 wantErr: "", 3427 }, 3428 { 3429 name: "AzureManagedControlPlane SecurityProfile.Defender is mutable and cannot be unset", 3430 oldAMCP: &AzureManagedControlPlane{ 3431 Spec: AzureManagedControlPlaneSpec{ 3432 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3433 Version: "v1.18.0", 3434 SecurityProfile: &ManagedClusterSecurityProfile{ 3435 Defender: &ManagedClusterSecurityProfileDefender{ 3436 LogAnalyticsWorkspaceResourceID: "0000-0000-0000-0000", 3437 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 3438 Enabled: true, 3439 }, 3440 }, 3441 }, 3442 }, 3443 }, 3444 }, 3445 amcp: &AzureManagedControlPlane{ 3446 Spec: AzureManagedControlPlaneSpec{ 3447 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3448 Version: "v1.18.0", 3449 }, 3450 }, 3451 }, 3452 wantErr: "AzureManagedControlPlane.infrastructure.cluster.x-k8s.io \"\" is invalid: spec.securityProfile.defender: Invalid value: \"null\": cannot unset Spec.SecurityProfile.Defender, to disable defender please set Spec.SecurityProfile.Defender.SecurityMonitoring.Enabled to false", 3453 }, 3454 { 3455 name: "AzureManagedControlPlane SecurityProfile.Defender is mutable and can be disabled", 3456 oldAMCP: &AzureManagedControlPlane{ 3457 Spec: AzureManagedControlPlaneSpec{ 3458 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3459 Version: "v1.18.0", 3460 SecurityProfile: &ManagedClusterSecurityProfile{ 3461 Defender: &ManagedClusterSecurityProfileDefender{ 3462 LogAnalyticsWorkspaceResourceID: "0000-0000-0000-0000", 3463 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 3464 Enabled: true, 3465 }, 3466 }, 3467 }, 3468 }, 3469 }, 3470 }, 3471 amcp: &AzureManagedControlPlane{ 3472 Spec: AzureManagedControlPlaneSpec{ 3473 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3474 Version: "v1.18.0", 3475 SecurityProfile: &ManagedClusterSecurityProfile{ 3476 Defender: &ManagedClusterSecurityProfileDefender{ 3477 LogAnalyticsWorkspaceResourceID: "0000-0000-0000-0000", 3478 SecurityMonitoring: ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 3479 Enabled: false, 3480 }, 3481 }, 3482 }, 3483 }, 3484 }, 3485 }, 3486 wantErr: "", 3487 }, 3488 { 3489 name: "AzureManagedControlPlane SecurityProfile.WorkloadIdentity is mutable", 3490 oldAMCP: &AzureManagedControlPlane{ 3491 Spec: AzureManagedControlPlaneSpec{ 3492 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3493 Version: "v1.18.0", 3494 }, 3495 }, 3496 }, 3497 amcp: &AzureManagedControlPlane{ 3498 Spec: AzureManagedControlPlaneSpec{ 3499 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3500 Version: "v1.18.0", 3501 OIDCIssuerProfile: &OIDCIssuerProfile{ 3502 Enabled: ptr.To(true), 3503 }, 3504 SecurityProfile: &ManagedClusterSecurityProfile{ 3505 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3506 Enabled: true, 3507 }, 3508 }, 3509 }, 3510 }, 3511 }, 3512 wantErr: "", 3513 }, 3514 { 3515 name: "AzureManagedControlPlane SecurityProfile.WorkloadIdentity cannot be enabled without OIDC issuer", 3516 oldAMCP: &AzureManagedControlPlane{ 3517 Spec: AzureManagedControlPlaneSpec{ 3518 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3519 Version: "v1.18.0", 3520 }, 3521 }, 3522 }, 3523 amcp: &AzureManagedControlPlane{ 3524 Spec: AzureManagedControlPlaneSpec{ 3525 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3526 Version: "v1.18.0", 3527 SecurityProfile: &ManagedClusterSecurityProfile{ 3528 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3529 Enabled: true, 3530 }, 3531 }, 3532 }, 3533 }, 3534 }, 3535 wantErr: "spec.securityProfile.workloadIdentity: Invalid value: v1beta1.ManagedClusterSecurityProfileWorkloadIdentity{Enabled:true}: Spec.SecurityProfile.WorkloadIdentity cannot be enabled when Spec.OIDCIssuerProfile is disabled", 3536 }, 3537 { 3538 name: "AzureManagedControlPlane SecurityProfile.WorkloadIdentity cannot unset values", 3539 oldAMCP: &AzureManagedControlPlane{ 3540 Spec: AzureManagedControlPlaneSpec{ 3541 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3542 Version: "v1.18.0", 3543 OIDCIssuerProfile: &OIDCIssuerProfile{ 3544 Enabled: ptr.To(true), 3545 }, 3546 SecurityProfile: &ManagedClusterSecurityProfile{ 3547 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3548 Enabled: true, 3549 }, 3550 }, 3551 }, 3552 }, 3553 }, 3554 amcp: &AzureManagedControlPlane{ 3555 Spec: AzureManagedControlPlaneSpec{ 3556 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3557 Version: "v1.18.0", 3558 OIDCIssuerProfile: &OIDCIssuerProfile{ 3559 Enabled: ptr.To(true), 3560 }, 3561 }, 3562 }, 3563 }, 3564 wantErr: "AzureManagedControlPlane.infrastructure.cluster.x-k8s.io \"\" is invalid: spec.securityProfile.workloadIdentity: Invalid value: \"null\": cannot unset Spec.SecurityProfile.WorkloadIdentity, to disable workloadIdentity please set Spec.SecurityProfile.WorkloadIdentity.Enabled to false", 3565 }, 3566 { 3567 name: "AzureManagedControlPlane SecurityProfile.WorkloadIdentity can be disabled", 3568 oldAMCP: &AzureManagedControlPlane{ 3569 Spec: AzureManagedControlPlaneSpec{ 3570 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3571 Version: "v1.18.0", 3572 OIDCIssuerProfile: &OIDCIssuerProfile{ 3573 Enabled: ptr.To(true), 3574 }, 3575 SecurityProfile: &ManagedClusterSecurityProfile{ 3576 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3577 Enabled: true, 3578 }, 3579 }, 3580 }, 3581 }, 3582 }, 3583 amcp: &AzureManagedControlPlane{ 3584 Spec: AzureManagedControlPlaneSpec{ 3585 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3586 Version: "v1.18.0", 3587 OIDCIssuerProfile: &OIDCIssuerProfile{ 3588 Enabled: ptr.To(true), 3589 }, 3590 SecurityProfile: &ManagedClusterSecurityProfile{ 3591 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 3592 Enabled: false, 3593 }, 3594 }, 3595 }, 3596 }, 3597 }, 3598 wantErr: "", 3599 }, 3600 { 3601 name: "AzureManagedControlPlane SecurityProfile.AzureKeyVaultKms is mutable", 3602 oldAMCP: &AzureManagedControlPlane{ 3603 Spec: AzureManagedControlPlaneSpec{ 3604 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3605 Version: "v1.18.0", 3606 }, 3607 }, 3608 }, 3609 amcp: &AzureManagedControlPlane{ 3610 Spec: AzureManagedControlPlaneSpec{ 3611 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3612 Version: "v1.18.0", 3613 Identity: &Identity{ 3614 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3615 UserAssignedIdentityResourceID: "not empty", 3616 }, 3617 SecurityProfile: &ManagedClusterSecurityProfile{ 3618 AzureKeyVaultKms: &AzureKeyVaultKms{ 3619 Enabled: true, 3620 KeyID: "0000-0000-0000-0000", 3621 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 3622 KeyVaultResourceID: ptr.To("0000-0000-0000-0000"), 3623 }, 3624 }, 3625 }, 3626 }, 3627 }, 3628 wantErr: "", 3629 }, 3630 { 3631 name: "AzureManagedControlPlane SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess can be updated when KMS is enabled", 3632 oldAMCP: &AzureManagedControlPlane{ 3633 Spec: AzureManagedControlPlaneSpec{ 3634 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3635 Version: "v1.18.0", 3636 Identity: &Identity{ 3637 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3638 UserAssignedIdentityResourceID: "not empty", 3639 }, 3640 SecurityProfile: &ManagedClusterSecurityProfile{ 3641 AzureKeyVaultKms: &AzureKeyVaultKms{ 3642 Enabled: true, 3643 KeyID: "0000-0000-0000-0000", 3644 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3645 }, 3646 }, 3647 }, 3648 }, 3649 }, 3650 amcp: &AzureManagedControlPlane{ 3651 Spec: AzureManagedControlPlaneSpec{ 3652 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3653 Version: "v1.18.0", 3654 Identity: &Identity{ 3655 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3656 UserAssignedIdentityResourceID: "not empty", 3657 }, 3658 SecurityProfile: &ManagedClusterSecurityProfile{ 3659 AzureKeyVaultKms: &AzureKeyVaultKms{ 3660 Enabled: true, 3661 KeyID: "0000-0000-0000-0000", 3662 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 3663 KeyVaultResourceID: ptr.To("0000-0000-0000-0000"), 3664 }, 3665 }, 3666 }, 3667 }, 3668 }, 3669 wantErr: "", 3670 }, 3671 { 3672 name: "AzureManagedControlPlane SecurityProfile.AzureKeyVaultKms.Enabled can be disabled", 3673 oldAMCP: &AzureManagedControlPlane{ 3674 Spec: AzureManagedControlPlaneSpec{ 3675 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3676 Version: "v1.18.0", 3677 Identity: &Identity{ 3678 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3679 UserAssignedIdentityResourceID: "not empty", 3680 }, 3681 SecurityProfile: &ManagedClusterSecurityProfile{ 3682 AzureKeyVaultKms: &AzureKeyVaultKms{ 3683 Enabled: true, 3684 KeyID: "0000-0000-0000-0000", 3685 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3686 }, 3687 }, 3688 }, 3689 }, 3690 }, 3691 amcp: &AzureManagedControlPlane{ 3692 Spec: AzureManagedControlPlaneSpec{ 3693 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3694 Version: "v1.18.0", 3695 Identity: &Identity{ 3696 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3697 UserAssignedIdentityResourceID: "not empty", 3698 }, 3699 SecurityProfile: &ManagedClusterSecurityProfile{ 3700 AzureKeyVaultKms: &AzureKeyVaultKms{ 3701 Enabled: false, 3702 KeyID: "0000-0000-0000-0000", 3703 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3704 }, 3705 }, 3706 }, 3707 }, 3708 }, 3709 wantErr: "", 3710 }, 3711 { 3712 name: "AzureManagedControlPlane SecurityProfile.AzureKeyVaultKms cannot unset", 3713 oldAMCP: &AzureManagedControlPlane{ 3714 Spec: AzureManagedControlPlaneSpec{ 3715 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3716 Version: "v1.18.0", 3717 Identity: &Identity{ 3718 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3719 UserAssignedIdentityResourceID: "not empty", 3720 }, 3721 SecurityProfile: &ManagedClusterSecurityProfile{ 3722 AzureKeyVaultKms: &AzureKeyVaultKms{ 3723 Enabled: true, 3724 KeyID: "0000-0000-0000-0000", 3725 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPublic), 3726 }, 3727 }, 3728 }, 3729 }, 3730 }, 3731 amcp: &AzureManagedControlPlane{ 3732 Spec: AzureManagedControlPlaneSpec{ 3733 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3734 Version: "v1.18.0", 3735 Identity: &Identity{ 3736 Type: ManagedControlPlaneIdentityTypeUserAssigned, 3737 UserAssignedIdentityResourceID: "not empty", 3738 }, 3739 }, 3740 }, 3741 }, 3742 wantErr: "AzureManagedControlPlane.infrastructure.cluster.x-k8s.io \"\" is invalid: spec.securityProfile.azureKeyVaultKms: Invalid value: \"null\": cannot unset Spec.SecurityProfile.AzureKeyVaultKms profile to disable the profile please set Spec.SecurityProfile.AzureKeyVaultKms.Enabled to false", 3743 }, 3744 { 3745 name: "AzureManagedControlPlane SecurityProfile.AzureKeyVaultKms cannot be enabled without UserAssigned Identity", 3746 oldAMCP: &AzureManagedControlPlane{ 3747 Spec: AzureManagedControlPlaneSpec{ 3748 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3749 Version: "v1.18.0", 3750 }, 3751 }, 3752 }, 3753 amcp: &AzureManagedControlPlane{ 3754 Spec: AzureManagedControlPlaneSpec{ 3755 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3756 Version: "v1.18.0", 3757 SecurityProfile: &ManagedClusterSecurityProfile{ 3758 AzureKeyVaultKms: &AzureKeyVaultKms{ 3759 Enabled: true, 3760 KeyID: "0000-0000-0000-0000", 3761 KeyVaultNetworkAccess: ptr.To(KeyVaultNetworkAccessTypesPrivate), 3762 KeyVaultResourceID: ptr.To("0000-0000-0000-0000"), 3763 }, 3764 }, 3765 }, 3766 }, 3767 }, 3768 wantErr: "spec.securityProfile.azureKeyVaultKms.keyVaultResourceID: Invalid value: \"0000-0000-0000-0000\": Spec.SecurityProfile.AzureKeyVaultKms can be set only when Spec.Identity.Type is UserAssigned", 3769 }, 3770 { 3771 name: "AzureManagedControlPlane SecurityProfile.ImageCleaner is mutable", 3772 oldAMCP: &AzureManagedControlPlane{ 3773 Spec: AzureManagedControlPlaneSpec{ 3774 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3775 Version: "v1.18.0", 3776 }, 3777 }, 3778 }, 3779 amcp: &AzureManagedControlPlane{ 3780 Spec: AzureManagedControlPlaneSpec{ 3781 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3782 Version: "v1.18.0", 3783 SecurityProfile: &ManagedClusterSecurityProfile{ 3784 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3785 Enabled: true, 3786 IntervalHours: ptr.To(28), 3787 }, 3788 }, 3789 }, 3790 }, 3791 }, 3792 wantErr: "", 3793 }, 3794 { 3795 name: "AzureManagedControlPlane SecurityProfile.ImageCleaner cannot be unset", 3796 oldAMCP: &AzureManagedControlPlane{ 3797 Spec: AzureManagedControlPlaneSpec{ 3798 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3799 Version: "v1.18.0", 3800 SecurityProfile: &ManagedClusterSecurityProfile{ 3801 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3802 Enabled: true, 3803 IntervalHours: ptr.To(48), 3804 }, 3805 }, 3806 }, 3807 }, 3808 }, 3809 amcp: &AzureManagedControlPlane{ 3810 Spec: AzureManagedControlPlaneSpec{ 3811 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3812 Version: "v1.18.0", 3813 SecurityProfile: &ManagedClusterSecurityProfile{}, 3814 }, 3815 }, 3816 }, 3817 wantErr: "AzureManagedControlPlane.infrastructure.cluster.x-k8s.io \"\" is invalid: spec.securityProfile.imageCleaner: Invalid value: \"null\": cannot unset Spec.SecurityProfile.ImageCleaner, to disable imageCleaner please set Spec.SecurityProfile.ImageCleaner.Enabled to false", 3818 }, 3819 { 3820 name: "AzureManagedControlPlane SecurityProfile.ImageCleaner is mutable", 3821 oldAMCP: &AzureManagedControlPlane{ 3822 Spec: AzureManagedControlPlaneSpec{ 3823 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3824 Version: "v1.18.0", 3825 SecurityProfile: &ManagedClusterSecurityProfile{ 3826 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3827 Enabled: true, 3828 }, 3829 }, 3830 }, 3831 }, 3832 }, 3833 amcp: &AzureManagedControlPlane{ 3834 Spec: AzureManagedControlPlaneSpec{ 3835 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3836 Version: "v1.18.0", 3837 SecurityProfile: &ManagedClusterSecurityProfile{ 3838 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3839 IntervalHours: ptr.To(48), 3840 }, 3841 }, 3842 }, 3843 }, 3844 }, 3845 wantErr: "", 3846 }, 3847 { 3848 name: "AzureManagedControlPlane SecurityProfile.ImageCleaner can be disabled", 3849 oldAMCP: &AzureManagedControlPlane{ 3850 Spec: AzureManagedControlPlaneSpec{ 3851 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3852 Version: "v1.18.0", 3853 SecurityProfile: &ManagedClusterSecurityProfile{ 3854 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3855 Enabled: true, 3856 IntervalHours: ptr.To(48), 3857 }, 3858 }, 3859 }, 3860 }, 3861 }, 3862 amcp: &AzureManagedControlPlane{ 3863 Spec: AzureManagedControlPlaneSpec{ 3864 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 3865 Version: "v1.18.0", 3866 SecurityProfile: &ManagedClusterSecurityProfile{ 3867 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 3868 Enabled: false, 3869 IntervalHours: ptr.To(36), 3870 }, 3871 }, 3872 }, 3873 }, 3874 }, 3875 wantErr: "", 3876 }, 3877 } 3878 client := mockClient{ReturnError: false} 3879 for _, tc := range tests { 3880 t.Run(tc.name, func(t *testing.T) { 3881 g := NewWithT(t) 3882 mcpw := &azureManagedControlPlaneWebhook{ 3883 Client: client, 3884 } 3885 _, err := mcpw.ValidateUpdate(context.Background(), tc.oldAMCP, tc.amcp) 3886 if tc.wantErr != "" { 3887 g.Expect(err).To(HaveOccurred()) 3888 g.Expect(err.Error()).To(Equal(tc.wantErr)) 3889 } else { 3890 g.Expect(err).NotTo(HaveOccurred()) 3891 } 3892 }) 3893 } 3894 } 3895 3896 func TestValidateAPIServerAccessProfile(t *testing.T) { 3897 tests := []struct { 3898 name string 3899 profile *APIServerAccessProfile 3900 expectErr bool 3901 }{ 3902 { 3903 name: "Testing valid PrivateDNSZone:System", 3904 profile: &APIServerAccessProfile{ 3905 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3906 PrivateDNSZone: ptr.To("System"), 3907 }, 3908 }, 3909 expectErr: false, 3910 }, 3911 { 3912 name: "Testing valid PrivateDNSZone:None", 3913 profile: &APIServerAccessProfile{ 3914 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3915 PrivateDNSZone: ptr.To("None"), 3916 }, 3917 }, 3918 expectErr: false, 3919 }, 3920 { 3921 name: "Testing valid PrivateDNSZone:With privatelink region", 3922 profile: &APIServerAccessProfile{ 3923 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3924 EnablePrivateCluster: ptr.To(true), 3925 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io"), 3926 }, 3927 }, 3928 expectErr: false, 3929 }, 3930 { 3931 name: "Testing valid PrivateDNSZone:With private region", 3932 profile: &APIServerAccessProfile{ 3933 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3934 EnablePrivateCluster: ptr.To(true), 3935 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/private.eastus.azmk8s.io"), 3936 }, 3937 }, 3938 expectErr: false, 3939 }, 3940 { 3941 name: "Testing invalid EnablePrivateCluster and valid PrivateDNSZone", 3942 profile: &APIServerAccessProfile{ 3943 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3944 EnablePrivateCluster: ptr.To(false), 3945 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/private.eastus.azmk8s.io"), 3946 }, 3947 }, 3948 expectErr: true, 3949 }, 3950 { 3951 name: "Testing valid PrivateDNSZone:With privatelink region and sub-region", 3952 profile: &APIServerAccessProfile{ 3953 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3954 EnablePrivateCluster: ptr.To(true), 3955 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/sublocation2.privatelink.eastus.azmk8s.io"), 3956 }, 3957 }, 3958 expectErr: false, 3959 }, 3960 { 3961 name: "Testing valid PrivateDNSZone:With private region and sub-region", 3962 profile: &APIServerAccessProfile{ 3963 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3964 EnablePrivateCluster: ptr.To(true), 3965 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/sublocation2.private.eastus.azmk8s.io"), 3966 }, 3967 }, 3968 expectErr: false, 3969 }, 3970 { 3971 name: "Testing invalid PrivateDNSZone: privatelink region: len(sub-region) > 32 characters", 3972 profile: &APIServerAccessProfile{ 3973 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3974 EnablePrivateCluster: ptr.To(true), 3975 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/thissublocationismorethan32characters.privatelink.eastus.azmk8s.io"), 3976 }, 3977 }, 3978 expectErr: true, 3979 }, 3980 { 3981 name: "Testing invalid PrivateDNSZone: private region: len(sub-region) > 32 characters", 3982 profile: &APIServerAccessProfile{ 3983 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3984 EnablePrivateCluster: ptr.To(true), 3985 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/thissublocationismorethan32characters.private.eastus.azmk8s.io"), 3986 }, 3987 }, 3988 expectErr: true, 3989 }, 3990 { 3991 name: "Testing invalid PrivateDNSZone: random string", 3992 profile: &APIServerAccessProfile{ 3993 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 3994 EnablePrivateCluster: ptr.To(true), 3995 PrivateDNSZone: ptr.To("WrongPrivateDNSZone"), 3996 }, 3997 }, 3998 expectErr: true, 3999 }, 4000 { 4001 name: "Testing invalid PrivateDNSZone: subzone has an invalid char %", 4002 profile: &APIServerAccessProfile{ 4003 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 4004 EnablePrivateCluster: ptr.To(true), 4005 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/subzone%1.privatelink.eastus.azmk8s.io"), 4006 }, 4007 }, 4008 expectErr: true, 4009 }, 4010 { 4011 name: "Testing invalid PrivateDNSZone: subzone has an invalid char _", 4012 profile: &APIServerAccessProfile{ 4013 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 4014 EnablePrivateCluster: ptr.To(true), 4015 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/subzone_1.privatelink.eastus.azmk8s.io"), 4016 }, 4017 }, 4018 expectErr: true, 4019 }, 4020 { 4021 name: "Testing invalid PrivateDNSZone: region has invalid char", 4022 profile: &APIServerAccessProfile{ 4023 APIServerAccessProfileClassSpec: APIServerAccessProfileClassSpec{ 4024 EnablePrivateCluster: ptr.To(true), 4025 PrivateDNSZone: ptr.To("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/privateDnsZones/subzone1.privatelink.location@1.azmk8s.io"), 4026 }, 4027 }, 4028 expectErr: true, 4029 }, 4030 } 4031 4032 for _, tc := range tests { 4033 t.Run(tc.name, func(t *testing.T) { 4034 g := NewWithT(t) 4035 errs := validateAPIServerAccessProfile(tc.profile, field.NewPath("profile")) 4036 if tc.expectErr { 4037 g.Expect(errs).To(HaveLen(1)) 4038 } else { 4039 g.Expect(errs).To(BeEmpty()) 4040 } 4041 }) 4042 } 4043 } 4044 4045 func TestValidateAMCPVirtualNetwork(t *testing.T) { 4046 tests := []struct { 4047 name string 4048 amcp *AzureManagedControlPlane 4049 wantErr string 4050 }{ 4051 { 4052 name: "Testing valid VirtualNetwork in same resource group", 4053 amcp: &AzureManagedControlPlane{ 4054 ObjectMeta: metav1.ObjectMeta{ 4055 Name: "fooName", 4056 Labels: map[string]string{ 4057 clusterv1.ClusterNameLabel: "fooCluster", 4058 }, 4059 }, 4060 Spec: AzureManagedControlPlaneSpec{ 4061 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4062 ResourceGroupName: "rg1", 4063 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4064 ResourceGroup: "rg1", 4065 Name: "vnet1", 4066 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4067 CIDRBlock: defaultAKSVnetCIDR, 4068 Subnet: ManagedControlPlaneSubnet{ 4069 Name: "subnet1", 4070 CIDRBlock: defaultAKSNodeSubnetCIDR, 4071 }, 4072 }, 4073 }, 4074 }, 4075 }, 4076 }, 4077 wantErr: "", 4078 }, 4079 { 4080 name: "Testing valid VirtualNetwork in different resource group", 4081 amcp: &AzureManagedControlPlane{ 4082 ObjectMeta: metav1.ObjectMeta{ 4083 Name: "fooName", 4084 Labels: map[string]string{ 4085 clusterv1.ClusterNameLabel: "fooCluster", 4086 }, 4087 }, 4088 Spec: AzureManagedControlPlaneSpec{ 4089 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4090 ResourceGroupName: "rg1", 4091 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4092 ResourceGroup: "rg2", 4093 Name: "vnet1", 4094 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4095 CIDRBlock: defaultAKSVnetCIDR, 4096 Subnet: ManagedControlPlaneSubnet{ 4097 Name: "subnet1", 4098 CIDRBlock: defaultAKSNodeSubnetCIDR, 4099 }, 4100 }, 4101 }, 4102 }, 4103 }, 4104 }, 4105 wantErr: "", 4106 }, 4107 { 4108 name: "Testing invalid VirtualNetwork in different resource group: invalid subnet CIDR", 4109 amcp: &AzureManagedControlPlane{ 4110 ObjectMeta: metav1.ObjectMeta{ 4111 Name: "fooName", 4112 Labels: map[string]string{ 4113 clusterv1.ClusterNameLabel: "fooCluster", 4114 }, 4115 }, 4116 Spec: AzureManagedControlPlaneSpec{ 4117 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4118 ResourceGroupName: "rg1", 4119 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4120 ResourceGroup: "rg2", 4121 Name: "vnet1", 4122 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4123 CIDRBlock: "10.1.0.0/16", 4124 Subnet: ManagedControlPlaneSubnet{ 4125 Name: "subnet1", 4126 CIDRBlock: "10.0.0.0/24", 4127 }, 4128 }, 4129 }, 4130 }, 4131 }, 4132 }, 4133 wantErr: "pre-existing virtual networks CIDR block should contain the subnet CIDR block", 4134 }, 4135 { 4136 name: "Testing invalid VirtualNetwork in different resource group: no subnet CIDR", 4137 amcp: &AzureManagedControlPlane{ 4138 ObjectMeta: metav1.ObjectMeta{ 4139 Name: "fooName", 4140 Labels: map[string]string{ 4141 clusterv1.ClusterNameLabel: "fooCluster", 4142 }, 4143 }, 4144 Spec: AzureManagedControlPlaneSpec{ 4145 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4146 ResourceGroupName: "rg1", 4147 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4148 ResourceGroup: "rg2", 4149 Name: "vnet1", 4150 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4151 CIDRBlock: "10.1.0.0/16", 4152 Subnet: ManagedControlPlaneSubnet{ 4153 Name: "subnet1", 4154 }, 4155 }, 4156 }, 4157 }, 4158 }, 4159 }, 4160 wantErr: "pre-existing virtual networks CIDR block should contain the subnet CIDR block", 4161 }, 4162 { 4163 name: "Testing invalid VirtualNetwork in different resource group: no VNet CIDR", 4164 amcp: &AzureManagedControlPlane{ 4165 ObjectMeta: metav1.ObjectMeta{ 4166 Name: "fooName", 4167 Labels: map[string]string{ 4168 clusterv1.ClusterNameLabel: "fooCluster", 4169 }, 4170 }, 4171 Spec: AzureManagedControlPlaneSpec{ 4172 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4173 ResourceGroupName: "rg1", 4174 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4175 ResourceGroup: "rg2", 4176 Name: "vnet1", 4177 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4178 Subnet: ManagedControlPlaneSubnet{ 4179 Name: "subnet1", 4180 CIDRBlock: "11.0.0.0/24", 4181 }, 4182 }, 4183 }, 4184 }, 4185 }, 4186 }, 4187 wantErr: "pre-existing virtual networks CIDR block should contain the subnet CIDR block", 4188 }, 4189 { 4190 name: "Testing invalid VirtualNetwork in different resource group: invalid VNet CIDR", 4191 amcp: &AzureManagedControlPlane{ 4192 ObjectMeta: metav1.ObjectMeta{ 4193 Name: "fooName", 4194 Labels: map[string]string{ 4195 clusterv1.ClusterNameLabel: "fooCluster", 4196 }, 4197 }, 4198 Spec: AzureManagedControlPlaneSpec{ 4199 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4200 ResourceGroupName: "rg1", 4201 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4202 ResourceGroup: "rg2", 4203 Name: "vnet1", 4204 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4205 CIDRBlock: "invalid_vnet_CIDR", 4206 Subnet: ManagedControlPlaneSubnet{ 4207 Name: "subnet1", 4208 CIDRBlock: "11.0.0.0/24", 4209 }, 4210 }, 4211 }, 4212 }, 4213 }, 4214 }, 4215 wantErr: "pre-existing virtual networks CIDR block is invalid", 4216 }, 4217 { 4218 name: "Testing invalid VirtualNetwork in different resource group: invalid Subnet CIDR", 4219 amcp: &AzureManagedControlPlane{ 4220 ObjectMeta: metav1.ObjectMeta{ 4221 Name: "fooName", 4222 Labels: map[string]string{ 4223 clusterv1.ClusterNameLabel: "fooCluster", 4224 }, 4225 }, 4226 Spec: AzureManagedControlPlaneSpec{ 4227 AzureManagedControlPlaneClassSpec: AzureManagedControlPlaneClassSpec{ 4228 ResourceGroupName: "rg1", 4229 VirtualNetwork: ManagedControlPlaneVirtualNetwork{ 4230 ResourceGroup: "rg2", 4231 Name: "vnet1", 4232 ManagedControlPlaneVirtualNetworkClassSpec: ManagedControlPlaneVirtualNetworkClassSpec{ 4233 Subnet: ManagedControlPlaneSubnet{ 4234 Name: "subnet1", 4235 CIDRBlock: "invalid_subnet_CIDR", 4236 }, 4237 }, 4238 }, 4239 }, 4240 }, 4241 }, 4242 wantErr: "pre-existing subnets CIDR block is invalid", 4243 }, 4244 } 4245 4246 for _, tc := range tests { 4247 t.Run(tc.name, func(t *testing.T) { 4248 g := NewWithT(t) 4249 mcpw := &azureManagedControlPlaneWebhook{} 4250 err := mcpw.Default(context.Background(), tc.amcp) 4251 g.Expect(err).NotTo(HaveOccurred()) 4252 4253 errs := validateAMCPVirtualNetwork(tc.amcp.Spec.VirtualNetwork, field.NewPath("spec", "virtualNetwork")) 4254 if tc.wantErr != "" { 4255 g.Expect(errs).ToNot(BeEmpty()) 4256 g.Expect(errs[0].Detail).To(Equal(tc.wantErr)) 4257 } else { 4258 g.Expect(err).NotTo(HaveOccurred()) 4259 } 4260 }) 4261 } 4262 }