sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/managedclusters/spec_test.go (about) 1 /* 2 Copyright 2022 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 managedclusters 18 19 import ( 20 "context" 21 "encoding/base64" 22 "testing" 23 24 asocontainerservicev1preview "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20230202preview" 25 asocontainerservicev1 "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231001" 26 "github.com/Azure/azure-service-operator/v2/pkg/genruntime" 27 "github.com/google/go-cmp/cmp" 28 . "github.com/onsi/gomega" 29 "k8s.io/utils/ptr" 30 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 31 "sigs.k8s.io/cluster-api-provider-azure/azure" 32 "sigs.k8s.io/cluster-api-provider-azure/azure/services/agentpools" 33 "sigs.k8s.io/cluster-api/util/secret" 34 ) 35 36 func TestParameters(t *testing.T) { 37 t.Run("no existing managed cluster", func(t *testing.T) { 38 g := NewGomegaWithT(t) 39 40 spec := &ManagedClusterSpec{ 41 Name: "name", 42 ResourceGroup: "rg", 43 NodeResourceGroup: "node rg", 44 ClusterName: "cluster", 45 VnetSubnetID: "vnet subnet id", 46 Location: "location", 47 Tags: map[string]string{"additional": "tags"}, 48 Version: "version", 49 LoadBalancerSKU: "lb sku", 50 NetworkPlugin: "network plugin", 51 NetworkPluginMode: ptr.To(infrav1.NetworkPluginMode("network plugin mode")), 52 NetworkPolicy: "network policy", 53 OutboundType: ptr.To(infrav1.ManagedControlPlaneOutboundType("outbound type")), 54 SSHPublicKey: base64.StdEncoding.EncodeToString([]byte("ssh")), 55 GetAllAgentPools: func() ([]azure.ASOResourceSpecGetter[genruntime.MetaObject], error) { 56 return []azure.ASOResourceSpecGetter[genruntime.MetaObject]{ 57 &agentpools.AgentPoolSpec{ 58 Replicas: 5, 59 Mode: "mode", 60 AzureName: "agentpool", 61 Patches: []string{`{"spec": {"tags": {"from": "patches"}}}`}, 62 }, 63 }, nil 64 }, 65 PodCIDR: "pod cidr", 66 ServiceCIDR: "0.0.0.0/10", 67 DNSServiceIP: nil, 68 AddonProfiles: []AddonProfile{ 69 { 70 Name: "addon name", 71 Enabled: true, 72 Config: map[string]string{"addon": "config"}, 73 }, 74 }, 75 AADProfile: &AADProfile{ 76 Managed: true, 77 }, 78 SKU: &SKU{ 79 Tier: "sku tier", 80 }, 81 LoadBalancerProfile: &LoadBalancerProfile{ 82 ManagedOutboundIPs: ptr.To(16), 83 OutboundIPPrefixes: []string{"outbound ip prefixes"}, 84 OutboundIPs: []string{"outbound ips"}, 85 }, 86 APIServerAccessProfile: &APIServerAccessProfile{ 87 AuthorizedIPRanges: []string{"authorized ip ranges"}, 88 }, 89 AutoScalerProfile: &AutoScalerProfile{ 90 Expander: ptr.To("expander"), 91 }, 92 AutoUpgradeProfile: &ManagedClusterAutoUpgradeProfile{ 93 UpgradeChannel: ptr.To(infrav1.UpgradeChannelRapid), 94 }, 95 Identity: &infrav1.Identity{ 96 Type: infrav1.ManagedControlPlaneIdentityType(asocontainerservicev1.ManagedClusterIdentity_Type_UserAssigned), 97 UserAssignedIdentityResourceID: "user assigned id", 98 }, 99 KubeletUserAssignedIdentity: "kubelet id", 100 HTTPProxyConfig: &HTTPProxyConfig{ 101 NoProxy: []string{"noproxy"}, 102 }, 103 OIDCIssuerProfile: &OIDCIssuerProfile{ 104 Enabled: ptr.To(true), 105 }, 106 DNSPrefix: ptr.To("dns prefix"), 107 DisableLocalAccounts: ptr.To(true), 108 SecurityProfile: &ManagedClusterSecurityProfile{ 109 AzureKeyVaultKms: &AzureKeyVaultKms{ 110 Enabled: ptr.To(true), 111 KeyID: ptr.To("KeyID"), 112 KeyVaultNetworkAccess: ptr.To(infrav1.KeyVaultNetworkAccessTypesPublic), 113 }, 114 Defender: &ManagedClusterSecurityProfileDefender{ 115 LogAnalyticsWorkspaceResourceID: ptr.To("LogAnalyticsWorkspaceResourceID"), 116 SecurityMonitoring: &ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 117 Enabled: ptr.To(true), 118 }, 119 }, 120 ImageCleaner: &ManagedClusterSecurityProfileImageCleaner{ 121 Enabled: ptr.To(true), 122 IntervalHours: ptr.To(24), 123 }, 124 WorkloadIdentity: &ManagedClusterSecurityProfileWorkloadIdentity{ 125 Enabled: ptr.To(true), 126 }, 127 }, 128 } 129 130 expected := &asocontainerservicev1.ManagedCluster{ 131 Spec: asocontainerservicev1.ManagedCluster_Spec{ 132 AadProfile: &asocontainerservicev1.ManagedClusterAADProfile{ 133 EnableAzureRBAC: ptr.To(false), 134 Managed: ptr.To(true), 135 }, 136 AddonProfiles: map[string]asocontainerservicev1.ManagedClusterAddonProfile{ 137 "addon name": { 138 Config: map[string]string{"addon": "config"}, 139 Enabled: ptr.To(true), 140 }, 141 }, 142 AgentPoolProfiles: []asocontainerservicev1.ManagedClusterAgentPoolProfile{ 143 { 144 Count: ptr.To(5), 145 EnableAutoScaling: ptr.To(false), 146 Mode: ptr.To(asocontainerservicev1.AgentPoolMode("mode")), 147 Name: ptr.To("agentpool"), 148 OsDiskSizeGB: ptr.To(asocontainerservicev1.ContainerServiceOSDisk(0)), 149 Type: ptr.To(asocontainerservicev1.AgentPoolType_VirtualMachineScaleSets), 150 Tags: map[string]string{"from": "patches"}, 151 }, 152 }, 153 ApiServerAccessProfile: &asocontainerservicev1.ManagedClusterAPIServerAccessProfile{ 154 AuthorizedIPRanges: []string{"authorized ip ranges"}, 155 }, 156 AutoScalerProfile: &asocontainerservicev1.ManagedClusterProperties_AutoScalerProfile{ 157 Expander: ptr.To(asocontainerservicev1.ManagedClusterProperties_AutoScalerProfile_Expander("expander")), 158 }, 159 AutoUpgradeProfile: &asocontainerservicev1.ManagedClusterAutoUpgradeProfile{ 160 UpgradeChannel: ptr.To(asocontainerservicev1.ManagedClusterAutoUpgradeProfile_UpgradeChannel_Rapid), 161 }, 162 AzureName: "name", 163 DisableLocalAccounts: ptr.To(true), 164 DnsPrefix: ptr.To("dns prefix"), 165 EnableRBAC: ptr.To(true), 166 HttpProxyConfig: &asocontainerservicev1.ManagedClusterHTTPProxyConfig{ 167 NoProxy: []string{"noproxy"}, 168 }, 169 Identity: &asocontainerservicev1.ManagedClusterIdentity{ 170 Type: ptr.To(asocontainerservicev1.ManagedClusterIdentity_Type_UserAssigned), 171 UserAssignedIdentities: []asocontainerservicev1.UserAssignedIdentityDetails{ 172 { 173 Reference: genruntime.ResourceReference{ 174 ARMID: "user assigned id", 175 }, 176 }, 177 }, 178 }, 179 IdentityProfile: map[string]asocontainerservicev1.UserAssignedIdentity{ 180 kubeletIdentityKey: { 181 ResourceReference: &genruntime.ResourceReference{ 182 ARMID: "kubelet id", 183 }, 184 }, 185 }, 186 KubernetesVersion: ptr.To("version"), 187 LinuxProfile: &asocontainerservicev1.ContainerServiceLinuxProfile{ 188 AdminUsername: ptr.To(azure.DefaultAKSUserName), 189 Ssh: &asocontainerservicev1.ContainerServiceSshConfiguration{ 190 PublicKeys: []asocontainerservicev1.ContainerServiceSshPublicKey{ 191 { 192 KeyData: ptr.To("ssh"), 193 }, 194 }, 195 }, 196 }, 197 Location: ptr.To("location"), 198 NetworkProfile: &asocontainerservicev1.ContainerServiceNetworkProfile{ 199 DnsServiceIP: ptr.To("0.0.0.10"), 200 LoadBalancerProfile: &asocontainerservicev1.ManagedClusterLoadBalancerProfile{ 201 ManagedOutboundIPs: &asocontainerservicev1.ManagedClusterLoadBalancerProfile_ManagedOutboundIPs{ 202 Count: ptr.To(16), 203 }, 204 OutboundIPPrefixes: &asocontainerservicev1.ManagedClusterLoadBalancerProfile_OutboundIPPrefixes{ 205 PublicIPPrefixes: []asocontainerservicev1.ResourceReference{ 206 { 207 Reference: &genruntime.ResourceReference{ 208 ARMID: "outbound ip prefixes", 209 }, 210 }, 211 }, 212 }, 213 OutboundIPs: &asocontainerservicev1.ManagedClusterLoadBalancerProfile_OutboundIPs{ 214 PublicIPs: []asocontainerservicev1.ResourceReference{ 215 { 216 Reference: &genruntime.ResourceReference{ 217 ARMID: "outbound ips", 218 }, 219 }, 220 }, 221 }, 222 }, 223 LoadBalancerSku: ptr.To(asocontainerservicev1.ContainerServiceNetworkProfile_LoadBalancerSku("lb sku")), 224 NetworkPlugin: ptr.To(asocontainerservicev1.NetworkPlugin("network plugin")), 225 NetworkPluginMode: ptr.To(asocontainerservicev1.ContainerServiceNetworkProfile_NetworkPluginMode("network plugin mode")), 226 NetworkPolicy: ptr.To(asocontainerservicev1.ContainerServiceNetworkProfile_NetworkPolicy("network policy")), 227 OutboundType: ptr.To(asocontainerservicev1.ContainerServiceNetworkProfile_OutboundType("outbound type")), 228 PodCidr: ptr.To("pod cidr"), 229 ServiceCidr: ptr.To("0.0.0.0/10"), 230 }, 231 NodeResourceGroup: ptr.To("node rg"), 232 OidcIssuerProfile: &asocontainerservicev1.ManagedClusterOIDCIssuerProfile{ 233 Enabled: ptr.To(true), 234 }, 235 OperatorSpec: &asocontainerservicev1.ManagedClusterOperatorSpec{ 236 Secrets: &asocontainerservicev1.ManagedClusterOperatorSecrets{ 237 UserCredentials: &genruntime.SecretDestination{ 238 Name: userKubeconfigSecretName("cluster"), 239 Key: secret.KubeconfigDataName, 240 }, 241 }, 242 ConfigMaps: &asocontainerservicev1.ManagedClusterOperatorConfigMaps{ 243 OIDCIssuerProfile: &genruntime.ConfigMapDestination{ 244 Name: oidcIssuerURLConfigMapName("cluster"), 245 Key: oidcIssuerProfileURL, 246 }, 247 }, 248 }, 249 Owner: &genruntime.KnownResourceReference{ 250 Name: "rg", 251 }, 252 ServicePrincipalProfile: &asocontainerservicev1.ManagedClusterServicePrincipalProfile{ 253 ClientId: ptr.To("msi"), 254 }, 255 Sku: &asocontainerservicev1.ManagedClusterSKU{ 256 Name: ptr.To(asocontainerservicev1.ManagedClusterSKU_Name_Base), 257 Tier: ptr.To(asocontainerservicev1.ManagedClusterSKU_Tier("sku tier")), 258 }, 259 Tags: map[string]string{ 260 "Name": "name", 261 "sigs.k8s.io_cluster-api-provider-azure_cluster_cluster": "owned", 262 "sigs.k8s.io_cluster-api-provider-azure_role": "common", 263 }, 264 SecurityProfile: &asocontainerservicev1.ManagedClusterSecurityProfile{ 265 AzureKeyVaultKms: &asocontainerservicev1.AzureKeyVaultKms{ 266 Enabled: ptr.To(true), 267 KeyId: ptr.To("KeyID"), 268 KeyVaultNetworkAccess: ptr.To(asocontainerservicev1.AzureKeyVaultKms_KeyVaultNetworkAccess_Public), 269 }, 270 Defender: &asocontainerservicev1.ManagedClusterSecurityProfileDefender{ 271 LogAnalyticsWorkspaceResourceReference: &genruntime.ResourceReference{ 272 ARMID: "LogAnalyticsWorkspaceResourceID", 273 }, 274 SecurityMonitoring: &asocontainerservicev1.ManagedClusterSecurityProfileDefenderSecurityMonitoring{ 275 Enabled: ptr.To(true), 276 }, 277 }, 278 ImageCleaner: &asocontainerservicev1.ManagedClusterSecurityProfileImageCleaner{ 279 Enabled: ptr.To(true), 280 IntervalHours: ptr.To(24), 281 }, 282 WorkloadIdentity: &asocontainerservicev1.ManagedClusterSecurityProfileWorkloadIdentity{ 283 Enabled: ptr.To(true), 284 }, 285 }, 286 }, 287 } 288 289 actual, err := spec.Parameters(context.Background(), nil) 290 291 g.Expect(err).NotTo(HaveOccurred()) 292 g.Expect(cmp.Diff(actual, expected)).To(BeEmpty()) 293 }) 294 295 t.Run("no existing preview managed cluster", func(t *testing.T) { 296 g := NewGomegaWithT(t) 297 298 spec := &ManagedClusterSpec{ 299 Name: "name", 300 Preview: true, 301 GetAllAgentPools: func() ([]azure.ASOResourceSpecGetter[genruntime.MetaObject], error) { 302 return []azure.ASOResourceSpecGetter[genruntime.MetaObject]{ 303 &agentpools.AgentPoolSpec{ 304 Replicas: 5, 305 Mode: "mode", 306 AzureName: "agentpool", 307 Patches: []string{`{"spec": {"tags": {"from": "patches"}}}`}, 308 Preview: true, 309 }, 310 }, nil 311 }, 312 } 313 314 actual, err := spec.Parameters(context.Background(), nil) 315 g.Expect(err).NotTo(HaveOccurred()) 316 _, ok := actual.(*asocontainerservicev1preview.ManagedCluster) 317 g.Expect(ok).To(BeTrue()) 318 }) 319 320 t.Run("with existing managed cluster", func(t *testing.T) { 321 g := NewGomegaWithT(t) 322 323 spec := &ManagedClusterSpec{ 324 DNSPrefix: ptr.To("managed by CAPZ"), 325 Tags: map[string]string{"additional": "tags"}, 326 Version: "1.25.9", 327 } 328 existing := &asocontainerservicev1.ManagedCluster{ 329 Spec: asocontainerservicev1.ManagedCluster_Spec{ 330 DnsPrefix: ptr.To("set by the user"), 331 EnablePodSecurityPolicy: ptr.To(true), // set by the user 332 }, 333 Status: asocontainerservicev1.ManagedCluster_STATUS{ 334 AgentPoolProfiles: []asocontainerservicev1.ManagedClusterAgentPoolProfile_STATUS{}, 335 Tags: map[string]string{}, 336 CurrentKubernetesVersion: ptr.To("1.26.6"), 337 }, 338 } 339 340 actualObj, err := spec.Parameters(context.Background(), existing) 341 actual := actualObj.(*asocontainerservicev1.ManagedCluster) 342 343 g.Expect(err).NotTo(HaveOccurred()) 344 g.Expect(actual.Spec.AgentPoolProfiles).To(BeNil()) 345 g.Expect(actual.Spec.Tags).To(BeNil()) 346 g.Expect(actual.Spec.DnsPrefix).To(Equal(ptr.To("managed by CAPZ"))) 347 g.Expect(actual.Spec.EnablePodSecurityPolicy).To(Equal(ptr.To(true))) 348 g.Expect(actual.Spec.KubernetesVersion).NotTo(BeNil()) 349 g.Expect(*actual.Spec.KubernetesVersion).To(Equal("1.26.6")) 350 }) 351 352 t.Run("updating existing managed cluster to a non nil DNS Service IP", func(t *testing.T) { 353 g := NewGomegaWithT(t) 354 355 spec := &ManagedClusterSpec{ 356 DNSPrefix: ptr.To("managed by CAPZ"), 357 Tags: map[string]string{"additional": "tags"}, 358 ServiceCIDR: "123.200.198.0/10", 359 DNSServiceIP: ptr.To("123.200.198.99"), 360 } 361 existing := &asocontainerservicev1.ManagedCluster{ 362 Spec: asocontainerservicev1.ManagedCluster_Spec{ 363 DnsPrefix: ptr.To("set by the user"), 364 EnablePodSecurityPolicy: ptr.To(true), // set by the user 365 366 }, 367 Status: asocontainerservicev1.ManagedCluster_STATUS{ 368 AgentPoolProfiles: []asocontainerservicev1.ManagedClusterAgentPoolProfile_STATUS{}, 369 Tags: map[string]string{}, 370 }, 371 } 372 373 actualObj, err := spec.Parameters(context.Background(), existing) 374 actual := actualObj.(*asocontainerservicev1.ManagedCluster) 375 376 g.Expect(err).NotTo(HaveOccurred()) 377 g.Expect(actual.Spec.AgentPoolProfiles).To(BeNil()) 378 g.Expect(actual.Spec.Tags).To(BeNil()) 379 g.Expect(actual.Spec.DnsPrefix).To(Equal(ptr.To("managed by CAPZ"))) 380 g.Expect(actual.Spec.EnablePodSecurityPolicy).To(Equal(ptr.To(true))) 381 g.Expect(actual.Spec.NetworkProfile.DnsServiceIP).To(Equal(ptr.To("123.200.198.99"))) 382 g.Expect(actual.Spec.NetworkProfile.ServiceCidr).To(Equal(ptr.To("123.200.198.0/10"))) 383 }) 384 } 385 386 func TestOIDCIssuerURLConfigMap(t *testing.T) { 387 t.Run("get oidc issuer profile", func(t *testing.T) { 388 g := NewGomegaWithT(t) 389 390 clusterName := "my-cluster" 391 actualOIDCIssuerConfigMapName := oidcIssuerURLConfigMapName(clusterName) 392 393 g.Expect(actualOIDCIssuerConfigMapName).To(Equal("my-cluster-aso-oidc-issuer-profile")) 394 }) 395 }