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