sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/scalesets/scalesets_test.go (about)

     1  /*
     2  Copyright 2020 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 scalesets
    18  
    19  import (
    20  	"context"
    21  	"io"
    22  	"net/http"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
    27  	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
    28  	. "github.com/onsi/gomega"
    29  	"go.uber.org/mock/gomock"
    30  	"k8s.io/client-go/kubernetes/scheme"
    31  	"k8s.io/utils/ptr"
    32  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    33  	"sigs.k8s.io/cluster-api-provider-azure/azure"
    34  	"sigs.k8s.io/cluster-api-provider-azure/azure/converters"
    35  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/async/mock_async"
    36  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/resourceskus"
    37  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/scalesets/mock_scalesets"
    38  	gomockinternal "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock"
    39  	azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure"
    40  	"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
    41  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    42  )
    43  
    44  const (
    45  	defaultSubscriptionID = "123"
    46  	defaultResourceGroup  = "my-rg"
    47  	defaultVMSSName       = "my-vmss"
    48  	vmSizeEPH             = "VM_SIZE_EPH"
    49  	vmSizeUSSD            = "VM_SIZE_USSD"
    50  	defaultVMSSID         = "subscriptions/1234/resourceGroups/my_resource_group/providers/Microsoft.Compute/virtualMachines/my-vm-id"
    51  	sshKeyData            = "ZmFrZXNzaGtleQo="
    52  )
    53  
    54  var (
    55  	defaultImage = infrav1.Image{
    56  		Marketplace: &infrav1.AzureMarketplaceImage{
    57  			ImagePlan: infrav1.ImagePlan{
    58  				Publisher: "fake-publisher",
    59  				Offer:     "my-offer",
    60  				SKU:       "sku-id",
    61  			},
    62  			Version: "1.0",
    63  		},
    64  	}
    65  
    66  	notFoundError = &azcore.ResponseError{StatusCode: http.StatusNotFound}
    67  )
    68  
    69  func internalError() *azcore.ResponseError {
    70  	return &azcore.ResponseError{
    71  		RawResponse: &http.Response{
    72  			Body:       io.NopCloser(strings.NewReader("#: Internal Server Error: StatusCode=500")),
    73  			StatusCode: http.StatusInternalServerError,
    74  		},
    75  	}
    76  }
    77  
    78  func init() {
    79  	_ = clusterv1.AddToScheme(scheme.Scheme)
    80  }
    81  
    82  func getDefaultVMSSSpec() azure.ResourceSpecGetter {
    83  	defaultSpec := newDefaultVMSSSpec()
    84  	defaultSpec.DataDisks = append(defaultSpec.DataDisks, infrav1.DataDisk{
    85  		NameSuffix: "my_disk_with_ultra_disks",
    86  		DiskSizeGB: 128,
    87  		Lun:        ptr.To[int32](3),
    88  		ManagedDisk: &infrav1.ManagedDiskParameters{
    89  			StorageAccountType: "UltraSSD_LRS",
    90  		},
    91  	})
    92  
    93  	return &defaultSpec
    94  }
    95  
    96  func getResultVMSS() armcompute.VirtualMachineScaleSet {
    97  	resultVMSS := newDefaultVMSS("VM_SIZE")
    98  	resultVMSS.ID = ptr.To(defaultVMSSID)
    99  
   100  	return resultVMSS
   101  }
   102  
   103  func TestReconcileVMSS(t *testing.T) {
   104  	defaultInstances := newDefaultInstances()
   105  	resultVMSS := newDefaultVMSS("VM_SIZE")
   106  	resultVMSS.ID = ptr.To(defaultVMSSID)
   107  	fetchedVMSS := converters.SDKToVMSS(getResultVMSS(), defaultInstances)
   108  
   109  	testcases := []struct {
   110  		name          string
   111  		expect        func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder)
   112  		expectedError string
   113  	}{
   114  		{
   115  			name:          "update an existing vmss",
   116  			expectedError: "",
   117  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   118  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   119  				spec := getDefaultVMSSSpec()
   120  				// Validate spec
   121  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   122  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(&resultVMSS, nil)
   123  				m.ListInstances(gomockinternal.AContext(), defaultSpec.ResourceGroup, defaultSpec.Name).Return(defaultInstances, nil)
   124  				r.CreateOrUpdateResource(gomockinternal.AContext(), spec, serviceName).Return(getResultVMSS(), nil)
   125  				s.UpdatePutStatus(infrav1.BootstrapSucceededCondition, serviceName, nil)
   126  
   127  				s.ReconcileReplicas(gomockinternal.AContext(), &fetchedVMSS).Return(nil)
   128  				s.SetProviderID(azureutil.ProviderIDPrefix + defaultVMSSID)
   129  				s.SetVMSSState(&fetchedVMSS)
   130  			},
   131  		},
   132  		{
   133  			name:          "create a vmss, skip list instances if vmss doesn't exist",
   134  			expectedError: "",
   135  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   136  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   137  				spec := getDefaultVMSSSpec()
   138  				// Validate spec
   139  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   140  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(nil, notFoundError)
   141  				r.CreateOrUpdateResource(gomockinternal.AContext(), spec, serviceName).Return(getResultVMSS(), nil)
   142  				s.UpdatePutStatus(infrav1.BootstrapSucceededCondition, serviceName, nil)
   143  
   144  				s.ReconcileReplicas(gomockinternal.AContext(), &fetchedVMSS).Return(nil)
   145  				s.SetProviderID(azureutil.ProviderIDPrefix + defaultVMSSID)
   146  				s.SetVMSSState(&fetchedVMSS)
   147  			},
   148  		},
   149  		{
   150  			name:          "error getting existing vmss",
   151  			expectedError: "failed to get existing VMSS:.*#: Internal Server Error: StatusCode=500",
   152  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   153  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   154  				spec := getDefaultVMSSSpec()
   155  				// Validate spec
   156  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   157  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(nil, internalError())
   158  			},
   159  		},
   160  		{
   161  			name:          "failed to list instances",
   162  			expectedError: "failed to get existing VMSS instances:.*#: Internal Server Error: StatusCode=500",
   163  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   164  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   165  				spec := getDefaultVMSSSpec()
   166  				// Validate spec
   167  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   168  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(&resultVMSS, nil)
   169  				m.ListInstances(gomockinternal.AContext(), defaultSpec.ResourceGroup, defaultSpec.Name).Return(defaultInstances, internalError())
   170  				s.UpdatePutStatus(infrav1.BootstrapSucceededCondition, serviceName, gomockinternal.ErrStrEq("failed to get existing VMSS instances: "+internalError().Error()))
   171  			},
   172  		},
   173  		{
   174  			name:          "failed to create a vmss",
   175  			expectedError: "#: Internal Server Error: StatusCode=500",
   176  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   177  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   178  				spec := getDefaultVMSSSpec()
   179  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   180  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(&resultVMSS, nil)
   181  				m.ListInstances(gomockinternal.AContext(), defaultSpec.ResourceGroup, defaultSpec.Name).Return(defaultInstances, nil)
   182  
   183  				r.CreateOrUpdateResource(gomockinternal.AContext(), spec, serviceName).
   184  					Return(nil, internalError())
   185  				s.UpdatePutStatus(infrav1.BootstrapSucceededCondition, serviceName, internalError())
   186  			},
   187  		},
   188  		{
   189  			name:          "failed to reconcile replicas",
   190  			expectedError: "unable to reconcile VMSS replicas:.*#: Internal Server Error: StatusCode=500",
   191  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   192  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   193  				spec := getDefaultVMSSSpec()
   194  				s.ScaleSetSpec(gomockinternal.AContext()).Return(spec).AnyTimes()
   195  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(&resultVMSS, nil)
   196  				m.ListInstances(gomockinternal.AContext(), defaultSpec.ResourceGroup, defaultSpec.Name).Return(defaultInstances, nil)
   197  
   198  				r.CreateOrUpdateResource(gomockinternal.AContext(), spec, serviceName).Return(getResultVMSS(), nil)
   199  				s.UpdatePutStatus(infrav1.BootstrapSucceededCondition, serviceName, nil)
   200  
   201  				s.ReconcileReplicas(gomockinternal.AContext(), &fetchedVMSS).Return(internalError())
   202  			},
   203  		},
   204  		{
   205  			name:          "validate spec failure: less than 2 vCPUs",
   206  			expectedError: "reconcile error that cannot be recovered occurred: vm size should be bigger or equal to at least 2 vCPUs. Object will not be requeued",
   207  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   208  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   209  				spec := newDefaultVMSSSpec()
   210  				spec.Size = "VM_SIZE_1_CPU"
   211  				spec.Capacity = 2
   212  				spec.SSHKeyData = sshKeyData
   213  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   214  			},
   215  		},
   216  		{
   217  			name:          "validate spec failure: Memory is less than 2Gi",
   218  			expectedError: "reconcile error that cannot be recovered occurred: vm memory should be bigger or equal to at least 2Gi. Object will not be requeued",
   219  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   220  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   221  				spec := newDefaultVMSSSpec()
   222  				spec.Size = "VM_SIZE_1_MEM"
   223  				spec.Capacity = 2
   224  				spec.SSHKeyData = sshKeyData
   225  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   226  			},
   227  		},
   228  		{
   229  			name:          "validate spec failure: failed to get SKU",
   230  			expectedError: "failed to get SKU INVALID_VM_SIZE in compute api: reconcile error that cannot be recovered occurred: resource sku with name 'INVALID_VM_SIZE' and category 'virtualMachines' not found in location 'test-location'. Object will not be requeued",
   231  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   232  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   233  				spec := newDefaultVMSSSpec()
   234  				spec.Size = "INVALID_VM_SIZE"
   235  				spec.Capacity = 2
   236  				spec.SSHKeyData = sshKeyData
   237  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   238  			},
   239  		},
   240  		{
   241  			name:          "validate spec failure: fail to create a vm with ultra disk implicitly enabled by data disk, when location not supported",
   242  			expectedError: "reconcile error that cannot be recovered occurred: vm size VM_SIZE_USSD does not support ultra disks in location test-location. select a different vm size or disable ultra disks. Object will not be requeued",
   243  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   244  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   245  				spec := newDefaultVMSSSpec()
   246  				spec.Size = vmSizeUSSD
   247  				spec.Capacity = 2
   248  				spec.SSHKeyData = sshKeyData
   249  				spec.DataDisks = append(spec.DataDisks, infrav1.DataDisk{
   250  					ManagedDisk: &infrav1.ManagedDiskParameters{
   251  						StorageAccountType: "UltraSSD_LRS",
   252  					},
   253  				})
   254  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   255  			},
   256  		},
   257  		{
   258  			name:          "validate spec failure: fail to create a vm with ultra disk explicitly enabled via additional capabilities, when location not supported",
   259  			expectedError: "reconcile error that cannot be recovered occurred: vm size VM_SIZE_USSD does not support ultra disks in location test-location. select a different vm size or disable ultra disks. Object will not be requeued",
   260  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   261  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   262  				spec := newDefaultVMSSSpec()
   263  				spec.Size = vmSizeUSSD
   264  				spec.Capacity = 2
   265  				spec.SSHKeyData = sshKeyData
   266  				spec.AdditionalCapabilities = &infrav1.AdditionalCapabilities{
   267  					UltraSSDEnabled: ptr.To(true),
   268  				}
   269  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   270  			},
   271  		},
   272  		{
   273  			name:          "validate spec failure: fail to create a vm with ultra disk explicitly enabled via additional capabilities, when location not supported",
   274  			expectedError: "reconcile error that cannot be recovered occurred: vm size VM_SIZE_USSD does not support ultra disks in location test-location. select a different vm size or disable ultra disks. Object will not be requeued",
   275  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   276  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   277  				spec := newDefaultVMSSSpec()
   278  				spec.Size = vmSizeUSSD
   279  				spec.Capacity = 2
   280  				spec.SSHKeyData = sshKeyData
   281  				spec.DataDisks = append(spec.DataDisks, infrav1.DataDisk{
   282  					ManagedDisk: &infrav1.ManagedDiskParameters{
   283  						StorageAccountType: "UltraSSD_LRS",
   284  					},
   285  				})
   286  				spec.AdditionalCapabilities = &infrav1.AdditionalCapabilities{
   287  					UltraSSDEnabled: ptr.To(true),
   288  				}
   289  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   290  			},
   291  		},
   292  		{
   293  			name:          "validate spec failure: fail to create a vm with diagnostics set to User Managed but empty StorageAccountURI",
   294  			expectedError: "reconcile error that cannot be recovered occurred: userManaged must be specified when storageAccountType is 'UserManaged'. Object will not be requeued",
   295  			expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   296  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   297  				spec := newDefaultVMSSSpec()
   298  				spec.Size = vmSizeUSSD
   299  				spec.Capacity = 2
   300  				spec.SSHKeyData = sshKeyData
   301  				spec.DiagnosticsProfile = &infrav1.Diagnostics{
   302  					Boot: &infrav1.BootDiagnostics{
   303  						StorageAccountType: infrav1.UserManagedDiagnosticsStorage,
   304  						UserManaged:        nil,
   305  					},
   306  				}
   307  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&spec).AnyTimes()
   308  			},
   309  		},
   310  	}
   311  
   312  	for _, tc := range testcases {
   313  		tc := tc
   314  		t.Run(tc.name, func(t *testing.T) {
   315  			g := NewWithT(t)
   316  			t.Parallel()
   317  			mockCtrl := gomock.NewController(t)
   318  			defer mockCtrl.Finish()
   319  
   320  			scopeMock := mock_scalesets.NewMockScaleSetScope(mockCtrl)
   321  			asyncMock := mock_async.NewMockReconciler(mockCtrl)
   322  			clientMock := mock_scalesets.NewMockClient(mockCtrl)
   323  
   324  			tc.expect(g, scopeMock.EXPECT(), asyncMock.EXPECT(), clientMock.EXPECT())
   325  
   326  			s := &Service{
   327  				Scope:            scopeMock,
   328  				Reconciler:       asyncMock,
   329  				Client:           clientMock,
   330  				resourceSKUCache: resourceskus.NewStaticCache(getFakeSkus(), "test-location"),
   331  			}
   332  
   333  			err := s.Reconcile(context.TODO())
   334  			if tc.expectedError != "" {
   335  				g.Expect(err).To(HaveOccurred())
   336  				g.Expect(strings.ReplaceAll(err.Error(), "\n", "")).To(MatchRegexp(tc.expectedError), err.Error())
   337  			} else {
   338  				g.Expect(err).NotTo(HaveOccurred())
   339  			}
   340  		})
   341  	}
   342  }
   343  
   344  func TestDeleteVMSS(t *testing.T) {
   345  	defaultSpec := newDefaultVMSSSpec()
   346  	defaultInstances := newDefaultInstances()
   347  	resultVMSS := newDefaultVMSS("VM_SIZE")
   348  	resultVMSS.ID = ptr.To(defaultVMSSID)
   349  	fetchedVMSS := converters.SDKToVMSS(getResultVMSS(), defaultInstances)
   350  	// Be careful about race conditions if you need modify these.
   351  
   352  	testcases := []struct {
   353  		name          string
   354  		expectedError string
   355  		expect        func(s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder)
   356  	}{
   357  		{
   358  			name:          "successfully delete an existing vmss",
   359  			expectedError: "",
   360  			expect: func(s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   361  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   362  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&defaultSpec).AnyTimes()
   363  				r.DeleteResource(gomockinternal.AContext(), &defaultSpec, serviceName).Return(nil)
   364  				s.UpdateDeleteStatus(infrav1.BootstrapSucceededCondition, serviceName, nil)
   365  
   366  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(resultVMSS, nil)
   367  				m.ListInstances(gomockinternal.AContext(), defaultSpec.ResourceGroup, defaultSpec.Name).Return(defaultInstances, nil)
   368  				s.SetVMSSState(&fetchedVMSS)
   369  			},
   370  		},
   371  		{
   372  			name:          "successfully delete an existing vmss, fetch call returns error",
   373  			expectedError: "",
   374  			expect: func(s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   375  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   376  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&defaultSpec).AnyTimes()
   377  				r.DeleteResource(gomockinternal.AContext(), &defaultSpec, serviceName).Return(nil)
   378  				s.UpdateDeleteStatus(infrav1.BootstrapSucceededCondition, serviceName, nil)
   379  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(armcompute.VirtualMachineScaleSet{}, notFoundError)
   380  			},
   381  		},
   382  		{
   383  			name:          "failed to delete an existing vmss",
   384  			expectedError: "#: Internal Server Error: StatusCode=500",
   385  			expect: func(s *mock_scalesets.MockScaleSetScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder, m *mock_scalesets.MockClientMockRecorder) {
   386  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   387  				s.ScaleSetSpec(gomockinternal.AContext()).Return(&defaultSpec).AnyTimes()
   388  				r.DeleteResource(gomockinternal.AContext(), &defaultSpec, serviceName).Return(internalError())
   389  				s.UpdateDeleteStatus(infrav1.BootstrapSucceededCondition, serviceName, internalError())
   390  				m.Get(gomockinternal.AContext(), &defaultSpec).Return(armcompute.VirtualMachineScaleSet{}, notFoundError)
   391  			},
   392  		},
   393  	}
   394  
   395  	for _, tc := range testcases {
   396  		tc := tc
   397  		t.Run(tc.name, func(t *testing.T) {
   398  			g := NewWithT(t)
   399  			t.Parallel()
   400  			mockCtrl := gomock.NewController(t)
   401  			defer mockCtrl.Finish()
   402  			scopeMock := mock_scalesets.NewMockScaleSetScope(mockCtrl)
   403  			asyncMock := mock_async.NewMockReconciler(mockCtrl)
   404  			mockClient := mock_scalesets.NewMockClient(mockCtrl)
   405  
   406  			tc.expect(scopeMock.EXPECT(), asyncMock.EXPECT(), mockClient.EXPECT())
   407  
   408  			s := &Service{
   409  				Scope:      scopeMock,
   410  				Reconciler: asyncMock,
   411  				Client:     mockClient,
   412  			}
   413  
   414  			err := s.Delete(context.TODO())
   415  			if tc.expectedError != "" {
   416  				g.Expect(err).To(HaveOccurred())
   417  				g.Expect(err.Error()).To(ContainSubstring(tc.expectedError))
   418  			} else {
   419  				g.Expect(err).NotTo(HaveOccurred())
   420  			}
   421  		})
   422  	}
   423  }
   424  
   425  func getFakeSkus() []armcompute.ResourceSKU {
   426  	return []armcompute.ResourceSKU{
   427  		{
   428  			Name:         ptr.To("VM_SIZE"),
   429  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   430  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   431  			Locations: []*string{
   432  				ptr.To("test-location"),
   433  			},
   434  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   435  				{
   436  					Location: ptr.To("test-location"),
   437  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   438  					ZoneDetails: []*armcompute.ResourceSKUZoneDetails{
   439  						{
   440  							Capabilities: []*armcompute.ResourceSKUCapabilities{
   441  								{
   442  									Name:  ptr.To("UltraSSDAvailable"),
   443  									Value: ptr.To("True"),
   444  								},
   445  							},
   446  							Name: []*string{ptr.To("1"), ptr.To("3")},
   447  						},
   448  					},
   449  				},
   450  			},
   451  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   452  				{
   453  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   454  					Value: ptr.To(string(resourceskus.CapabilityUnsupported)),
   455  				},
   456  				{
   457  					Name:  ptr.To(resourceskus.VCPUs),
   458  					Value: ptr.To("4"),
   459  				},
   460  				{
   461  					Name:  ptr.To(resourceskus.MemoryGB),
   462  					Value: ptr.To("4"),
   463  				},
   464  			},
   465  		},
   466  		{
   467  			Name:         ptr.To("VM_SIZE_AN"),
   468  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   469  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   470  			Locations: []*string{
   471  				ptr.To("test-location"),
   472  			},
   473  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   474  				{
   475  					Location: ptr.To("test-location"),
   476  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   477  				},
   478  			},
   479  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   480  				{
   481  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   482  					Value: ptr.To(string(resourceskus.CapabilitySupported)),
   483  				},
   484  				{
   485  					Name:  ptr.To(resourceskus.VCPUs),
   486  					Value: ptr.To("4"),
   487  				},
   488  				{
   489  					Name:  ptr.To(resourceskus.MemoryGB),
   490  					Value: ptr.To("6"),
   491  				},
   492  			},
   493  		},
   494  		{
   495  			Name:         ptr.To("VM_SIZE_1_CPU"),
   496  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   497  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   498  			Locations: []*string{
   499  				ptr.To("test-location"),
   500  			},
   501  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   502  				{
   503  					Location: ptr.To("test-location"),
   504  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   505  				},
   506  			},
   507  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   508  				{
   509  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   510  					Value: ptr.To(string(resourceskus.CapabilityUnsupported)),
   511  				},
   512  				{
   513  					Name:  ptr.To(resourceskus.VCPUs),
   514  					Value: ptr.To("1"),
   515  				},
   516  				{
   517  					Name:  ptr.To(resourceskus.MemoryGB),
   518  					Value: ptr.To("4"),
   519  				},
   520  			},
   521  		},
   522  		{
   523  			Name:         ptr.To("VM_SIZE_1_MEM"),
   524  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   525  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   526  			Locations: []*string{
   527  				ptr.To("test-location"),
   528  			},
   529  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   530  				{
   531  					Location: ptr.To("test-location"),
   532  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   533  				},
   534  			},
   535  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   536  				{
   537  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   538  					Value: ptr.To(string(resourceskus.CapabilityUnsupported)),
   539  				},
   540  				{
   541  					Name:  ptr.To(resourceskus.VCPUs),
   542  					Value: ptr.To("2"),
   543  				},
   544  				{
   545  					Name:  ptr.To(resourceskus.MemoryGB),
   546  					Value: ptr.To("1"),
   547  				},
   548  			},
   549  		},
   550  		{
   551  			Name:         ptr.To("VM_SIZE_EAH"),
   552  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   553  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   554  			Locations: []*string{
   555  				ptr.To("test-location"),
   556  			},
   557  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   558  				{
   559  					Location: ptr.To("test-location"),
   560  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   561  				},
   562  			},
   563  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   564  				{
   565  					Name:  ptr.To(resourceskus.VCPUs),
   566  					Value: ptr.To("4"),
   567  				},
   568  				{
   569  					Name:  ptr.To(resourceskus.MemoryGB),
   570  					Value: ptr.To("8"),
   571  				},
   572  				{
   573  					Name:  ptr.To(resourceskus.EncryptionAtHost),
   574  					Value: ptr.To(string(resourceskus.CapabilitySupported)),
   575  				},
   576  			},
   577  		},
   578  		{
   579  			Name:         ptr.To(vmSizeUSSD),
   580  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   581  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   582  			Locations: []*string{
   583  				ptr.To("test-location"),
   584  			},
   585  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   586  				{
   587  					Location: ptr.To("test-location"),
   588  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   589  				},
   590  			},
   591  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   592  				{
   593  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   594  					Value: ptr.To(string(resourceskus.CapabilitySupported)),
   595  				},
   596  				{
   597  					Name:  ptr.To(resourceskus.VCPUs),
   598  					Value: ptr.To("4"),
   599  				},
   600  				{
   601  					Name:  ptr.To(resourceskus.MemoryGB),
   602  					Value: ptr.To("6"),
   603  				},
   604  			},
   605  		},
   606  		{
   607  			Name:         ptr.To("VM_SIZE_EPH"),
   608  			ResourceType: ptr.To(string(resourceskus.VirtualMachines)),
   609  			Kind:         ptr.To(string(resourceskus.VirtualMachines)),
   610  			Locations: []*string{
   611  				ptr.To("test-location"),
   612  			},
   613  			LocationInfo: []*armcompute.ResourceSKULocationInfo{
   614  				{
   615  					Location: ptr.To("test-location"),
   616  					Zones:    []*string{ptr.To("1"), ptr.To("3")},
   617  					ZoneDetails: []*armcompute.ResourceSKUZoneDetails{
   618  						{
   619  							Capabilities: []*armcompute.ResourceSKUCapabilities{
   620  								{
   621  									Name:  ptr.To("UltraSSDAvailable"),
   622  									Value: ptr.To("True"),
   623  								},
   624  							},
   625  							Name: []*string{ptr.To("1"), ptr.To("3")},
   626  						},
   627  					},
   628  				},
   629  			},
   630  			Capabilities: []*armcompute.ResourceSKUCapabilities{
   631  				{
   632  					Name:  ptr.To(resourceskus.AcceleratedNetworking),
   633  					Value: ptr.To(string(resourceskus.CapabilityUnsupported)),
   634  				},
   635  				{
   636  					Name:  ptr.To(resourceskus.VCPUs),
   637  					Value: ptr.To("4"),
   638  				},
   639  				{
   640  					Name:  ptr.To(resourceskus.MemoryGB),
   641  					Value: ptr.To("4"),
   642  				},
   643  				{
   644  					Name:  ptr.To(resourceskus.EphemeralOSDisk),
   645  					Value: ptr.To("True"),
   646  				},
   647  			},
   648  		},
   649  	}
   650  }
   651  
   652  func newDefaultVMSSSpec() ScaleSetSpec {
   653  	return ScaleSetSpec{
   654  		Name:       defaultVMSSName,
   655  		Size:       "VM_SIZE",
   656  		Capacity:   2,
   657  		SSHKeyData: sshKeyData,
   658  		OSDisk: infrav1.OSDisk{
   659  			OSType:     "Linux",
   660  			DiskSizeGB: ptr.To[int32](120),
   661  			ManagedDisk: &infrav1.ManagedDiskParameters{
   662  				StorageAccountType: "Premium_LRS",
   663  			},
   664  		},
   665  		DataDisks: []infrav1.DataDisk{
   666  			{
   667  				NameSuffix: "my_disk",
   668  				DiskSizeGB: 128,
   669  				Lun:        ptr.To[int32](0),
   670  			},
   671  			{
   672  				NameSuffix: "my_disk_with_managed_disk",
   673  				DiskSizeGB: 128,
   674  				Lun:        ptr.To[int32](1),
   675  				ManagedDisk: &infrav1.ManagedDiskParameters{
   676  					StorageAccountType: "Standard_LRS",
   677  				},
   678  			},
   679  			{
   680  				NameSuffix: "managed_disk_with_encryption",
   681  				DiskSizeGB: 128,
   682  				Lun:        ptr.To[int32](2),
   683  				ManagedDisk: &infrav1.ManagedDiskParameters{
   684  					StorageAccountType: "Standard_LRS",
   685  					DiskEncryptionSet: &infrav1.DiskEncryptionSetParameters{
   686  						ID: "encryption_id",
   687  					},
   688  				},
   689  			},
   690  		},
   691  		DiagnosticsProfile: &infrav1.Diagnostics{
   692  			Boot: &infrav1.BootDiagnostics{
   693  				StorageAccountType: infrav1.ManagedDiagnosticsStorage,
   694  			},
   695  		},
   696  		SubnetName:                   "my-subnet",
   697  		VNetName:                     "my-vnet",
   698  		VNetResourceGroup:            defaultResourceGroup,
   699  		PublicLBName:                 "capz-lb",
   700  		PublicLBAddressPoolName:      "backendPool",
   701  		AcceleratedNetworking:        nil,
   702  		TerminateNotificationTimeout: ptr.To(7),
   703  		FailureDomains:               []string{"1", "3"},
   704  		NetworkInterfaces: []infrav1.NetworkInterface{
   705  			{
   706  				SubnetName:       "my-subnet",
   707  				PrivateIPConfigs: 1,
   708  			},
   709  		},
   710  		SubscriptionID: "123",
   711  		ResourceGroup:  "my-rg",
   712  		Location:       "test-location",
   713  		ClusterName:    "my-cluster",
   714  		VMSSInstances:  newDefaultInstances(),
   715  		VMImage:        &defaultImage,
   716  		BootstrapData:  "fake-bootstrap-data",
   717  		VMSSExtensionSpecs: []azure.ResourceSpecGetter{
   718  			&VMSSExtensionSpec{
   719  				ExtensionSpec: azure.ExtensionSpec{
   720  					Name:      "someExtension",
   721  					VMName:    "my-vmss",
   722  					Publisher: "somePublisher",
   723  					Version:   "someVersion",
   724  					Settings: map[string]string{
   725  						"someSetting": "someValue",
   726  					},
   727  					ProtectedSettings: map[string]string{
   728  						"commandToExecute": "echo hello",
   729  					},
   730  				},
   731  				ResourceGroup: "my-rg",
   732  			},
   733  		},
   734  		PlatformFaultDomainCount: ptr.To(int32(1)),
   735  		ZoneBalance:              ptr.To(true),
   736  	}
   737  }
   738  
   739  func newWindowsVMSSSpec() ScaleSetSpec {
   740  	vmss := newDefaultVMSSSpec()
   741  	vmss.OSDisk.OSType = azure.WindowsOS
   742  	return vmss
   743  }
   744  
   745  func newDefaultExistingVMSS(vmSize string) armcompute.VirtualMachineScaleSet {
   746  	vmss := newDefaultVMSS(vmSize)
   747  	vmss.ID = ptr.To("subscriptions/1234/resourceGroups/my_resource_group/providers/Microsoft.Compute/virtualMachines/my-vm")
   748  	return vmss
   749  }
   750  
   751  func newDefaultWindowsVMSS() armcompute.VirtualMachineScaleSet {
   752  	vmss := newDefaultVMSS("VM_SIZE")
   753  	vmss.Properties.VirtualMachineProfile.StorageProfile.OSDisk.OSType = ptr.To(armcompute.OperatingSystemTypesWindows)
   754  	vmss.Properties.VirtualMachineProfile.OSProfile.LinuxConfiguration = nil
   755  	vmss.Properties.VirtualMachineProfile.OSProfile.WindowsConfiguration = &armcompute.WindowsConfiguration{
   756  		EnableAutomaticUpdates: ptr.To(false),
   757  	}
   758  	return vmss
   759  }
   760  
   761  func newDefaultVMSS(vmSize string) armcompute.VirtualMachineScaleSet {
   762  	dataDisk := fetchDataDiskBasedOnSize(vmSize)
   763  	return armcompute.VirtualMachineScaleSet{
   764  		Location: ptr.To("test-location"),
   765  		Tags: map[string]*string{
   766  			"Name": ptr.To(defaultVMSSName),
   767  			"sigs.k8s.io_cluster-api-provider-azure_cluster_my-cluster": ptr.To("owned"),
   768  			"sigs.k8s.io_cluster-api-provider-azure_role":               ptr.To("node"),
   769  		},
   770  		SKU: &armcompute.SKU{
   771  			Name:     ptr.To(vmSize),
   772  			Tier:     ptr.To("Standard"),
   773  			Capacity: ptr.To[int64](2),
   774  		},
   775  		Zones: []*string{ptr.To("1"), ptr.To("3")},
   776  		Properties: &armcompute.VirtualMachineScaleSetProperties{
   777  			SinglePlacementGroup: ptr.To(false),
   778  			UpgradePolicy: &armcompute.UpgradePolicy{
   779  				Mode: ptr.To(armcompute.UpgradeModeManual),
   780  			},
   781  			Overprovision:     ptr.To(false),
   782  			OrchestrationMode: ptr.To(armcompute.OrchestrationModeUniform),
   783  			VirtualMachineProfile: &armcompute.VirtualMachineScaleSetVMProfile{
   784  				OSProfile: &armcompute.VirtualMachineScaleSetOSProfile{
   785  					ComputerNamePrefix: ptr.To(defaultVMSSName),
   786  					AdminUsername:      ptr.To(azure.DefaultUserName),
   787  					CustomData:         ptr.To("fake-bootstrap-data"),
   788  					LinuxConfiguration: &armcompute.LinuxConfiguration{
   789  						SSH: &armcompute.SSHConfiguration{
   790  							PublicKeys: []*armcompute.SSHPublicKey{
   791  								{
   792  									Path:    ptr.To("/home/capi/.ssh/authorized_keys"),
   793  									KeyData: ptr.To("fakesshkey\n"),
   794  								},
   795  							},
   796  						},
   797  						DisablePasswordAuthentication: ptr.To(true),
   798  					},
   799  				},
   800  				ScheduledEventsProfile: &armcompute.ScheduledEventsProfile{
   801  					TerminateNotificationProfile: &armcompute.TerminateNotificationProfile{
   802  						NotBeforeTimeout: ptr.To("PT7M"),
   803  						Enable:           ptr.To(true),
   804  					},
   805  				},
   806  				StorageProfile: &armcompute.VirtualMachineScaleSetStorageProfile{
   807  					ImageReference: &armcompute.ImageReference{
   808  						Publisher: ptr.To("fake-publisher"),
   809  						Offer:     ptr.To("my-offer"),
   810  						SKU:       ptr.To("sku-id"),
   811  						Version:   ptr.To("1.0"),
   812  					},
   813  					OSDisk: &armcompute.VirtualMachineScaleSetOSDisk{
   814  						OSType:       ptr.To(armcompute.OperatingSystemTypesLinux),
   815  						CreateOption: ptr.To(armcompute.DiskCreateOptionTypesFromImage),
   816  						DiskSizeGB:   ptr.To[int32](120),
   817  						ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   818  							StorageAccountType: ptr.To(armcompute.StorageAccountTypesPremiumLRS),
   819  						},
   820  					},
   821  					DataDisks: dataDisk,
   822  				},
   823  				DiagnosticsProfile: &armcompute.DiagnosticsProfile{
   824  					BootDiagnostics: &armcompute.BootDiagnostics{
   825  						Enabled: ptr.To(true),
   826  					},
   827  				},
   828  				NetworkProfile: &armcompute.VirtualMachineScaleSetNetworkProfile{
   829  					NetworkInterfaceConfigurations: []*armcompute.VirtualMachineScaleSetNetworkConfiguration{
   830  						{
   831  							Name: ptr.To("my-vmss-nic-0"),
   832  							Properties: &armcompute.VirtualMachineScaleSetNetworkConfigurationProperties{
   833  								Primary:                     ptr.To(true),
   834  								EnableAcceleratedNetworking: ptr.To(false),
   835  								EnableIPForwarding:          ptr.To(true),
   836  								IPConfigurations: []*armcompute.VirtualMachineScaleSetIPConfiguration{
   837  									{
   838  										Name: ptr.To("ipConfig0"),
   839  										Properties: &armcompute.VirtualMachineScaleSetIPConfigurationProperties{
   840  											Subnet: &armcompute.APIEntityReference{
   841  												ID: ptr.To("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/my-subnet"),
   842  											},
   843  											Primary:                         ptr.To(true),
   844  											PrivateIPAddressVersion:         ptr.To(armcompute.IPVersionIPv4),
   845  											LoadBalancerBackendAddressPools: []*armcompute.SubResource{{ID: ptr.To("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/loadBalancers/capz-lb/backendAddressPools/backendPool")}},
   846  										},
   847  									},
   848  								},
   849  							},
   850  						},
   851  					},
   852  				},
   853  				ExtensionProfile: &armcompute.VirtualMachineScaleSetExtensionProfile{
   854  					Extensions: []*armcompute.VirtualMachineScaleSetExtension{
   855  						{
   856  							Name: ptr.To("someExtension"),
   857  							Properties: &armcompute.VirtualMachineScaleSetExtensionProperties{
   858  								Publisher:          ptr.To("somePublisher"),
   859  								Type:               ptr.To("someExtension"),
   860  								TypeHandlerVersion: ptr.To("someVersion"),
   861  								Settings: map[string]string{
   862  									"someSetting": "someValue",
   863  								},
   864  								ProtectedSettings: map[string]string{
   865  									"commandToExecute": "echo hello",
   866  								},
   867  							},
   868  						},
   869  					},
   870  				},
   871  			},
   872  			PlatformFaultDomainCount: ptr.To(int32(1)),
   873  			ZoneBalance:              ptr.To(true),
   874  			// AdditionalCapabilities: &armcompute.AdditionalCapabilities{UltraSSDEnabled: ptr.To(true)},
   875  		},
   876  	}
   877  }
   878  
   879  func fetchDataDiskBasedOnSize(vmSize string) []*armcompute.VirtualMachineScaleSetDataDisk {
   880  	var dataDisk []*armcompute.VirtualMachineScaleSetDataDisk
   881  	if vmSize == "VM_SIZE" {
   882  		dataDisk = []*armcompute.VirtualMachineScaleSetDataDisk{
   883  			{
   884  				Lun:          ptr.To[int32](0),
   885  				Name:         ptr.To("my-vmss_my_disk"),
   886  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   887  				DiskSizeGB:   ptr.To[int32](128),
   888  			},
   889  			{
   890  				Lun:          ptr.To[int32](1),
   891  				Name:         ptr.To("my-vmss_my_disk_with_managed_disk"),
   892  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   893  				DiskSizeGB:   ptr.To[int32](128),
   894  				ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   895  					StorageAccountType: ptr.To(armcompute.StorageAccountTypesStandardLRS),
   896  				},
   897  			},
   898  			{
   899  				Lun:          ptr.To[int32](2),
   900  				Name:         ptr.To("my-vmss_managed_disk_with_encryption"),
   901  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   902  				DiskSizeGB:   ptr.To[int32](128),
   903  				ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   904  					StorageAccountType: ptr.To(armcompute.StorageAccountTypesStandardLRS),
   905  					DiskEncryptionSet: &armcompute.DiskEncryptionSetParameters{
   906  						ID: ptr.To("encryption_id"),
   907  					},
   908  				},
   909  			},
   910  			{
   911  				Lun:          ptr.To[int32](3),
   912  				Name:         ptr.To("my-vmss_my_disk_with_ultra_disks"),
   913  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   914  				DiskSizeGB:   ptr.To[int32](128),
   915  				ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   916  					StorageAccountType: ptr.To(armcompute.StorageAccountTypesUltraSSDLRS),
   917  				},
   918  			},
   919  		}
   920  	} else {
   921  		dataDisk = []*armcompute.VirtualMachineScaleSetDataDisk{
   922  			{
   923  				Lun:          ptr.To[int32](0),
   924  				Name:         ptr.To("my-vmss_my_disk"),
   925  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   926  				DiskSizeGB:   ptr.To[int32](128),
   927  			},
   928  			{
   929  				Lun:          ptr.To[int32](1),
   930  				Name:         ptr.To("my-vmss_my_disk_with_managed_disk"),
   931  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   932  				DiskSizeGB:   ptr.To[int32](128),
   933  				ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   934  					StorageAccountType: ptr.To(armcompute.StorageAccountTypesStandardLRS),
   935  				},
   936  			},
   937  			{
   938  				Lun:          ptr.To[int32](2),
   939  				Name:         ptr.To("my-vmss_managed_disk_with_encryption"),
   940  				CreateOption: ptr.To(armcompute.DiskCreateOptionTypesEmpty),
   941  				DiskSizeGB:   ptr.To[int32](128),
   942  				ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{
   943  					StorageAccountType: ptr.To(armcompute.StorageAccountTypesStandardLRS),
   944  					DiskEncryptionSet: &armcompute.DiskEncryptionSetParameters{
   945  						ID: ptr.To("encryption_id"),
   946  					},
   947  				},
   948  			},
   949  		}
   950  	}
   951  	return dataDisk
   952  }
   953  
   954  func newDefaultInstances() []armcompute.VirtualMachineScaleSetVM {
   955  	return []armcompute.VirtualMachineScaleSetVM{
   956  		{
   957  			ID:         ptr.To("my-vm-id"),
   958  			InstanceID: ptr.To("my-vm-1"),
   959  			Name:       ptr.To("my-vm"),
   960  			Properties: &armcompute.VirtualMachineScaleSetVMProperties{
   961  				ProvisioningState: ptr.To("Succeeded"),
   962  				OSProfile: &armcompute.OSProfile{
   963  					ComputerName: ptr.To("instance-000001"),
   964  				},
   965  				StorageProfile: &armcompute.StorageProfile{
   966  					ImageReference: &armcompute.ImageReference{
   967  						Publisher: ptr.To("fake-publisher"),
   968  						Offer:     ptr.To("my-offer"),
   969  						SKU:       ptr.To("sku-id"),
   970  						Version:   ptr.To("1.0"),
   971  					},
   972  				},
   973  			},
   974  		},
   975  		{
   976  			ID:         ptr.To("my-vm-id"),
   977  			InstanceID: ptr.To("my-vm-2"),
   978  			Name:       ptr.To("my-vm"),
   979  			Properties: &armcompute.VirtualMachineScaleSetVMProperties{
   980  				ProvisioningState: ptr.To("Succeeded"),
   981  				OSProfile: &armcompute.OSProfile{
   982  					ComputerName: ptr.To("instance-000002"),
   983  				},
   984  				StorageProfile: &armcompute.StorageProfile{
   985  					ImageReference: &armcompute.ImageReference{
   986  						Publisher: ptr.To("fake-publisher"),
   987  						Offer:     ptr.To("my-offer"),
   988  						SKU:       ptr.To("sku-id"),
   989  						Version:   ptr.To("1.0"),
   990  					},
   991  				},
   992  			},
   993  		},
   994  	}
   995  }