Skip to content

Commit c0f616c

Browse files
committed
Add unit tests for AzureManagedMachinePoolController
1 parent 4fc2041 commit c0f616c

File tree

2 files changed

+417
-0
lines changed

2 files changed

+417
-0
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/*
2+
Copyright 2019 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 controllers
18+
19+
import (
20+
"context"
21+
"os"
22+
"testing"
23+
"time"
24+
25+
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-11-01/compute"
26+
"github.com/Azure/go-autorest/autorest/azure/auth"
27+
"github.com/golang/mock/gomock"
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/apimachinery/pkg/types"
33+
"k8s.io/client-go/kubernetes/scheme"
34+
"k8s.io/utils/pointer"
35+
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
36+
"sigs.k8s.io/cluster-api-provider-azure/azure/mock_azure"
37+
"sigs.k8s.io/cluster-api-provider-azure/azure/scope"
38+
"sigs.k8s.io/cluster-api-provider-azure/azure/services/agentpools"
39+
"sigs.k8s.io/cluster-api-provider-azure/azure/services/agentpools/mock_agentpools"
40+
gomock2 "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock"
41+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
42+
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
43+
ctrl "sigs.k8s.io/controller-runtime"
44+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
45+
)
46+
47+
func TestAzureManagedMachinePoolReconcile(t *testing.T) {
48+
os.Setenv(auth.ClientID, "fooClient")
49+
os.Setenv(auth.ClientSecret, "fooSecret")
50+
os.Setenv(auth.TenantID, "fooTenant")
51+
os.Setenv(auth.SubscriptionID, "fooSubscription")
52+
53+
cases := []struct {
54+
name string
55+
Setup func(cb *fake.ClientBuilder, reconciler *mock_azure.MockReconcilerMockRecorder, agentpools *mock_agentpools.MockAgentPoolScopeMockRecorder, nodelister *MockNodeListerMockRecorder)
56+
Verify func(g *WithT, result ctrl.Result, err error)
57+
}{
58+
{
59+
name: "Reconcile succeed",
60+
Setup: func(cb *fake.ClientBuilder, reconciler *mock_azure.MockReconcilerMockRecorder, agentpools *mock_agentpools.MockAgentPoolScopeMockRecorder, nodelister *MockNodeListerMockRecorder) {
61+
cluster, azManagedCluster, azManagedControlPlane, ammp, mp := newReadyAzureManagedMachinePoolCluster()
62+
fakeAgentPoolSpec := fakeAgentPool()
63+
providerIDs := []string{"azure:///subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroupname/providers/Microsoft.Compute/virtualMachineScaleSets/myScaleSetName/virtualMachines/156"}
64+
fakeVirtualMachineScaleSet := fakeVirtualMachineScaleSet()
65+
fakeVirtualMachineScaleSetVM := fakeVirtualMachineScaleSetVM()
66+
67+
reconciler.Reconcile(gomock2.AContext()).Return(nil)
68+
agentpools.AgentPoolSpec().Return(&fakeAgentPoolSpec)
69+
agentpools.NodeResourceGroup().Return("fake-rg")
70+
agentpools.SetAgentPoolProviderIDList(providerIDs)
71+
agentpools.SetAgentPoolReplicas(int32(len(providerIDs))).Return()
72+
agentpools.SetAgentPoolReady(true).Return()
73+
74+
nodelister.List(gomock2.AContext(), "fake-rg").Return(fakeVirtualMachineScaleSet, nil)
75+
nodelister.ListInstances(gomock2.AContext(), "fake-rg", "vmssName").Return(fakeVirtualMachineScaleSetVM, nil)
76+
77+
cb.WithObjects(cluster, azManagedCluster, azManagedControlPlane, ammp, mp)
78+
},
79+
Verify: func(g *WithT, result ctrl.Result, err error) {
80+
g.Expect(err).NotTo(HaveOccurred())
81+
},
82+
},
83+
{
84+
name: "Reconcile delete",
85+
Setup: func(cb *fake.ClientBuilder, reconciler *mock_azure.MockReconcilerMockRecorder, _ *mock_agentpools.MockAgentPoolScopeMockRecorder, _ *MockNodeListerMockRecorder) {
86+
cluster, azManagedCluster, azManagedControlPlane, ammp, mp := newReadyAzureManagedMachinePoolCluster()
87+
reconciler.Delete(gomock2.AContext()).Return(nil)
88+
ammp.DeletionTimestamp = &metav1.Time{
89+
Time: time.Now(),
90+
}
91+
cb.WithObjects(cluster, azManagedCluster, azManagedControlPlane, ammp, mp)
92+
},
93+
Verify: func(g *WithT, result ctrl.Result, err error) {
94+
g.Expect(err).NotTo(HaveOccurred())
95+
},
96+
},
97+
}
98+
99+
for _, c := range cases {
100+
c := c
101+
t.Run(c.name, func(t *testing.T) {
102+
var (
103+
g = NewWithT(t)
104+
mockCtrl = gomock.NewController(t)
105+
reconciler = mock_azure.NewMockReconciler(mockCtrl)
106+
agentpools = mock_agentpools.NewMockAgentPoolScope(mockCtrl)
107+
nodelister = NewMockNodeLister(mockCtrl)
108+
scheme = func() *runtime.Scheme {
109+
s := runtime.NewScheme()
110+
for _, addTo := range []func(s *runtime.Scheme) error{
111+
scheme.AddToScheme,
112+
clusterv1.AddToScheme,
113+
expv1.AddToScheme,
114+
infrav1.AddToScheme,
115+
} {
116+
g.Expect(addTo(s)).To(Succeed())
117+
}
118+
119+
return s
120+
}()
121+
cb = fake.NewClientBuilder().WithScheme(scheme)
122+
)
123+
defer mockCtrl.Finish()
124+
125+
c.Setup(cb, reconciler.EXPECT(), agentpools.EXPECT(), nodelister.EXPECT())
126+
controller := NewAzureManagedMachinePoolReconciler(cb.Build(), nil, 30*time.Second, "foo")
127+
controller.createAzureManagedMachinePoolService = func(_ *scope.ManagedMachinePoolScope) (*azureManagedMachinePoolService, error) {
128+
return &azureManagedMachinePoolService{
129+
scope: agentpools,
130+
agentPoolsSvc: reconciler,
131+
scaleSetsSvc: nodelister,
132+
}, nil
133+
}
134+
res, err := controller.Reconcile(context.TODO(), ctrl.Request{
135+
NamespacedName: types.NamespacedName{
136+
Name: "foo-ammp",
137+
Namespace: "foobar",
138+
},
139+
})
140+
c.Verify(g, res, err)
141+
})
142+
}
143+
}
144+
145+
func newReadyAzureManagedMachinePoolCluster() (*clusterv1.Cluster, *infrav1.AzureManagedCluster, *infrav1.AzureManagedControlPlane, *infrav1.AzureManagedMachinePool, *expv1.MachinePool) {
146+
// AzureManagedCluster
147+
azManagedCluster := &infrav1.AzureManagedCluster{
148+
ObjectMeta: metav1.ObjectMeta{
149+
Name: "foo-azManagedCluster",
150+
Namespace: "foobar",
151+
OwnerReferences: []metav1.OwnerReference{
152+
{
153+
Name: "foo-cluster",
154+
Kind: "Cluster",
155+
APIVersion: "cluster.x-k8s.io/v1beta1",
156+
},
157+
},
158+
},
159+
Spec: infrav1.AzureManagedClusterSpec{
160+
ControlPlaneEndpoint: clusterv1.APIEndpoint{
161+
Host: "foo.bar",
162+
Port: 123,
163+
},
164+
},
165+
}
166+
// AzureManagedControlPlane
167+
azManagedControlPlane := &infrav1.AzureManagedControlPlane{
168+
ObjectMeta: metav1.ObjectMeta{
169+
Name: "foo-azManagedControlPlane",
170+
Namespace: "foobar",
171+
OwnerReferences: []metav1.OwnerReference{
172+
{
173+
Name: "foo-cluster",
174+
Kind: "Cluster",
175+
APIVersion: "cluster.x-k8s.io/v1beta1",
176+
},
177+
},
178+
},
179+
Spec: infrav1.AzureManagedControlPlaneSpec{
180+
ControlPlaneEndpoint: clusterv1.APIEndpoint{
181+
Host: "foo.bar",
182+
Port: 123,
183+
},
184+
},
185+
Status: infrav1.AzureManagedControlPlaneStatus{
186+
Ready: true,
187+
Initialized: true,
188+
},
189+
}
190+
// Cluster
191+
cluster := &clusterv1.Cluster{
192+
ObjectMeta: metav1.ObjectMeta{
193+
Name: "foo-cluster",
194+
Namespace: "foobar",
195+
},
196+
Spec: clusterv1.ClusterSpec{
197+
ControlPlaneRef: &corev1.ObjectReference{
198+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
199+
Kind: "AzureManagedControlPlane",
200+
Name: azManagedControlPlane.Name,
201+
Namespace: azManagedControlPlane.Namespace,
202+
},
203+
InfrastructureRef: &corev1.ObjectReference{
204+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
205+
Kind: "AzureManagedCluster",
206+
Name: azManagedCluster.Name,
207+
Namespace: azManagedCluster.Namespace,
208+
},
209+
},
210+
}
211+
// AzureManagedMachinePool
212+
ammp := &infrav1.AzureManagedMachinePool{
213+
ObjectMeta: metav1.ObjectMeta{
214+
Name: "foo-ammp",
215+
Namespace: "foobar",
216+
OwnerReferences: []metav1.OwnerReference{
217+
{
218+
Name: "foo-mp1",
219+
Kind: "MachinePool",
220+
APIVersion: "cluster.x-k8s.io/v1beta1",
221+
},
222+
},
223+
},
224+
}
225+
// MachinePool
226+
mp := &expv1.MachinePool{
227+
ObjectMeta: metav1.ObjectMeta{
228+
Name: "foo-mp1",
229+
Namespace: "foobar",
230+
Labels: map[string]string{
231+
"cluster.x-k8s.io/cluster-name": cluster.Name,
232+
},
233+
OwnerReferences: []metav1.OwnerReference{
234+
{
235+
APIVersion: "cluster.x-k8s.io/v1beta1",
236+
Kind: "Cluster",
237+
Name: "foo-cluster",
238+
},
239+
},
240+
},
241+
Spec: expv1.MachinePoolSpec{
242+
Template: clusterv1.MachineTemplateSpec{
243+
Spec: clusterv1.MachineSpec{
244+
ClusterName: cluster.Name,
245+
InfrastructureRef: corev1.ObjectReference{
246+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
247+
Kind: "AzureManagedMachinePool",
248+
Name: ammp.Name,
249+
Namespace: ammp.Namespace,
250+
},
251+
},
252+
},
253+
},
254+
}
255+
256+
return cluster, azManagedCluster, azManagedControlPlane, ammp, mp
257+
}
258+
259+
func fakeAgentPool(changes ...func(*agentpools.AgentPoolSpec)) agentpools.AgentPoolSpec {
260+
pool := agentpools.AgentPoolSpec{
261+
Name: "fake-agent-pool-name",
262+
ResourceGroup: "fake-rg",
263+
Cluster: "fake-cluster",
264+
AvailabilityZones: []string{"fake-zone"},
265+
EnableAutoScaling: pointer.Bool(true),
266+
EnableUltraSSD: pointer.Bool(true),
267+
KubeletDiskType: (*infrav1.KubeletDiskType)(pointer.String("fake-kubelet-disk-type")),
268+
MaxCount: pointer.Int32(5),
269+
MaxPods: pointer.Int32(10),
270+
MinCount: pointer.Int32(1),
271+
Mode: "fake-mode",
272+
NodeLabels: map[string]*string{"fake-label": pointer.String("fake-value")},
273+
NodeTaints: []string{"fake-taint"},
274+
OSDiskSizeGB: 2,
275+
OsDiskType: pointer.String("fake-os-disk-type"),
276+
OSType: pointer.String("fake-os-type"),
277+
Replicas: 1,
278+
SKU: "fake-sku",
279+
Version: pointer.String("fake-version"),
280+
VnetSubnetID: "fake-vnet-subnet-id",
281+
Headers: map[string]string{"fake-header": "fake-value"},
282+
AdditionalTags: infrav1.Tags{"fake": "tag"},
283+
}
284+
285+
for _, change := range changes {
286+
change(&pool)
287+
}
288+
289+
return pool
290+
}
291+
292+
func fakeVirtualMachineScaleSetVM() []compute.VirtualMachineScaleSetVM {
293+
virtualMachineScaleSetVM := []compute.VirtualMachineScaleSetVM{
294+
{
295+
InstanceID: pointer.String("0"),
296+
ID: pointer.String("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupName/providers/Microsoft.Compute/virtualMachineScaleSets/myScaleSetName/virtualMachines/156"),
297+
Name: pointer.String("vm0"),
298+
Zones: &[]string{"zone0"},
299+
VirtualMachineScaleSetVMProperties: &compute.VirtualMachineScaleSetVMProperties{
300+
ProvisioningState: pointer.String(string(compute.ProvisioningState1Succeeded)),
301+
OsProfile: &compute.OSProfile{
302+
ComputerName: pointer.String("instance-000000"),
303+
},
304+
},
305+
},
306+
}
307+
return virtualMachineScaleSetVM
308+
}
309+
310+
func fakeVirtualMachineScaleSet() []compute.VirtualMachineScaleSet {
311+
tags := map[string]*string{
312+
"foo": pointer.String("bazz"),
313+
"poolName": pointer.String("fake-agent-pool-name"),
314+
}
315+
zones := []string{"zone0", "zone1"}
316+
virtualMachineScaleSet := []compute.VirtualMachineScaleSet{
317+
{
318+
Sku: &compute.Sku{
319+
Name: pointer.String("skuName"),
320+
Tier: pointer.String("skuTier"),
321+
Capacity: pointer.Int64(2),
322+
},
323+
Zones: &zones,
324+
ID: pointer.String("vmssID"),
325+
Name: pointer.String("vmssName"),
326+
Location: pointer.String("westus2"),
327+
Tags: tags,
328+
VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{
329+
SinglePlacementGroup: pointer.Bool(false),
330+
ProvisioningState: pointer.String(string(compute.ProvisioningState1Succeeded)),
331+
},
332+
},
333+
}
334+
return virtualMachineScaleSet
335+
}

0 commit comments

Comments
 (0)