sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/scope/managedcontrolplane_test.go (about)

     1  /*
     2  Copyright 2021 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 scope
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	asokubernetesconfigurationv1 "github.com/Azure/azure-service-operator/v2/api/kubernetesconfiguration/v1api20230501"
    25  	asonetworkv1 "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701"
    26  	asoresourcesv1 "github.com/Azure/azure-service-operator/v2/api/resources/v1api20200601"
    27  	"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
    28  	. "github.com/onsi/gomega"
    29  	corev1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/runtime"
    32  	"k8s.io/utils/ptr"
    33  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    34  	"sigs.k8s.io/cluster-api-provider-azure/azure"
    35  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/agentpools"
    36  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/aksextensions"
    37  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/groups"
    38  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/managedclusters"
    39  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/privateendpoints"
    40  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    41  	expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
    42  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    43  )
    44  
    45  func TestManagedControlPlaneScope_OutboundType(t *testing.T) {
    46  	scheme := runtime.NewScheme()
    47  	_ = expv1.AddToScheme(scheme)
    48  	_ = infrav1.AddToScheme(scheme)
    49  	_ = corev1.AddToScheme(scheme)
    50  	explicitOutboundType := infrav1.ManagedControlPlaneOutboundTypeUserDefinedRouting
    51  	cases := []struct {
    52  		Name     string
    53  		Input    ManagedControlPlaneScopeParams
    54  		Expected bool
    55  	}{
    56  		{
    57  			Name: "With Explicit OutboundType defined",
    58  			Input: ManagedControlPlaneScopeParams{
    59  				Cluster: &clusterv1.Cluster{
    60  					ObjectMeta: metav1.ObjectMeta{
    61  						Name:      "cluster1",
    62  						Namespace: "default",
    63  					},
    64  				},
    65  				ControlPlane: &infrav1.AzureManagedControlPlane{
    66  					Spec: infrav1.AzureManagedControlPlaneSpec{
    67  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
    68  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
    69  							IdentityRef: &corev1.ObjectReference{
    70  								Name:      "fake-identity",
    71  								Namespace: "default",
    72  								Kind:      "AzureClusterIdentity",
    73  							},
    74  							OutboundType: &explicitOutboundType,
    75  						},
    76  					},
    77  				},
    78  			},
    79  			Expected: false,
    80  		},
    81  		{
    82  			Name: "Without OutboundType defined",
    83  			Input: ManagedControlPlaneScopeParams{
    84  				Cluster: &clusterv1.Cluster{
    85  					ObjectMeta: metav1.ObjectMeta{
    86  						Name:      "cluster1",
    87  						Namespace: "default",
    88  					},
    89  				},
    90  				ControlPlane: &infrav1.AzureManagedControlPlane{
    91  					Spec: infrav1.AzureManagedControlPlaneSpec{
    92  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
    93  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
    94  							IdentityRef: &corev1.ObjectReference{
    95  								Name:      "fake-identity",
    96  								Namespace: "default",
    97  								Kind:      "AzureClusterIdentity",
    98  							},
    99  						},
   100  					},
   101  				},
   102  			},
   103  			Expected: true,
   104  		},
   105  	}
   106  	for _, c := range cases {
   107  		c := c
   108  		t.Run(c.Name, func(t *testing.T) {
   109  			g := NewWithT(t)
   110  			fakeIdentity := &infrav1.AzureClusterIdentity{
   111  				ObjectMeta: metav1.ObjectMeta{
   112  					Name:      "fake-identity",
   113  					Namespace: "default",
   114  				},
   115  				Spec: infrav1.AzureClusterIdentitySpec{
   116  					Type:     infrav1.ServicePrincipal,
   117  					ClientID: fakeClientID,
   118  					TenantID: fakeTenantID,
   119  				},
   120  			}
   121  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   122  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   123  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   124  
   125  			c.Input.Client = fakeClient
   126  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   127  			g.Expect(err).To(Succeed())
   128  			managedCluster := s.ManagedClusterSpec()
   129  			result := managedCluster.(*managedclusters.ManagedClusterSpec).OutboundType == nil
   130  			g.Expect(result).To(Equal(c.Expected))
   131  		})
   132  	}
   133  }
   134  
   135  func TestManagedControlPlaneScope_PoolVersion(t *testing.T) {
   136  	scheme := runtime.NewScheme()
   137  	_ = expv1.AddToScheme(scheme)
   138  	_ = infrav1.AddToScheme(scheme)
   139  	_ = corev1.AddToScheme(scheme)
   140  
   141  	cases := []struct {
   142  		Name     string
   143  		Input    ManagedControlPlaneScopeParams
   144  		Expected []azure.ASOResourceSpecGetter[genruntime.MetaObject]
   145  		Err      string
   146  	}{
   147  		{
   148  			Name: "Without Version",
   149  			Input: ManagedControlPlaneScopeParams{
   150  				Cluster: &clusterv1.Cluster{
   151  					ObjectMeta: metav1.ObjectMeta{
   152  						Name:      "cluster1",
   153  						Namespace: "default",
   154  					},
   155  				},
   156  				ControlPlane: &infrav1.AzureManagedControlPlane{
   157  					ObjectMeta: metav1.ObjectMeta{
   158  						Name:      "cluster1",
   159  						Namespace: "default",
   160  					},
   161  					Spec: infrav1.AzureManagedControlPlaneSpec{
   162  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   163  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   164  							IdentityRef: &corev1.ObjectReference{
   165  								Name:      "fake-identity",
   166  								Namespace: "default",
   167  								Kind:      "AzureClusterIdentity",
   168  							},
   169  						},
   170  					},
   171  				},
   172  				ManagedMachinePools: []ManagedMachinePool{
   173  					{
   174  						MachinePool:      getMachinePool("pool0"),
   175  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   176  					},
   177  				},
   178  			},
   179  			Expected: []azure.ASOResourceSpecGetter[genruntime.MetaObject]{
   180  				&agentpools.AgentPoolSpec{
   181  					Name:         "pool0",
   182  					AzureName:    "pool0",
   183  					SKU:          "Standard_D2s_v3",
   184  					Replicas:     1,
   185  					Mode:         "System",
   186  					Cluster:      "cluster1",
   187  					VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
   188  				},
   189  			},
   190  		},
   191  		{
   192  			Name: "With Version",
   193  			Input: ManagedControlPlaneScopeParams{
   194  				Cluster: &clusterv1.Cluster{
   195  					ObjectMeta: metav1.ObjectMeta{
   196  						Name:      "cluster1",
   197  						Namespace: "default",
   198  					},
   199  				},
   200  				ControlPlane: &infrav1.AzureManagedControlPlane{
   201  					ObjectMeta: metav1.ObjectMeta{
   202  						Name:      "cluster1",
   203  						Namespace: "default",
   204  					},
   205  					Spec: infrav1.AzureManagedControlPlaneSpec{
   206  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   207  							Version:        "v1.22.0",
   208  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   209  							IdentityRef: &corev1.ObjectReference{
   210  								Name:      "fake-identity",
   211  								Namespace: "default",
   212  								Kind:      "AzureClusterIdentity",
   213  							},
   214  						},
   215  					},
   216  				},
   217  				ManagedMachinePools: []ManagedMachinePool{
   218  					{
   219  						MachinePool:      getMachinePoolWithVersion("pool0", "v1.21.1"),
   220  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   221  					},
   222  				},
   223  			},
   224  			Expected: []azure.ASOResourceSpecGetter[genruntime.MetaObject]{
   225  				&agentpools.AgentPoolSpec{
   226  					Name:         "pool0",
   227  					AzureName:    "pool0",
   228  					SKU:          "Standard_D2s_v3",
   229  					Mode:         "System",
   230  					Replicas:     1,
   231  					Version:      ptr.To("1.21.1"),
   232  					Cluster:      "cluster1",
   233  					VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
   234  				},
   235  			},
   236  		},
   237  		{
   238  			Name: "With bad version",
   239  			Input: ManagedControlPlaneScopeParams{
   240  				Cluster: &clusterv1.Cluster{
   241  					ObjectMeta: metav1.ObjectMeta{
   242  						Name:      "cluster1",
   243  						Namespace: "default",
   244  					},
   245  				},
   246  				ControlPlane: &infrav1.AzureManagedControlPlane{
   247  					ObjectMeta: metav1.ObjectMeta{
   248  						Name:      "cluster1",
   249  						Namespace: "default",
   250  					},
   251  					Spec: infrav1.AzureManagedControlPlaneSpec{
   252  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   253  							Version:        "v1.20.1",
   254  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   255  							IdentityRef: &corev1.ObjectReference{
   256  								Name:      "fake-identity",
   257  								Namespace: "default",
   258  								Kind:      "AzureClusterIdentity",
   259  							},
   260  						},
   261  					},
   262  				},
   263  				ManagedMachinePools: []ManagedMachinePool{
   264  					{
   265  						MachinePool:      getMachinePoolWithVersion("pool0", "v1.21.1"),
   266  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   267  					},
   268  				},
   269  			},
   270  			Err: "MachinePool version cannot be greater than the AzureManagedControlPlane version",
   271  		},
   272  	}
   273  
   274  	for _, c := range cases {
   275  		c := c
   276  		t.Run(c.Name, func(t *testing.T) {
   277  			g := NewWithT(t)
   278  			fakeIdentity := &infrav1.AzureClusterIdentity{
   279  				ObjectMeta: metav1.ObjectMeta{
   280  					Name:      "fake-identity",
   281  					Namespace: "default",
   282  				},
   283  				Spec: infrav1.AzureClusterIdentitySpec{
   284  					Type:     infrav1.ServicePrincipal,
   285  					ClientID: fakeClientID,
   286  					TenantID: fakeTenantID,
   287  				},
   288  			}
   289  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   290  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   291  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   292  
   293  			c.Input.Client = fakeClient
   294  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   295  			g.Expect(err).To(Succeed())
   296  			agentPools, err := s.GetAllAgentPoolSpecs()
   297  			if err != nil {
   298  				g.Expect(err.Error()).To(Equal(c.Err))
   299  			} else {
   300  				g.Expect(agentPools).To(Equal(c.Expected))
   301  			}
   302  		})
   303  	}
   304  }
   305  
   306  func TestManagedControlPlaneScope_AddonProfiles(t *testing.T) {
   307  	scheme := runtime.NewScheme()
   308  	_ = expv1.AddToScheme(scheme)
   309  	_ = infrav1.AddToScheme(scheme)
   310  	_ = corev1.AddToScheme(scheme)
   311  
   312  	cases := []struct {
   313  		Name     string
   314  		Input    ManagedControlPlaneScopeParams
   315  		Expected []managedclusters.AddonProfile
   316  	}{
   317  		{
   318  			Name: "Without add-ons",
   319  			Input: ManagedControlPlaneScopeParams{
   320  				Cluster: &clusterv1.Cluster{
   321  					ObjectMeta: metav1.ObjectMeta{
   322  						Name:      "cluster1",
   323  						Namespace: "default",
   324  					},
   325  				},
   326  				ControlPlane: &infrav1.AzureManagedControlPlane{
   327  					ObjectMeta: metav1.ObjectMeta{
   328  						Name:      "cluster1",
   329  						Namespace: "default",
   330  					},
   331  					Spec: infrav1.AzureManagedControlPlaneSpec{
   332  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   333  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   334  							IdentityRef: &corev1.ObjectReference{
   335  								Name:      "fake-identity",
   336  								Namespace: "default",
   337  								Kind:      "AzureClusterIdentity",
   338  							},
   339  						},
   340  					},
   341  				},
   342  				ManagedMachinePools: []ManagedMachinePool{
   343  					{
   344  						MachinePool:      getMachinePool("pool0"),
   345  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   346  					},
   347  				},
   348  			},
   349  			Expected: nil,
   350  		},
   351  		{
   352  			Name: "With add-ons",
   353  			Input: ManagedControlPlaneScopeParams{
   354  				Cluster: &clusterv1.Cluster{
   355  					ObjectMeta: metav1.ObjectMeta{
   356  						Name:      "cluster1",
   357  						Namespace: "default",
   358  					},
   359  				},
   360  				ControlPlane: &infrav1.AzureManagedControlPlane{
   361  					ObjectMeta: metav1.ObjectMeta{
   362  						Name:      "cluster1",
   363  						Namespace: "default",
   364  					},
   365  					Spec: infrav1.AzureManagedControlPlaneSpec{
   366  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   367  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   368  							IdentityRef: &corev1.ObjectReference{
   369  								Name:      "fake-identity",
   370  								Namespace: "default",
   371  								Kind:      "AzureClusterIdentity",
   372  							},
   373  							AddonProfiles: []infrav1.AddonProfile{
   374  								{Name: "addon1", Config: nil, Enabled: false},
   375  								{Name: "addon2", Config: map[string]string{"k1": "v1", "k2": "v2"}, Enabled: true},
   376  							},
   377  						},
   378  					},
   379  				},
   380  				ManagedMachinePools: []ManagedMachinePool{
   381  					{
   382  						MachinePool:      getMachinePool("pool0"),
   383  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   384  					},
   385  				},
   386  			},
   387  			Expected: []managedclusters.AddonProfile{
   388  				{Name: "addon1", Config: nil, Enabled: false},
   389  				{Name: "addon2", Config: map[string]string{"k1": "v1", "k2": "v2"}, Enabled: true},
   390  			},
   391  		},
   392  	}
   393  
   394  	for _, c := range cases {
   395  		c := c
   396  		t.Run(c.Name, func(t *testing.T) {
   397  			g := NewWithT(t)
   398  			fakeIdentity := &infrav1.AzureClusterIdentity{
   399  				ObjectMeta: metav1.ObjectMeta{
   400  					Name:      "fake-identity",
   401  					Namespace: "default",
   402  				},
   403  				Spec: infrav1.AzureClusterIdentitySpec{
   404  					Type:     infrav1.ServicePrincipal,
   405  					ClientID: fakeClientID,
   406  					TenantID: fakeTenantID,
   407  				},
   408  			}
   409  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   410  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   411  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   412  
   413  			c.Input.Client = fakeClient
   414  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   415  			g.Expect(err).To(Succeed())
   416  			managedCluster := s.ManagedClusterSpec()
   417  			g.Expect(managedCluster.(*managedclusters.ManagedClusterSpec).AddonProfiles).To(Equal(c.Expected))
   418  		})
   419  	}
   420  }
   421  
   422  func TestManagedControlPlaneScope_OSType(t *testing.T) {
   423  	scheme := runtime.NewScheme()
   424  	_ = expv1.AddToScheme(scheme)
   425  	_ = infrav1.AddToScheme(scheme)
   426  	_ = corev1.AddToScheme(scheme)
   427  
   428  	cases := []struct {
   429  		Name     string
   430  		Input    ManagedControlPlaneScopeParams
   431  		Expected []azure.ASOResourceSpecGetter[genruntime.MetaObject]
   432  		Err      string
   433  	}{
   434  		{
   435  			Name: "with Linux and Windows pools",
   436  			Input: ManagedControlPlaneScopeParams{
   437  				Cluster: &clusterv1.Cluster{
   438  					ObjectMeta: metav1.ObjectMeta{
   439  						Name:      "cluster1",
   440  						Namespace: "default",
   441  					},
   442  				},
   443  				ControlPlane: &infrav1.AzureManagedControlPlane{
   444  					ObjectMeta: metav1.ObjectMeta{
   445  						Name:      "cluster1",
   446  						Namespace: "default",
   447  					},
   448  					Spec: infrav1.AzureManagedControlPlaneSpec{
   449  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   450  							Version:        "v1.20.1",
   451  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   452  							IdentityRef: &corev1.ObjectReference{
   453  								Name:      "fake-identity",
   454  								Namespace: "default",
   455  								Kind:      "AzureClusterIdentity",
   456  							},
   457  						},
   458  					},
   459  				},
   460  				ManagedMachinePools: []ManagedMachinePool{
   461  					{
   462  						MachinePool:      getMachinePool("pool0"),
   463  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   464  					},
   465  					{
   466  						MachinePool:      getMachinePool("pool1"),
   467  						InfraMachinePool: getLinuxAzureMachinePool("pool1"),
   468  					},
   469  					{
   470  						MachinePool:      getMachinePool("pool2"),
   471  						InfraMachinePool: getWindowsAzureMachinePool("pool2"),
   472  					},
   473  				},
   474  			},
   475  			Expected: []azure.ASOResourceSpecGetter[genruntime.MetaObject]{
   476  				&agentpools.AgentPoolSpec{
   477  					Name:         "pool0",
   478  					AzureName:    "pool0",
   479  					SKU:          "Standard_D2s_v3",
   480  					Mode:         "System",
   481  					Replicas:     1,
   482  					Cluster:      "cluster1",
   483  					VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
   484  				},
   485  				&agentpools.AgentPoolSpec{
   486  					Name:         "pool1",
   487  					AzureName:    "pool1",
   488  					SKU:          "Standard_D2s_v3",
   489  					Mode:         "User",
   490  					Replicas:     1,
   491  					Cluster:      "cluster1",
   492  					VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
   493  					OSType:       ptr.To(azure.LinuxOS),
   494  				},
   495  				&agentpools.AgentPoolSpec{
   496  					Name:         "pool2",
   497  					AzureName:    "pool2",
   498  					SKU:          "Standard_D2s_v3",
   499  					Mode:         "User",
   500  					Replicas:     1,
   501  					Cluster:      "cluster1",
   502  					VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
   503  					OSType:       ptr.To(azure.WindowsOS),
   504  				},
   505  			},
   506  		},
   507  		{
   508  			Name: "system pool required",
   509  			Input: ManagedControlPlaneScopeParams{
   510  				Cluster: &clusterv1.Cluster{
   511  					ObjectMeta: metav1.ObjectMeta{
   512  						Name:      "cluster1",
   513  						Namespace: "default",
   514  					},
   515  				},
   516  				ControlPlane: &infrav1.AzureManagedControlPlane{
   517  					ObjectMeta: metav1.ObjectMeta{
   518  						Name:      "cluster1",
   519  						Namespace: "default",
   520  					},
   521  					Spec: infrav1.AzureManagedControlPlaneSpec{
   522  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   523  							Version:        "v1.20.1",
   524  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   525  							IdentityRef: &corev1.ObjectReference{
   526  								Name:      "fake-identity",
   527  								Namespace: "default",
   528  								Kind:      "AzureClusterIdentity",
   529  							},
   530  						},
   531  					},
   532  				},
   533  				ManagedMachinePools: []ManagedMachinePool{
   534  					{
   535  						MachinePool:      getMachinePool("pool0"),
   536  						InfraMachinePool: getLinuxAzureMachinePool("pool0"),
   537  					},
   538  					{
   539  						MachinePool:      getMachinePool("pool1"),
   540  						InfraMachinePool: getWindowsAzureMachinePool("pool1"),
   541  					},
   542  				},
   543  			},
   544  			Err: "failed to fetch azuremanagedMachine pool with mode:System, require at least 1 system node pool",
   545  		},
   546  	}
   547  
   548  	for _, c := range cases {
   549  		c := c
   550  		t.Run(c.Name, func(t *testing.T) {
   551  			g := NewWithT(t)
   552  			fakeIdentity := &infrav1.AzureClusterIdentity{
   553  				ObjectMeta: metav1.ObjectMeta{
   554  					Name:      "fake-identity",
   555  					Namespace: "default",
   556  				},
   557  				Spec: infrav1.AzureClusterIdentitySpec{
   558  					Type:     infrav1.ServicePrincipal,
   559  					ClientID: fakeClientID,
   560  					TenantID: fakeTenantID,
   561  				},
   562  			}
   563  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   564  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   565  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   566  
   567  			c.Input.Client = fakeClient
   568  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   569  			g.Expect(err).To(Succeed())
   570  			agentPools, err := s.GetAllAgentPoolSpecs()
   571  			if err != nil {
   572  				g.Expect(err.Error()).To(Equal(c.Err))
   573  			} else {
   574  				g.Expect(agentPools).To(Equal(c.Expected))
   575  			}
   576  		})
   577  	}
   578  }
   579  
   580  func TestManagedControlPlaneScope_IsVnetManagedCache(t *testing.T) {
   581  	scheme := runtime.NewScheme()
   582  	_ = expv1.AddToScheme(scheme)
   583  	_ = infrav1.AddToScheme(scheme)
   584  	_ = corev1.AddToScheme(scheme)
   585  
   586  	cases := []struct {
   587  		Name     string
   588  		Input    ManagedControlPlaneScopeParams
   589  		Expected bool
   590  	}{
   591  		{
   592  			Name: "no Cache value",
   593  			Input: ManagedControlPlaneScopeParams{
   594  				Cluster: &clusterv1.Cluster{
   595  					ObjectMeta: metav1.ObjectMeta{
   596  						Name:      "cluster1",
   597  						Namespace: "default",
   598  					},
   599  				},
   600  				ControlPlane: &infrav1.AzureManagedControlPlane{
   601  					ObjectMeta: metav1.ObjectMeta{
   602  						Name:      "cluster1",
   603  						Namespace: "default",
   604  					},
   605  					Spec: infrav1.AzureManagedControlPlaneSpec{
   606  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   607  							Version:        "v1.20.1",
   608  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   609  							IdentityRef: &corev1.ObjectReference{
   610  								Name:      "fake-identity",
   611  								Namespace: "default",
   612  								Kind:      "AzureClusterIdentity",
   613  							},
   614  						},
   615  					},
   616  				},
   617  				ManagedMachinePools: []ManagedMachinePool{
   618  					{
   619  						MachinePool:      getMachinePool("pool0"),
   620  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   621  					},
   622  					{
   623  						MachinePool:      getMachinePool("pool1"),
   624  						InfraMachinePool: getLinuxAzureMachinePool("pool1"),
   625  					},
   626  				},
   627  			},
   628  			Expected: false,
   629  		},
   630  		{
   631  			Name: "with Cache value of true",
   632  			Input: ManagedControlPlaneScopeParams{
   633  				Cluster: &clusterv1.Cluster{
   634  					ObjectMeta: metav1.ObjectMeta{
   635  						Name:      "cluster1",
   636  						Namespace: "default",
   637  					},
   638  				},
   639  				ControlPlane: &infrav1.AzureManagedControlPlane{
   640  					ObjectMeta: metav1.ObjectMeta{
   641  						Name:      "cluster1",
   642  						Namespace: "default",
   643  					},
   644  					Spec: infrav1.AzureManagedControlPlaneSpec{
   645  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   646  							Version:        "v1.20.1",
   647  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   648  							IdentityRef: &corev1.ObjectReference{
   649  								Name:      "fake-identity",
   650  								Namespace: "default",
   651  								Kind:      "AzureClusterIdentity",
   652  							},
   653  						},
   654  					},
   655  				},
   656  				ManagedMachinePools: []ManagedMachinePool{
   657  					{
   658  						MachinePool:      getMachinePool("pool0"),
   659  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   660  					},
   661  					{
   662  						MachinePool:      getMachinePool("pool1"),
   663  						InfraMachinePool: getLinuxAzureMachinePool("pool1"),
   664  					},
   665  				},
   666  				Cache: &ManagedControlPlaneCache{
   667  					isVnetManaged: ptr.To(true),
   668  				},
   669  			},
   670  			Expected: true,
   671  		},
   672  		{
   673  			Name: "with Cache value of false",
   674  			Input: ManagedControlPlaneScopeParams{
   675  				Cluster: &clusterv1.Cluster{
   676  					ObjectMeta: metav1.ObjectMeta{
   677  						Name:      "cluster1",
   678  						Namespace: "default",
   679  					},
   680  				},
   681  				ControlPlane: &infrav1.AzureManagedControlPlane{
   682  					ObjectMeta: metav1.ObjectMeta{
   683  						Name:      "cluster1",
   684  						Namespace: "default",
   685  					},
   686  					Spec: infrav1.AzureManagedControlPlaneSpec{
   687  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   688  							Version:        "v1.20.1",
   689  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   690  							IdentityRef: &corev1.ObjectReference{
   691  								Name:      "fake-identity",
   692  								Namespace: "default",
   693  								Kind:      "AzureClusterIdentity",
   694  							},
   695  						},
   696  					},
   697  				},
   698  				ManagedMachinePools: []ManagedMachinePool{
   699  					{
   700  						MachinePool:      getMachinePool("pool0"),
   701  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   702  					},
   703  					{
   704  						MachinePool:      getMachinePool("pool1"),
   705  						InfraMachinePool: getLinuxAzureMachinePool("pool1"),
   706  					},
   707  				},
   708  				Cache: &ManagedControlPlaneCache{
   709  					isVnetManaged: ptr.To(false),
   710  				},
   711  			},
   712  			Expected: false,
   713  		},
   714  	}
   715  
   716  	for _, c := range cases {
   717  		c := c
   718  		t.Run(c.Name, func(t *testing.T) {
   719  			g := NewWithT(t)
   720  			fakeIdentity := &infrav1.AzureClusterIdentity{
   721  				ObjectMeta: metav1.ObjectMeta{
   722  					Name:      "fake-identity",
   723  					Namespace: "default",
   724  				},
   725  				Spec: infrav1.AzureClusterIdentitySpec{
   726  					Type:     infrav1.ServicePrincipal,
   727  					ClientID: fakeClientID,
   728  					TenantID: fakeTenantID,
   729  				},
   730  			}
   731  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   732  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   733  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   734  
   735  			c.Input.Client = fakeClient
   736  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   737  			g.Expect(err).To(Succeed())
   738  			isVnetManaged := s.IsVnetManaged()
   739  			g.Expect(isVnetManaged).To(Equal(c.Expected))
   740  		})
   741  	}
   742  }
   743  
   744  func TestManagedControlPlaneScope_AADProfile(t *testing.T) {
   745  	scheme := runtime.NewScheme()
   746  	_ = infrav1.AddToScheme(scheme)
   747  	_ = corev1.AddToScheme(scheme)
   748  
   749  	cases := []struct {
   750  		Name     string
   751  		Input    ManagedControlPlaneScopeParams
   752  		Expected *managedclusters.AADProfile
   753  	}{
   754  		{
   755  			Name: "Without AADProfile",
   756  			Input: ManagedControlPlaneScopeParams{
   757  				Cluster: &clusterv1.Cluster{
   758  					ObjectMeta: metav1.ObjectMeta{
   759  						Name:      "cluster1",
   760  						Namespace: "default",
   761  					},
   762  				},
   763  				ControlPlane: &infrav1.AzureManagedControlPlane{
   764  					ObjectMeta: metav1.ObjectMeta{
   765  						Name:      "cluster1",
   766  						Namespace: "default",
   767  					},
   768  					Spec: infrav1.AzureManagedControlPlaneSpec{
   769  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   770  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   771  							IdentityRef: &corev1.ObjectReference{
   772  								Name:      "fake-identity",
   773  								Namespace: "default",
   774  								Kind:      "AzureClusterIdentity",
   775  							},
   776  						},
   777  					},
   778  				},
   779  				ManagedMachinePools: []ManagedMachinePool{
   780  					{
   781  						MachinePool:      getMachinePool("pool0"),
   782  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   783  					},
   784  				},
   785  			},
   786  			Expected: nil,
   787  		},
   788  		{
   789  			Name: "With AADProfile",
   790  			Input: ManagedControlPlaneScopeParams{
   791  				Cluster: &clusterv1.Cluster{
   792  					ObjectMeta: metav1.ObjectMeta{
   793  						Name:      "cluster1",
   794  						Namespace: "default",
   795  					},
   796  				},
   797  				ControlPlane: &infrav1.AzureManagedControlPlane{
   798  					ObjectMeta: metav1.ObjectMeta{
   799  						Name:      "cluster1",
   800  						Namespace: "default",
   801  					},
   802  					Spec: infrav1.AzureManagedControlPlaneSpec{
   803  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   804  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   805  							IdentityRef: &corev1.ObjectReference{
   806  								Name:      "fake-identity",
   807  								Namespace: "default",
   808  								Kind:      "AzureClusterIdentity",
   809  							},
   810  							AADProfile: &infrav1.AADProfile{
   811  								Managed:             true,
   812  								AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
   813  							},
   814  						},
   815  					},
   816  				},
   817  				ManagedMachinePools: []ManagedMachinePool{
   818  					{
   819  						MachinePool:      getMachinePool("pool0"),
   820  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   821  					},
   822  				},
   823  			},
   824  			Expected: &managedclusters.AADProfile{
   825  				Managed:             true,
   826  				EnableAzureRBAC:     true,
   827  				AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
   828  			},
   829  		},
   830  	}
   831  	for _, c := range cases {
   832  		c := c
   833  		t.Run(c.Name, func(t *testing.T) {
   834  			g := NewWithT(t)
   835  			fakeIdentity := &infrav1.AzureClusterIdentity{
   836  				ObjectMeta: metav1.ObjectMeta{
   837  					Name:      "fake-identity",
   838  					Namespace: "default",
   839  				},
   840  				Spec: infrav1.AzureClusterIdentitySpec{
   841  					Type:     infrav1.ServicePrincipal,
   842  					ClientID: fakeClientID,
   843  					TenantID: fakeTenantID,
   844  				},
   845  			}
   846  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   847  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   848  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   849  
   850  			c.Input.Client = fakeClient
   851  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
   852  			g.Expect(err).To(Succeed())
   853  			managedClusterGetter := s.ManagedClusterSpec()
   854  			managedCluster, ok := managedClusterGetter.(*managedclusters.ManagedClusterSpec)
   855  			g.Expect(ok).To(BeTrue())
   856  			g.Expect(managedCluster.AADProfile).To(Equal(c.Expected))
   857  		})
   858  	}
   859  }
   860  
   861  func TestManagedControlPlaneScope_DisableLocalAccounts(t *testing.T) {
   862  	scheme := runtime.NewScheme()
   863  	_ = infrav1.AddToScheme(scheme)
   864  	_ = corev1.AddToScheme(scheme)
   865  
   866  	cases := []struct {
   867  		Name     string
   868  		Input    ManagedControlPlaneScopeParams
   869  		Expected *bool
   870  	}{
   871  		{
   872  			Name: "Without DisableLocalAccounts",
   873  			Input: ManagedControlPlaneScopeParams{
   874  				Cluster: &clusterv1.Cluster{
   875  					ObjectMeta: metav1.ObjectMeta{
   876  						Name:      "cluster1",
   877  						Namespace: "default",
   878  					},
   879  				},
   880  				ControlPlane: &infrav1.AzureManagedControlPlane{
   881  					ObjectMeta: metav1.ObjectMeta{
   882  						Name:      "cluster1",
   883  						Namespace: "default",
   884  					},
   885  					Spec: infrav1.AzureManagedControlPlaneSpec{
   886  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   887  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   888  							IdentityRef: &corev1.ObjectReference{
   889  								Name:      "fake-identity",
   890  								Namespace: "default",
   891  								Kind:      "AzureClusterIdentity",
   892  							},
   893  						},
   894  					},
   895  				},
   896  				ManagedMachinePools: []ManagedMachinePool{
   897  					{
   898  						MachinePool:      getMachinePool("pool0"),
   899  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   900  					},
   901  				},
   902  			},
   903  			Expected: nil,
   904  		},
   905  		{
   906  			Name: "Without AAdProfile and With DisableLocalAccounts",
   907  			Input: ManagedControlPlaneScopeParams{
   908  				Cluster: &clusterv1.Cluster{
   909  					ObjectMeta: metav1.ObjectMeta{
   910  						Name:      "cluster1",
   911  						Namespace: "default",
   912  					},
   913  				},
   914  				ControlPlane: &infrav1.AzureManagedControlPlane{
   915  					ObjectMeta: metav1.ObjectMeta{
   916  						Name:      "cluster1",
   917  						Namespace: "default",
   918  					},
   919  					Spec: infrav1.AzureManagedControlPlaneSpec{
   920  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   921  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   922  							IdentityRef: &corev1.ObjectReference{
   923  								Name:      "fake-identity",
   924  								Namespace: "default",
   925  								Kind:      "AzureClusterIdentity",
   926  							},
   927  							DisableLocalAccounts: ptr.To[bool](true),
   928  						},
   929  					},
   930  				},
   931  				ManagedMachinePools: []ManagedMachinePool{
   932  					{
   933  						MachinePool:      getMachinePool("pool0"),
   934  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   935  					},
   936  				},
   937  			},
   938  			Expected: nil,
   939  		},
   940  		{
   941  			Name: "With AAdProfile and With DisableLocalAccounts",
   942  			Input: ManagedControlPlaneScopeParams{
   943  				Cluster: &clusterv1.Cluster{
   944  					ObjectMeta: metav1.ObjectMeta{
   945  						Name:      "cluster1",
   946  						Namespace: "default",
   947  					},
   948  				},
   949  				ControlPlane: &infrav1.AzureManagedControlPlane{
   950  					ObjectMeta: metav1.ObjectMeta{
   951  						Name:      "cluster1",
   952  						Namespace: "default",
   953  					},
   954  					Spec: infrav1.AzureManagedControlPlaneSpec{
   955  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
   956  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
   957  							IdentityRef: &corev1.ObjectReference{
   958  								Name:      "fake-identity",
   959  								Namespace: "default",
   960  								Kind:      "AzureClusterIdentity",
   961  							},
   962  							AADProfile: &infrav1.AADProfile{
   963  								Managed:             true,
   964  								AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
   965  							},
   966  							DisableLocalAccounts: ptr.To[bool](true),
   967  						},
   968  					},
   969  				},
   970  				ManagedMachinePools: []ManagedMachinePool{
   971  					{
   972  						MachinePool:      getMachinePool("pool0"),
   973  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
   974  					},
   975  				},
   976  			},
   977  			Expected: ptr.To[bool](true),
   978  		},
   979  	}
   980  	for _, c := range cases {
   981  		c := c
   982  		t.Run(c.Name, func(t *testing.T) {
   983  			g := NewWithT(t)
   984  			fakeIdentity := &infrav1.AzureClusterIdentity{
   985  				ObjectMeta: metav1.ObjectMeta{
   986  					Name:      "fake-identity",
   987  					Namespace: "default",
   988  				},
   989  				Spec: infrav1.AzureClusterIdentitySpec{
   990  					Type:     infrav1.ServicePrincipal,
   991  					ClientID: fakeClientID,
   992  					TenantID: fakeTenantID,
   993  				},
   994  			}
   995  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
   996  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
   997  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
   998  
   999  			c.Input.Client = fakeClient
  1000  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
  1001  			g.Expect(err).To(Succeed())
  1002  			managedClusterGetter := s.ManagedClusterSpec()
  1003  			managedCluster, ok := managedClusterGetter.(*managedclusters.ManagedClusterSpec)
  1004  			g.Expect(ok).To(BeTrue())
  1005  			g.Expect(managedCluster.DisableLocalAccounts).To(Equal(c.Expected))
  1006  		})
  1007  	}
  1008  }
  1009  
  1010  func TestIsAADEnabled(t *testing.T) {
  1011  	scheme := runtime.NewScheme()
  1012  	_ = infrav1.AddToScheme(scheme)
  1013  	_ = corev1.AddToScheme(scheme)
  1014  
  1015  	cases := []struct {
  1016  		Name     string
  1017  		Input    ManagedControlPlaneScopeParams
  1018  		Expected bool
  1019  	}{
  1020  		{
  1021  			Name: "AAD is not enabled",
  1022  			Input: ManagedControlPlaneScopeParams{
  1023  				Cluster: &clusterv1.Cluster{
  1024  					ObjectMeta: metav1.ObjectMeta{
  1025  						Name:      "cluster1",
  1026  						Namespace: "default",
  1027  					},
  1028  				},
  1029  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1030  					ObjectMeta: metav1.ObjectMeta{
  1031  						Name:      "cluster1",
  1032  						Namespace: "default",
  1033  					},
  1034  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1035  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1036  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1037  							IdentityRef: &corev1.ObjectReference{
  1038  								Name:      "fake-identity",
  1039  								Namespace: "default",
  1040  								Kind:      "AzureClusterIdentity",
  1041  							},
  1042  						},
  1043  					},
  1044  				},
  1045  				ManagedMachinePools: []ManagedMachinePool{
  1046  					{
  1047  						MachinePool:      getMachinePool("pool0"),
  1048  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1049  					},
  1050  				},
  1051  			},
  1052  			Expected: false,
  1053  		},
  1054  		{
  1055  			Name: "AAdProfile and With DisableLocalAccounts",
  1056  			Input: ManagedControlPlaneScopeParams{
  1057  				Cluster: &clusterv1.Cluster{
  1058  					ObjectMeta: metav1.ObjectMeta{
  1059  						Name:      "cluster1",
  1060  						Namespace: "default",
  1061  					},
  1062  				},
  1063  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1064  					ObjectMeta: metav1.ObjectMeta{
  1065  						Name:      "cluster1",
  1066  						Namespace: "default",
  1067  					},
  1068  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1069  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1070  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1071  							IdentityRef: &corev1.ObjectReference{
  1072  								Name:      "fake-identity",
  1073  								Namespace: "default",
  1074  								Kind:      "AzureClusterIdentity",
  1075  							},
  1076  							AADProfile: &infrav1.AADProfile{
  1077  								Managed:             true,
  1078  								AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
  1079  							},
  1080  							DisableLocalAccounts: ptr.To[bool](true),
  1081  						},
  1082  					},
  1083  				},
  1084  				ManagedMachinePools: []ManagedMachinePool{
  1085  					{
  1086  						MachinePool:      getMachinePool("pool0"),
  1087  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1088  					},
  1089  				},
  1090  			},
  1091  			Expected: true,
  1092  		},
  1093  	}
  1094  	for _, c := range cases {
  1095  		c := c
  1096  		t.Run(c.Name, func(t *testing.T) {
  1097  			g := NewWithT(t)
  1098  			fakeIdentity := &infrav1.AzureClusterIdentity{
  1099  				ObjectMeta: metav1.ObjectMeta{
  1100  					Name:      "fake-identity",
  1101  					Namespace: "default",
  1102  				},
  1103  				Spec: infrav1.AzureClusterIdentitySpec{
  1104  					Type:     infrav1.ServicePrincipal,
  1105  					ClientID: fakeClientID,
  1106  					TenantID: fakeTenantID,
  1107  				},
  1108  			}
  1109  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
  1110  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
  1111  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
  1112  
  1113  			c.Input.Client = fakeClient
  1114  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
  1115  			g.Expect(err).To(Succeed())
  1116  			aadEnabled := s.IsAADEnabled()
  1117  			g.Expect(aadEnabled).To(Equal(c.Expected))
  1118  		})
  1119  	}
  1120  }
  1121  
  1122  func TestAreLocalAccountsDisabled(t *testing.T) {
  1123  	scheme := runtime.NewScheme()
  1124  	_ = infrav1.AddToScheme(scheme)
  1125  	_ = corev1.AddToScheme(scheme)
  1126  
  1127  	cases := []struct {
  1128  		Name     string
  1129  		Input    ManagedControlPlaneScopeParams
  1130  		Expected bool
  1131  	}{
  1132  		{
  1133  			Name: "DisbaleLocalAccount is not enabled",
  1134  			Input: ManagedControlPlaneScopeParams{
  1135  				Cluster: &clusterv1.Cluster{
  1136  					ObjectMeta: metav1.ObjectMeta{
  1137  						Name:      "cluster1",
  1138  						Namespace: "default",
  1139  					},
  1140  				},
  1141  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1142  					ObjectMeta: metav1.ObjectMeta{
  1143  						Name:      "cluster1",
  1144  						Namespace: "default",
  1145  					},
  1146  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1147  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1148  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1149  							IdentityRef: &corev1.ObjectReference{
  1150  								Name:      "fake-identity",
  1151  								Namespace: "default",
  1152  								Kind:      "AzureClusterIdentity",
  1153  							},
  1154  						},
  1155  					},
  1156  				},
  1157  				ManagedMachinePools: []ManagedMachinePool{
  1158  					{
  1159  						MachinePool:      getMachinePool("pool0"),
  1160  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1161  					},
  1162  				},
  1163  			},
  1164  			Expected: false,
  1165  		},
  1166  		{
  1167  			Name: "With AAdProfile and Without DisableLocalAccounts",
  1168  			Input: ManagedControlPlaneScopeParams{
  1169  				Cluster: &clusterv1.Cluster{
  1170  					ObjectMeta: metav1.ObjectMeta{
  1171  						Name:      "cluster1",
  1172  						Namespace: "default",
  1173  					},
  1174  				},
  1175  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1176  					ObjectMeta: metav1.ObjectMeta{
  1177  						Name:      "cluster1",
  1178  						Namespace: "default",
  1179  					},
  1180  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1181  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1182  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1183  							IdentityRef: &corev1.ObjectReference{
  1184  								Name:      "fake-identity",
  1185  								Namespace: "default",
  1186  								Kind:      "AzureClusterIdentity",
  1187  							},
  1188  							AADProfile: &infrav1.AADProfile{
  1189  								Managed:             true,
  1190  								AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
  1191  							},
  1192  						},
  1193  					},
  1194  				},
  1195  				ManagedMachinePools: []ManagedMachinePool{
  1196  					{
  1197  						MachinePool:      getMachinePool("pool0"),
  1198  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1199  					},
  1200  				},
  1201  			},
  1202  			Expected: false,
  1203  		},
  1204  		{
  1205  			Name: "With AAdProfile and With DisableLocalAccounts",
  1206  			Input: ManagedControlPlaneScopeParams{
  1207  				Cluster: &clusterv1.Cluster{
  1208  					ObjectMeta: metav1.ObjectMeta{
  1209  						Name:      "cluster1",
  1210  						Namespace: "default",
  1211  					},
  1212  				},
  1213  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1214  					ObjectMeta: metav1.ObjectMeta{
  1215  						Name:      "cluster1",
  1216  						Namespace: "default",
  1217  					},
  1218  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1219  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1220  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1221  							IdentityRef: &corev1.ObjectReference{
  1222  								Name:      "fake-identity",
  1223  								Namespace: "default",
  1224  								Kind:      "AzureClusterIdentity",
  1225  							},
  1226  							AADProfile: &infrav1.AADProfile{
  1227  								Managed:             true,
  1228  								AdminGroupObjectIDs: []string{"00000000-0000-0000-0000-000000000000"},
  1229  							},
  1230  							DisableLocalAccounts: ptr.To[bool](true),
  1231  						},
  1232  					},
  1233  				},
  1234  				ManagedMachinePools: []ManagedMachinePool{
  1235  					{
  1236  						MachinePool:      getMachinePool("pool0"),
  1237  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1238  					},
  1239  				},
  1240  			},
  1241  			Expected: true,
  1242  		},
  1243  	}
  1244  	for _, c := range cases {
  1245  		c := c
  1246  		t.Run(c.Name, func(t *testing.T) {
  1247  			g := NewWithT(t)
  1248  			fakeIdentity := &infrav1.AzureClusterIdentity{
  1249  				ObjectMeta: metav1.ObjectMeta{
  1250  					Name:      "fake-identity",
  1251  					Namespace: "default",
  1252  				},
  1253  				Spec: infrav1.AzureClusterIdentitySpec{
  1254  					Type:     infrav1.ServicePrincipal,
  1255  					ClientID: fakeClientID,
  1256  					TenantID: fakeTenantID,
  1257  				},
  1258  			}
  1259  			fakeSecret := &corev1.Secret{Data: map[string][]byte{"clientSecret": []byte("fooSecret")}}
  1260  			initObjects := []runtime.Object{c.Input.ControlPlane, fakeIdentity, fakeSecret}
  1261  			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build()
  1262  
  1263  			c.Input.Client = fakeClient
  1264  			s, err := NewManagedControlPlaneScope(context.TODO(), c.Input)
  1265  			g.Expect(err).To(Succeed())
  1266  			localAccountsDisabled := s.AreLocalAccountsDisabled()
  1267  			g.Expect(localAccountsDisabled).To(Equal(c.Expected))
  1268  		})
  1269  	}
  1270  }
  1271  
  1272  func TestManagedControlPlaneScope_PrivateEndpointSpecs(t *testing.T) {
  1273  	cases := []struct {
  1274  		Name     string
  1275  		Input    ManagedControlPlaneScopeParams
  1276  		Expected []azure.ASOResourceSpecGetter[*asonetworkv1.PrivateEndpoint]
  1277  		Err      string
  1278  	}{
  1279  		{
  1280  			Name: "returns empty private endpoints list if no subnets are specified",
  1281  			Input: ManagedControlPlaneScopeParams{
  1282  				Cluster: &clusterv1.Cluster{
  1283  					ObjectMeta: metav1.ObjectMeta{
  1284  						Name:      "cluster1",
  1285  						Namespace: "default",
  1286  					},
  1287  				},
  1288  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1289  					ObjectMeta: metav1.ObjectMeta{
  1290  						Name:      "cluster1",
  1291  						Namespace: "default",
  1292  					},
  1293  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1294  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1295  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{},
  1296  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1297  						},
  1298  					},
  1299  				},
  1300  			},
  1301  			Expected: make([]azure.ASOResourceSpecGetter[*asonetworkv1.PrivateEndpoint], 0),
  1302  		},
  1303  		{
  1304  			Name: "returns empty private endpoints list if no private endpoints are specified",
  1305  			Input: ManagedControlPlaneScopeParams{
  1306  				Cluster: &clusterv1.Cluster{
  1307  					ObjectMeta: metav1.ObjectMeta{
  1308  						Name:      "cluster1",
  1309  						Namespace: "default",
  1310  					},
  1311  				},
  1312  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1313  					ObjectMeta: metav1.ObjectMeta{
  1314  						Name:      "cluster1",
  1315  						Namespace: "default",
  1316  					},
  1317  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1318  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1319  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1320  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1321  								ManagedControlPlaneVirtualNetworkClassSpec: infrav1.ManagedControlPlaneVirtualNetworkClassSpec{
  1322  									Subnet: infrav1.ManagedControlPlaneSubnet{
  1323  										PrivateEndpoints: infrav1.PrivateEndpoints{},
  1324  									},
  1325  								},
  1326  							},
  1327  						},
  1328  					},
  1329  				},
  1330  			},
  1331  			Expected: make([]azure.ASOResourceSpecGetter[*asonetworkv1.PrivateEndpoint], 0),
  1332  		},
  1333  		{
  1334  			Name: "returns list of private endpoint specs if private endpoints are specified",
  1335  			Input: ManagedControlPlaneScopeParams{
  1336  				Cluster: &clusterv1.Cluster{
  1337  					ObjectMeta: metav1.ObjectMeta{
  1338  						Name:      "my-cluster",
  1339  						Namespace: "dummy-ns",
  1340  					},
  1341  				},
  1342  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1343  					ObjectMeta: metav1.ObjectMeta{
  1344  						Name:      "my-cluster",
  1345  						Namespace: "dummy-ns",
  1346  					},
  1347  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1348  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1349  							SubscriptionID: "00000000-0000-0000-0000-000000000001",
  1350  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1351  								ResourceGroup: "dummy-rg",
  1352  								ManagedControlPlaneVirtualNetworkClassSpec: infrav1.ManagedControlPlaneVirtualNetworkClassSpec{
  1353  									Name: "vnet1",
  1354  									Subnet: infrav1.ManagedControlPlaneSubnet{
  1355  										Name: "subnet1",
  1356  										PrivateEndpoints: infrav1.PrivateEndpoints{
  1357  											{
  1358  												Name:     "my-private-endpoint",
  1359  												Location: "westus2",
  1360  												PrivateLinkServiceConnections: []infrav1.PrivateLinkServiceConnection{
  1361  													{
  1362  														Name:                 "my-pls-connection",
  1363  														PrivateLinkServiceID: "my-pls-id",
  1364  														GroupIDs: []string{
  1365  															"my-group-id-1",
  1366  														},
  1367  														RequestMessage: "my-request-message",
  1368  													},
  1369  												},
  1370  												CustomNetworkInterfaceName: "my-custom-nic",
  1371  												PrivateIPAddresses: []string{
  1372  													"IP1",
  1373  													"IP2",
  1374  												},
  1375  												ApplicationSecurityGroups: []string{
  1376  													"ASG1",
  1377  													"ASG2",
  1378  												},
  1379  												ManualApproval: true,
  1380  											},
  1381  										},
  1382  									},
  1383  								},
  1384  							},
  1385  						},
  1386  					},
  1387  				},
  1388  			},
  1389  			Expected: []azure.ASOResourceSpecGetter[*asonetworkv1.PrivateEndpoint]{
  1390  				&privateendpoints.PrivateEndpointSpec{
  1391  					Name:                       "my-private-endpoint",
  1392  					ResourceGroup:              "dummy-rg",
  1393  					Location:                   "westus2",
  1394  					CustomNetworkInterfaceName: "my-custom-nic",
  1395  					PrivateIPAddresses: []string{
  1396  						"IP1",
  1397  						"IP2",
  1398  					},
  1399  					SubnetID: "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/dummy-rg/providers/Microsoft.Network/virtualNetworks/vnet1/subnets/subnet1",
  1400  					ApplicationSecurityGroups: []string{
  1401  						"ASG1",
  1402  						"ASG2",
  1403  					},
  1404  					ClusterName: "my-cluster",
  1405  					PrivateLinkServiceConnections: []privateendpoints.PrivateLinkServiceConnection{
  1406  						{
  1407  							Name:                 "my-pls-connection",
  1408  							RequestMessage:       "my-request-message",
  1409  							PrivateLinkServiceID: "my-pls-id",
  1410  							GroupIDs: []string{
  1411  								"my-group-id-1",
  1412  							},
  1413  						},
  1414  					},
  1415  					ManualApproval: true,
  1416  					AdditionalTags: make(infrav1.Tags, 0),
  1417  				},
  1418  			},
  1419  		},
  1420  	}
  1421  	for _, c := range cases {
  1422  		c := c
  1423  		t.Run(c.Name, func(t *testing.T) {
  1424  			s := &ManagedControlPlaneScope{
  1425  				ControlPlane: c.Input.ControlPlane,
  1426  				Cluster:      c.Input.Cluster,
  1427  			}
  1428  			if got := s.PrivateEndpointSpecs(); !reflect.DeepEqual(got, c.Expected) {
  1429  				t.Errorf("PrivateEndpointSpecs() = %s, want %s", specArrayToString(got), specArrayToString(c.Expected))
  1430  			}
  1431  		})
  1432  	}
  1433  }
  1434  
  1435  func TestManagedControlPlaneScope_AKSExtensionSpecs(t *testing.T) {
  1436  	cases := []struct {
  1437  		Name     string
  1438  		Input    ManagedControlPlaneScopeParams
  1439  		Expected []azure.ASOResourceSpecGetter[*asokubernetesconfigurationv1.Extension]
  1440  		Err      string
  1441  	}{
  1442  		{
  1443  			Name: "returns empty AKS extensions list if no extensions are specified",
  1444  			Input: ManagedControlPlaneScopeParams{
  1445  				Cluster: &clusterv1.Cluster{
  1446  					ObjectMeta: metav1.ObjectMeta{
  1447  						Name:      "cluster1",
  1448  						Namespace: "dummy-ns",
  1449  					},
  1450  				},
  1451  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1452  					ObjectMeta: metav1.ObjectMeta{
  1453  						Name:      "my-cluster",
  1454  						Namespace: "dummy-ns",
  1455  					},
  1456  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1457  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{},
  1458  					},
  1459  				},
  1460  			},
  1461  		},
  1462  		{
  1463  			Name: "returns list of AKS extensions if extensions are specified",
  1464  			Input: ManagedControlPlaneScopeParams{
  1465  				Cluster: &clusterv1.Cluster{
  1466  					ObjectMeta: metav1.ObjectMeta{
  1467  						Name:      "my-cluster",
  1468  						Namespace: "dummy-ns",
  1469  					},
  1470  				},
  1471  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1472  					ObjectMeta: metav1.ObjectMeta{
  1473  						Name:      "my-cluster",
  1474  						Namespace: "dummy-ns",
  1475  					},
  1476  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1477  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1478  							Extensions: []infrav1.AKSExtension{
  1479  								{
  1480  									Name:                    "my-extension",
  1481  									AutoUpgradeMinorVersion: ptr.To(true),
  1482  									ConfigurationSettings: map[string]string{
  1483  										"my-key": "my-value",
  1484  									},
  1485  									ExtensionType: ptr.To("my-extension-type"),
  1486  									ReleaseTrain:  ptr.To("my-release-train"),
  1487  									Version:       ptr.To("my-version"),
  1488  									Plan: &infrav1.ExtensionPlan{
  1489  										Name:      "my-plan-name",
  1490  										Product:   "my-product",
  1491  										Publisher: "my-publisher",
  1492  									},
  1493  									AKSAssignedIdentityType: infrav1.AKSAssignedIdentitySystemAssigned,
  1494  									Identity:                infrav1.ExtensionIdentitySystemAssigned,
  1495  								},
  1496  							},
  1497  						},
  1498  					},
  1499  				},
  1500  			},
  1501  			Expected: []azure.ASOResourceSpecGetter[*asokubernetesconfigurationv1.Extension]{
  1502  				&aksextensions.AKSExtensionSpec{
  1503  					Name:                    "my-extension",
  1504  					Namespace:               "dummy-ns",
  1505  					AutoUpgradeMinorVersion: ptr.To(true),
  1506  					ConfigurationSettings: map[string]string{
  1507  						"my-key": "my-value",
  1508  					},
  1509  					ExtensionType: ptr.To("my-extension-type"),
  1510  					ReleaseTrain:  ptr.To("my-release-train"),
  1511  					Version:       ptr.To("my-version"),
  1512  					Owner:         "/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/my-cluster",
  1513  					Plan: &infrav1.ExtensionPlan{
  1514  						Name:      "my-plan-name",
  1515  						Product:   "my-product",
  1516  						Publisher: "my-publisher",
  1517  					},
  1518  					AKSAssignedIdentityType: infrav1.AKSAssignedIdentitySystemAssigned,
  1519  					ExtensionIdentity:       infrav1.ExtensionIdentitySystemAssigned,
  1520  				},
  1521  			},
  1522  		},
  1523  	}
  1524  
  1525  	for _, c := range cases {
  1526  		c := c
  1527  		t.Run(c.Name, func(t *testing.T) {
  1528  			s := &ManagedControlPlaneScope{
  1529  				ControlPlane: c.Input.ControlPlane,
  1530  				Cluster:      c.Input.Cluster,
  1531  			}
  1532  			if got := s.AKSExtensionSpecs(); !reflect.DeepEqual(got, c.Expected) {
  1533  				t.Errorf("AKSExtensionSpecs() = %s, want %s", specArrayToString(got), specArrayToString(c.Expected))
  1534  			}
  1535  		})
  1536  	}
  1537  }
  1538  
  1539  func TestManagedControlPlaneScope_AutoUpgradeProfile(t *testing.T) {
  1540  	cases := []struct {
  1541  		name     string
  1542  		input    ManagedControlPlaneScopeParams
  1543  		expected *managedclusters.ManagedClusterAutoUpgradeProfile
  1544  	}{
  1545  		{
  1546  			name: "Without AutoUpgradeProfile",
  1547  			input: ManagedControlPlaneScopeParams{
  1548  				Cluster: &clusterv1.Cluster{
  1549  					ObjectMeta: metav1.ObjectMeta{
  1550  						Name:      "cluster1",
  1551  						Namespace: "default",
  1552  					},
  1553  				},
  1554  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1555  					ObjectMeta: metav1.ObjectMeta{
  1556  						Name:      "cluster1",
  1557  						Namespace: "default",
  1558  					},
  1559  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1560  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1561  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1562  						},
  1563  					},
  1564  				},
  1565  				ManagedMachinePools: []ManagedMachinePool{
  1566  					{
  1567  						MachinePool:      getMachinePool("pool0"),
  1568  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1569  					},
  1570  				},
  1571  			},
  1572  			expected: nil,
  1573  		},
  1574  		{
  1575  			name: "With AutoUpgradeProfile UpgradeChannelNodeImage",
  1576  			input: ManagedControlPlaneScopeParams{
  1577  				Cluster: &clusterv1.Cluster{
  1578  					ObjectMeta: metav1.ObjectMeta{
  1579  						Name:      "cluster1",
  1580  						Namespace: "default",
  1581  					},
  1582  				},
  1583  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1584  					ObjectMeta: metav1.ObjectMeta{
  1585  						Name:      "cluster1",
  1586  						Namespace: "default",
  1587  					},
  1588  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1589  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1590  							SubscriptionID: "00000000-0000-0000-0000-000000000000",
  1591  							AutoUpgradeProfile: &infrav1.ManagedClusterAutoUpgradeProfile{
  1592  								UpgradeChannel: ptr.To(infrav1.UpgradeChannelNodeImage),
  1593  							},
  1594  						},
  1595  					},
  1596  				},
  1597  				ManagedMachinePools: []ManagedMachinePool{
  1598  					{
  1599  						MachinePool:      getMachinePool("pool0"),
  1600  						InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
  1601  					},
  1602  				},
  1603  			},
  1604  			expected: &managedclusters.ManagedClusterAutoUpgradeProfile{
  1605  				UpgradeChannel: ptr.To(infrav1.UpgradeChannelNodeImage),
  1606  			},
  1607  		},
  1608  	}
  1609  	for _, c := range cases {
  1610  		c := c
  1611  		t.Run(c.name, func(t *testing.T) {
  1612  			g := NewWithT(t)
  1613  			s := &ManagedControlPlaneScope{
  1614  				ControlPlane: c.input.ControlPlane,
  1615  				Cluster:      c.input.Cluster,
  1616  			}
  1617  			managedClusterGetter := s.ManagedClusterSpec()
  1618  			managedCluster, ok := managedClusterGetter.(*managedclusters.ManagedClusterSpec)
  1619  			g.Expect(ok).To(BeTrue())
  1620  			g.Expect(managedCluster.AutoUpgradeProfile).To(Equal(c.expected))
  1621  		})
  1622  	}
  1623  }
  1624  
  1625  func TestManagedControlPlaneScope_GroupSpecs(t *testing.T) {
  1626  	cases := []struct {
  1627  		name     string
  1628  		input    ManagedControlPlaneScopeParams
  1629  		expected []azure.ASOResourceSpecGetter[*asoresourcesv1.ResourceGroup]
  1630  	}{
  1631  		{
  1632  			name: "virtualNetwork belongs to a different resource group",
  1633  			input: ManagedControlPlaneScopeParams{
  1634  				Cluster: &clusterv1.Cluster{
  1635  					ObjectMeta: metav1.ObjectMeta{
  1636  						Name: "cluster1",
  1637  					},
  1638  				},
  1639  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1640  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1641  						ResourceGroupName: "dummy-rg",
  1642  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1643  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1644  								ResourceGroup: "different-rg",
  1645  							},
  1646  						},
  1647  					},
  1648  				},
  1649  			},
  1650  			expected: []azure.ASOResourceSpecGetter[*asoresourcesv1.ResourceGroup]{
  1651  				&groups.GroupSpec{
  1652  					Name:           "dummy-rg",
  1653  					AzureName:      "dummy-rg",
  1654  					ClusterName:    "cluster1",
  1655  					Location:       "",
  1656  					AdditionalTags: make(infrav1.Tags, 0),
  1657  				},
  1658  				&groups.GroupSpec{
  1659  					Name:           "different-rg",
  1660  					AzureName:      "different-rg",
  1661  					ClusterName:    "cluster1",
  1662  					Location:       "",
  1663  					AdditionalTags: make(infrav1.Tags, 0),
  1664  				},
  1665  			},
  1666  		},
  1667  		{
  1668  			name: "virtualNetwork belongs to a same resource group",
  1669  			input: ManagedControlPlaneScopeParams{
  1670  				Cluster: &clusterv1.Cluster{
  1671  					ObjectMeta: metav1.ObjectMeta{
  1672  						Name: "cluster1",
  1673  					},
  1674  				},
  1675  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1676  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1677  						ResourceGroupName: "dummy-rg",
  1678  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1679  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1680  								ResourceGroup: "dummy-rg",
  1681  							},
  1682  						},
  1683  					},
  1684  				},
  1685  			},
  1686  			expected: []azure.ASOResourceSpecGetter[*asoresourcesv1.ResourceGroup]{
  1687  				&groups.GroupSpec{
  1688  					Name:           "dummy-rg",
  1689  					AzureName:      "dummy-rg",
  1690  					ClusterName:    "cluster1",
  1691  					Location:       "",
  1692  					AdditionalTags: make(infrav1.Tags, 0),
  1693  				},
  1694  			},
  1695  		},
  1696  		{
  1697  			name: "virtualNetwork resource group not specified",
  1698  			input: ManagedControlPlaneScopeParams{
  1699  				Cluster: &clusterv1.Cluster{
  1700  					ObjectMeta: metav1.ObjectMeta{
  1701  						Name:      "cluster1",
  1702  						Namespace: "default",
  1703  					},
  1704  				},
  1705  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1706  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1707  						ResourceGroupName: "dummy-rg",
  1708  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1709  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1710  								ManagedControlPlaneVirtualNetworkClassSpec: infrav1.ManagedControlPlaneVirtualNetworkClassSpec{
  1711  									Name: "vnet1",
  1712  								},
  1713  							},
  1714  						},
  1715  					},
  1716  				},
  1717  			},
  1718  			expected: []azure.ASOResourceSpecGetter[*asoresourcesv1.ResourceGroup]{
  1719  				&groups.GroupSpec{
  1720  					Name:           "dummy-rg",
  1721  					AzureName:      "dummy-rg",
  1722  					ClusterName:    "cluster1",
  1723  					Location:       "",
  1724  					AdditionalTags: make(infrav1.Tags, 0),
  1725  				},
  1726  			},
  1727  		},
  1728  		{
  1729  			name: "virtualNetwork belongs to different resource group with non-k8s name",
  1730  			input: ManagedControlPlaneScopeParams{
  1731  				Cluster: &clusterv1.Cluster{
  1732  					ObjectMeta: metav1.ObjectMeta{
  1733  						Name:      "cluster1",
  1734  						Namespace: "default",
  1735  					},
  1736  				},
  1737  				ControlPlane: &infrav1.AzureManagedControlPlane{
  1738  					Spec: infrav1.AzureManagedControlPlaneSpec{
  1739  						ResourceGroupName: "dummy-rg",
  1740  						AzureManagedControlPlaneClassSpec: infrav1.AzureManagedControlPlaneClassSpec{
  1741  							VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
  1742  								ResourceGroup: "my_custom_rg",
  1743  								ManagedControlPlaneVirtualNetworkClassSpec: infrav1.ManagedControlPlaneVirtualNetworkClassSpec{
  1744  									Name: "vnet1",
  1745  								},
  1746  							},
  1747  						},
  1748  					},
  1749  				},
  1750  			},
  1751  			expected: []azure.ASOResourceSpecGetter[*asoresourcesv1.ResourceGroup]{
  1752  				&groups.GroupSpec{
  1753  					Name:           "dummy-rg",
  1754  					AzureName:      "dummy-rg",
  1755  					ClusterName:    "cluster1",
  1756  					Location:       "",
  1757  					AdditionalTags: make(infrav1.Tags, 0),
  1758  				},
  1759  				&groups.GroupSpec{
  1760  					Name:           "my-custom-rg",
  1761  					AzureName:      "my_custom_rg",
  1762  					ClusterName:    "cluster1",
  1763  					Location:       "",
  1764  					AdditionalTags: make(infrav1.Tags, 0),
  1765  				},
  1766  			},
  1767  		},
  1768  	}
  1769  
  1770  	for _, c := range cases {
  1771  		c := c
  1772  		t.Run(c.name, func(t *testing.T) {
  1773  			s := &ManagedControlPlaneScope{
  1774  				ControlPlane: c.input.ControlPlane,
  1775  				Cluster:      c.input.Cluster,
  1776  			}
  1777  			if got := s.GroupSpecs(); !reflect.DeepEqual(got, c.expected) {
  1778  				t.Errorf("GroupSpecs() = %s, want %s", specArrayToString(got), specArrayToString(c.expected))
  1779  			}
  1780  		})
  1781  	}
  1782  }