diff --git a/api/v1beta1/azuremanagedcontrolplane_webhook_test.go b/api/v1beta1/azuremanagedcontrolplane_webhook_test.go index c62161c6906..74e93ef1684 100644 --- a/api/v1beta1/azuremanagedcontrolplane_webhook_test.go +++ b/api/v1beta1/azuremanagedcontrolplane_webhook_test.go @@ -21,6 +21,7 @@ import ( . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/pointer" "sigs.k8s.io/cluster-api-provider-azure/feature" @@ -78,471 +79,362 @@ func TestDefaultingWebhook(t *testing.T) { g.Expect(amcp.Spec.SKU.Tier).To(Equal(PaidManagedControlPlaneTier)) } -func TestValidatingWebhook(t *testing.T) { - // NOTE: AzureManageControlPlane is behind AKS feature gate flag; the webhook - // must prevent creating new objects in case the feature flag is disabled. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, capifeature.MachinePool, true)() +func TestValidateDNSServiceIP(t *testing.T) { g := NewWithT(t) tests := []struct { name string - amcp AzureManagedControlPlane + dnsIP *string expectErr bool }{ { - name: "Testing valid DNSServiceIP", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "v1.17.8", - }, - }, + name: "Testing valid DNSServiceIP", + dnsIP: pointer.String("192.168.0.0"), expectErr: false, }, { - name: "Testing invalid DNSServiceIP", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0.3"), - Version: "v1.17.8", - }, - }, - expectErr: true, + name: "Testing invalid DNSServiceIP", + dnsIP: pointer.String("192.168.0.0.3"), + expectErr: false, }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + allErrs := validateDNSServiceIP(tt.dnsIP, field.NewPath("spec").Child("DNSServiceIP")) + if tt.expectErr { + g.Expect(allErrs).NotTo(BeNil()) + } else { + g.Expect(allErrs).To(BeNil()) + } + }) + } +} + +func TestValidateVersion(t *testing.T) { + g := NewWithT(t) + tests := []struct { + name string + version string + expectErr bool + }{ { - name: "Invalid Version", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "honk", - }, - }, + name: "Invalid Version", + version: "honk", expectErr: true, }, { - name: "not following the Kubernetes Version pattern", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "1.19.0", - }, - }, + name: "not following the Kubernetes Version pattern", + version: "1.19.0", expectErr: true, }, { - name: "Version not set", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "", - }, - }, + name: "Version not set", + version: "", expectErr: true, }, { - name: "Valid Version", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "v1.17.8", - }, - }, - expectErr: false, - }, - { - name: "Valid Managed AADProfile", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - AADProfile: &AADProfile{ - Managed: true, - AdminGroupObjectIDs: []string{ - "616077a8-5db7-4c98-b856-b34619afg75h", - }, - }, - }, - }, + name: "Valid Version", + version: "v1.17.8", expectErr: false, }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + allErrs := validateVersion(tt.version, field.NewPath("spec").Child("Version")) + if tt.expectErr { + g.Expect(allErrs).NotTo(BeNil()) + } else { + g.Expect(allErrs).To(BeNil()) + } + }) + } +} + +func TestValidateLoadBalancerProfile(t *testing.T) { + g := NewWithT(t) + tests := []struct { + name string + profile *LoadBalancerProfile + expectErr bool + }{ { name: "Valid LoadBalancerProfile", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(10), - AllocatedOutboundPorts: pointer.Int32(1000), - IdleTimeoutInMinutes: pointer.Int32(60), - }, - }, + profile: &LoadBalancerProfile{ + ManagedOutboundIPs: pointer.Int32(10), + AllocatedOutboundPorts: pointer.Int32(1000), + IdleTimeoutInMinutes: pointer.Int32(60), }, expectErr: false, }, { name: "Invalid LoadBalancerProfile.ManagedOutboundIPs", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(200), - }, - }, - }, - expectErr: true, - }, - { - name: "Invalid LoadBalancerProfile.AllocatedOutboundPorts", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - AllocatedOutboundPorts: pointer.Int32(80000), - }, - }, + profile: &LoadBalancerProfile{ + ManagedOutboundIPs: pointer.Int32(200), }, expectErr: true, }, { name: "Invalid LoadBalancerProfile.IdleTimeoutInMinutes", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - IdleTimeoutInMinutes: pointer.Int32(600), - }, - }, + profile: &LoadBalancerProfile{ + IdleTimeoutInMinutes: pointer.Int32(600), }, expectErr: true, }, { name: "LoadBalancerProfile must specify at most one of ManagedOutboundIPs, OutboundIPPrefixes and OutboundIPs", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(1), - OutboundIPs: []string{ - "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo-bar/providers/Microsoft.Network/publicIPAddresses/my-public-ip", - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Invalid CIDR for AuthorizedIPRanges", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.21.2", - APIServerAccessProfile: &APIServerAccessProfile{ - AuthorizedIPRanges: []string{"1.2.3.400/32"}, - }, + profile: &LoadBalancerProfile{ + ManagedOutboundIPs: pointer.Int32(1), + OutboundIPs: []string{ + "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo-bar/providers/Microsoft.Network/publicIPAddresses/my-public-ip", }, }, expectErr: true, }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + allErrs := validateLoadBalancerProfile(tt.profile, field.NewPath("spec").Child("LoadBalancerProfile")) + if tt.expectErr { + g.Expect(allErrs).NotTo(BeNil()) + } else { + g.Expect(allErrs).To(BeNil()) + } + }) + } +} + +func TestValidateAutoScalerProfile(t *testing.T) { + g := NewWithT(t) + tests := []struct { + name string + profile *AutoScalerProfile + expectErr bool + }{ { - name: "Testing valid AutoScalerProfile", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), - Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - MaxEmptyBulkDelete: pointer.String("10"), - MaxGracefulTerminationSec: pointer.String("600"), - MaxNodeProvisionTime: pointer.String("10m"), - MaxTotalUnreadyPercentage: pointer.String("45"), - NewPodScaleUpDelay: pointer.String("10m"), - OkTotalUnreadyCount: pointer.String("3"), - ScanInterval: pointer.String("60s"), - ScaleDownDelayAfterAdd: pointer.String("10m"), - ScaleDownDelayAfterDelete: pointer.String("10s"), - ScaleDownDelayAfterFailure: pointer.String("10m"), - ScaleDownUnneededTime: pointer.String("10m"), - ScaleDownUnreadyTime: pointer.String("10m"), - ScaleDownUtilizationThreshold: pointer.String("0.5"), - SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), - SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsTrue))), - }, - }, + name: "Valid AutoScalerProfile", + profile: &AutoScalerProfile{ + BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), + Expander: (*Expander)(pointer.String(string(ExpanderRandom))), + MaxEmptyBulkDelete: pointer.String("10"), + MaxGracefulTerminationSec: pointer.String("600"), + MaxNodeProvisionTime: pointer.String("10m"), + MaxTotalUnreadyPercentage: pointer.String("45"), + NewPodScaleUpDelay: pointer.String("10m"), + OkTotalUnreadyCount: pointer.String("3"), + ScanInterval: pointer.String("60s"), + ScaleDownDelayAfterAdd: pointer.String("10m"), + ScaleDownDelayAfterDelete: pointer.String("10s"), + ScaleDownDelayAfterFailure: pointer.String("10m"), + ScaleDownUnneededTime: pointer.String("10m"), + ScaleDownUnreadyTime: pointer.String("10m"), + ScaleDownUtilizationThreshold: pointer.String("0.5"), + SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), + SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsTrue))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.ExpanderRandom", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - }, - }, + profile: &AutoScalerProfile{ + Expander: (*Expander)(pointer.String(string(ExpanderRandom))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.ExpanderLeastWaste", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - Expander: (*Expander)(pointer.String(string(ExpanderLeastWaste))), - }, - }, + profile: &AutoScalerProfile{ + Expander: (*Expander)(pointer.String(string(ExpanderLeastWaste))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.ExpanderMostPods", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - Expander: (*Expander)(pointer.String(string(ExpanderMostPods))), - }, - }, + profile: &AutoScalerProfile{ + Expander: (*Expander)(pointer.String(string(ExpanderMostPods))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.ExpanderPriority", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - Expander: (*Expander)(pointer.String(string(ExpanderPriority))), - }, - }, + profile: &AutoScalerProfile{ + Expander: (*Expander)(pointer.String(string(ExpanderPriority))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsTrue", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsTrue))), - }, - }, + profile: &AutoScalerProfile{ + BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsTrue))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsFalse", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), - }, - }, + profile: &AutoScalerProfile{ + BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), }, expectErr: false, }, { name: "Testing invalid AutoScalerProfile.MaxEmptyBulkDelete", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - MaxEmptyBulkDelete: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + MaxEmptyBulkDelete: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.MaxGracefulTerminationSec", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - MaxGracefulTerminationSec: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + MaxGracefulTerminationSec: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.MaxNodeProvisionTime", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - MaxNodeProvisionTime: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + MaxNodeProvisionTime: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.MaxTotalUnreadyPercentage", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - MaxTotalUnreadyPercentage: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + MaxTotalUnreadyPercentage: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.NewPodScaleUpDelay", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - NewPodScaleUpDelay: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + NewPodScaleUpDelay: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.OkTotalUnreadyCount", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - OkTotalUnreadyCount: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + OkTotalUnreadyCount: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScanInterval", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScanInterval: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScanInterval: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterAdd", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownDelayAfterAdd: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownDelayAfterAdd: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterDelete", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownDelayAfterDelete: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownDelayAfterDelete: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterFailure", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownDelayAfterFailure: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownDelayAfterFailure: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownUnneededTime", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownUnneededTime: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownUnneededTime: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownUnreadyTime", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownUnreadyTime: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownUnreadyTime: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing invalid AutoScalerProfile.ScaleDownUtilizationThreshold", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - ScaleDownUtilizationThreshold: pointer.String("invalid"), - }, - }, + profile: &AutoScalerProfile{ + ScaleDownUtilizationThreshold: pointer.String("invalid"), }, expectErr: true, }, { name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageTrue", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), - }, - }, + profile: &AutoScalerProfile{ + SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), }, expectErr: false, }, { name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageFalse", - amcp: AzureManagedControlPlane{ - Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageFalse))), - }, - }, + profile: &AutoScalerProfile{ + SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsFalse))), }, expectErr: false, }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + allErrs := validateAutoScalerProfile(tt.profile, field.NewPath("spec").Child("AutoScalerProfile")) + if tt.expectErr { + g.Expect(allErrs).NotTo(BeNil()) + } else { + g.Expect(allErrs).To(BeNil()) + } + }) + } +} + +func TestValidatingWebhook(t *testing.T) { + // NOTE: AzureManageControlPlane is behind AKS feature gate flag; the webhook + // must prevent creating new objects in case the feature flag is disabled. + defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, capifeature.MachinePool, true)() + g := NewWithT(t) + tests := []struct { + name string + amcp AzureManagedControlPlane + expectErr bool + }{ { - name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsTrue", + name: "Valid Managed AADProfile", amcp: AzureManagedControlPlane{ Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsTrue))), + Version: "v1.21.2", + AADProfile: &AADProfile{ + Managed: true, + AdminGroupObjectIDs: []string{ + "616077a8-5db7-4c98-b856-b34619afg75h", + }, }, }, }, expectErr: false, }, { - name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsFalse", + name: "Invalid CIDR for AuthorizedIPRanges", amcp: AzureManagedControlPlane{ Spec: AzureManagedControlPlaneSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsFalse))), + Version: "v1.21.2", + APIServerAccessProfile: &APIServerAccessProfile{ + AuthorizedIPRanges: []string{"1.2.3.400/32"}, }, }, }, - expectErr: false, + expectErr: true, }, } diff --git a/api/v1beta1/azuremanagedcontrolplanetemplate_webhook_test.go b/api/v1beta1/azuremanagedcontrolplanetemplate_webhook_test.go index e4e3c88ae4b..c7979ac8e40 100644 --- a/api/v1beta1/azuremanagedcontrolplanetemplate_webhook_test.go +++ b/api/v1beta1/azuremanagedcontrolplanetemplate_webhook_test.go @@ -20,567 +20,9 @@ import ( "testing" . "github.com/onsi/gomega" - utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/pointer" - "sigs.k8s.io/cluster-api-provider-azure/feature" - capifeature "sigs.k8s.io/cluster-api/feature" ) -func TestTemplateValidatingWebhook(t *testing.T) { - // NOTE: AzureManageControlPlane is behind AKS feature gate flag; the webhook - // must prevent creating new objects in case the feature flag is disabled. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, capifeature.MachinePool, true)() - g := NewWithT(t) - tests := []struct { - name string - amcpt AzureManagedControlPlaneTemplate - expectErr bool - }{ - { - name: "Testing valid DNSServiceIP", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "v1.17.8", - }, - }, - }, - }, - expectErr: false, - }, - { - name: "Testing invalid DNSServiceIP", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0.3"), - Version: "v1.17.8", - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Invalid Version", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "honk", - }, - }, - }, - }, - expectErr: true, - }, - { - name: "not following the Kubernetes Version pattern", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "1.19.0", - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Version not set", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "", - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Valid Version", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - DNSServiceIP: pointer.String("192.168.0.0"), - Version: "v1.17.8", - }, - }, - }, - }, - expectErr: false, - }, - { - name: "Valid LoadBalancerProfile", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(10), - AllocatedOutboundPorts: pointer.Int32(1000), - IdleTimeoutInMinutes: pointer.Int32(60), - }, - }, - }, - }, - }, - expectErr: false, - }, - { - name: "Invalid LoadBalancerProfile.ManagedOutboundIPs", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(200), - }, - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Invalid LoadBalancerProfile.AllocatedOutboundPorts", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - AllocatedOutboundPorts: pointer.Int32(80000), - }, - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Invalid LoadBalancerProfile.IdleTimeoutInMinutes", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - IdleTimeoutInMinutes: pointer.Int32(600), - }, - }, - }, - }, - }, - expectErr: true, - }, - { - name: "LoadBalancerProfile must specify at most one of ManagedOutboundIPs, OutboundIPPrefixes and OutboundIPs", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.21.2", - LoadBalancerProfile: &LoadBalancerProfile{ - ManagedOutboundIPs: pointer.Int32(1), - OutboundIPs: []string{ - "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo-bar/providers/Microsoft.Network/publicIPAddresses/my-public-ip", - }, - }, - }, - }, - }, - }, - expectErr: true, - }, - { - name: "Testing valid AutoScalerProfile", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), - Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - MaxEmptyBulkDelete: pointer.String("10"), - MaxGracefulTerminationSec: pointer.String("600"), - MaxNodeProvisionTime: pointer.String("10m"), - MaxTotalUnreadyPercentage: pointer.String("45"), - NewPodScaleUpDelay: pointer.String("10m"), - OkTotalUnreadyCount: pointer.String("3"), - ScanInterval: pointer.String("60s"), - ScaleDownDelayAfterAdd: pointer.String("10m"), - ScaleDownDelayAfterDelete: pointer.String("10s"), - ScaleDownDelayAfterFailure: pointer.String("10m"), - ScaleDownUnneededTime: pointer.String("10m"), - ScaleDownUnreadyTime: pointer.String("10m"), - ScaleDownUtilizationThreshold: pointer.String("0.5"), - SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), - SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsTrue))), - }, - }, - }, - }, - }, - expectErr: false, - }, - { - name: "Testing valid AutoScalerProfile.ExpanderRandom", - amcpt: AzureManagedControlPlaneTemplate{ - Spec: AzureManagedControlPlaneTemplateSpec{ - Template: AzureManagedControlPlaneTemplateResource{ - Spec: AzureManagedControlPlaneTemplateResourceSpec{ - Version: "v1.24.1", - AutoScalerProfile: &AutoScalerProfile{ - Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - }, - }, - }, - }, - }, - expectErr: false, - }, - // { - // name: "Testing valid AutoScalerProfile.ExpanderLeastWaste", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderLeastWaste))), - // }, - // }, - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Template: AzureManagedControlPlaneTemplateResource{ - // Spec: AzureManagedControlPlaneTemplateResourceSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - // }, - // }, - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.ExpanderMostPods", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderMostPods))), - // }, - // }, - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Template: AzureManagedControlPlaneTemplateResource{ - // Spec: AzureManagedControlPlaneTemplateResourceSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - // }, - // }, - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.ExpanderPriority", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderPriority))), - // }, - // }, - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Template: AzureManagedControlPlaneTemplateResource{ - // Spec: AzureManagedControlPlaneTemplateResourceSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - // }, - // }, - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsTrue", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsTrue))), - // }, - // }, - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Template: AzureManagedControlPlaneTemplateResource{ - // Spec: AzureManagedControlPlaneTemplateResourceSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - // }, - // }, - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.BalanceSimilarNodeGroupsFalse", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // BalanceSimilarNodeGroups: (*BalanceSimilarNodeGroups)(pointer.String(string(BalanceSimilarNodeGroupsFalse))), - // }, - // }, - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Template: AzureManagedControlPlaneTemplateResource{ - // Spec: AzureManagedControlPlaneTemplateResourceSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // Expander: (*Expander)(pointer.String(string(ExpanderRandom))), - // }, - // }, - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing invalid AutoScalerProfile.MaxEmptyBulkDelete", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // MaxEmptyBulkDelete: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.MaxGracefulTerminationSec", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // MaxGracefulTerminationSec: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.MaxNodeProvisionTime", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // MaxNodeProvisionTime: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.MaxTotalUnreadyPercentage", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // MaxTotalUnreadyPercentage: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.NewPodScaleUpDelay", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // NewPodScaleUpDelay: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.OkTotalUnreadyCount", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // OkTotalUnreadyCount: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScanInterval", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScanInterval: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterAdd", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownDelayAfterAdd: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterDelete", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownDelayAfterDelete: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownDelayAfterFailure", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownDelayAfterFailure: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownUnneededTime", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownUnneededTime: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownUnreadyTime", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownUnreadyTime: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing invalid AutoScalerProfile.ScaleDownUtilizationThreshold", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // ScaleDownUtilizationThreshold: pointer.String("invalid"), - // }, - // }, - // }, - // expectErr: true, - // }, - // { - // name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageTrue", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageTrue))), - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.SkipNodesWithLocalStorageFalse", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // SkipNodesWithLocalStorage: (*SkipNodesWithLocalStorage)(pointer.String(string(SkipNodesWithLocalStorageFalse))), - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsTrue", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsTrue))), - // }, - // }, - // }, - // expectErr: false, - // }, - // { - // name: "Testing valid AutoScalerProfile.SkipNodesWithSystemPodsFalse", - // amcpt: AzureManagedControlPlaneTemplate{ - // Spec: AzureManagedControlPlaneTemplateSpec{ - // Version: "v1.24.1", - // AutoScalerProfile: &AutoScalerProfile{ - // SkipNodesWithSystemPods: (*SkipNodesWithSystemPods)(pointer.String(string(SkipNodesWithSystemPodsFalse))), - // }, - // }, - // }, - // expectErr: false, - // }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - if tt.expectErr { - g.Expect(tt.amcpt.ValidateCreate(nil)).NotTo(Succeed()) - } else { - g.Expect(tt.amcpt.ValidateCreate(nil)).To(Succeed()) - } - }) - } -} - func TestAzureManagedControlPlaneTemplateTemplateValidateUpdate(t *testing.T) { oldManagedControlPlaneTemplate := &AzureManagedControlPlaneTemplate{