Skip to content

Commit 07d47dc

Browse files
authored
Merge pull request #363 from nader-ziada/subnets
add unit tests for subnets in the cloud services package
2 parents 152c0e1 + d49de06 commit 07d47dc

File tree

1 file changed

+283
-0
lines changed

1 file changed

+283
-0
lines changed
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
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 subnets
18+
19+
import (
20+
"context"
21+
"net/http"
22+
"testing"
23+
24+
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network"
25+
"github.com/Azure/go-autorest/autorest"
26+
"github.com/Azure/go-autorest/autorest/to"
27+
"github.com/golang/mock/gomock"
28+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1alpha2"
30+
"sigs.k8s.io/cluster-api-provider-azure/cloud/scope"
31+
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/routetables/mock_routetables"
32+
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/securitygroups/mock_securitygroups"
33+
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/subnets/mock_subnets"
34+
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha2"
35+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
36+
)
37+
38+
func TestReconcileSubnets(t *testing.T) {
39+
testcases := []struct {
40+
name string
41+
subnetSpec Spec
42+
vnetSpec *infrav1.VnetSpec
43+
subnets []*infrav1.SubnetSpec
44+
expectedError string
45+
expect func(m *mock_subnets.MockClientMockRecorder, m1 *mock_routetables.MockClientMockRecorder, m2 *mock_securitygroups.MockClientMockRecorder)
46+
}{
47+
{
48+
name: "subnet does not exist",
49+
subnetSpec: Spec{
50+
Name: "my-subnet",
51+
CIDR: "10.0.0.0/16",
52+
VnetName: "my-vnet",
53+
RouteTableName: "my-subent_route_table",
54+
SecurityGroupName: "my-sg",
55+
Role: infrav1.SubnetNode,
56+
InternalLBIPAddress: "10.0.0.10",
57+
},
58+
vnetSpec: &infrav1.VnetSpec{Name: "my-vnet"},
59+
subnets: []*infrav1.SubnetSpec{},
60+
expectedError: "",
61+
expect: func(m *mock_subnets.MockClientMockRecorder, m1 *mock_routetables.MockClientMockRecorder, m2 *mock_securitygroups.MockClientMockRecorder) {
62+
m.Get(context.TODO(), "", "my-vnet", "my-subnet").
63+
Return(network.Subnet{}, autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: 404}, "Not found"))
64+
65+
m1.Get(context.TODO(), "my-rg", "my-subent_route_table").
66+
Return(network.RouteTable{}, nil)
67+
68+
m2.Get(context.TODO(), "my-rg", "my-sg").
69+
Return(network.SecurityGroup{}, nil)
70+
71+
m.CreateOrUpdate(context.TODO(), "", "my-vnet", "my-subnet", gomock.AssignableToTypeOf(network.Subnet{}))
72+
},
73+
},
74+
{
75+
name: "vnet was provided but subnet is missing",
76+
subnetSpec: Spec{
77+
Name: "my-subnet",
78+
CIDR: "10.0.0.0/16",
79+
VnetName: "custom-vnet",
80+
RouteTableName: "my-subent_route_table",
81+
SecurityGroupName: "my-sg",
82+
Role: infrav1.SubnetNode,
83+
InternalLBIPAddress: "10.0.0.10",
84+
},
85+
vnetSpec: &infrav1.VnetSpec{ResourceGroup: "custom-vnet-rg", Name: "custom-vnet", ID: "id1"},
86+
subnets: []*infrav1.SubnetSpec{},
87+
expectedError: "vnet was provided but subnet my-subnet is missing",
88+
expect: func(m *mock_subnets.MockClientMockRecorder, m1 *mock_routetables.MockClientMockRecorder, m2 *mock_securitygroups.MockClientMockRecorder) {
89+
m.Get(context.TODO(), "custom-vnet-rg", "custom-vnet", "my-subnet").
90+
Return(network.Subnet{}, autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: 404}, "Not found"))
91+
},
92+
},
93+
{
94+
name: "vnet was provided and subnet exists",
95+
subnetSpec: Spec{
96+
Name: "my-subnet",
97+
CIDR: "10.0.0.0/16",
98+
VnetName: "my-vnet",
99+
RouteTableName: "my-subent_route_table",
100+
SecurityGroupName: "my-sg",
101+
Role: infrav1.SubnetNode,
102+
InternalLBIPAddress: "10.0.0.10",
103+
},
104+
vnetSpec: &infrav1.VnetSpec{Name: "my-vnet"},
105+
subnets: []*infrav1.SubnetSpec{{
106+
Name: "my-subnet",
107+
Role: infrav1.SubnetNode,
108+
}},
109+
expectedError: "",
110+
expect: func(m *mock_subnets.MockClientMockRecorder, m1 *mock_routetables.MockClientMockRecorder, m2 *mock_securitygroups.MockClientMockRecorder) {
111+
m.Get(context.TODO(), "", "my-vnet", "my-subnet").
112+
Return(network.Subnet{
113+
ID: to.StringPtr("subnet-id"),
114+
Name: to.StringPtr("my-subnet"),
115+
SubnetPropertiesFormat: &network.SubnetPropertiesFormat{
116+
AddressPrefix: to.StringPtr("10.0.0.0/16"),
117+
RouteTable: &network.RouteTable{
118+
ID: to.StringPtr("rt-id"),
119+
Name: to.StringPtr("my-subent_route_table"),
120+
},
121+
NetworkSecurityGroup: &network.SecurityGroup{
122+
ID: to.StringPtr("sg-id"),
123+
Name: to.StringPtr("my-sg"),
124+
},
125+
},
126+
}, nil)
127+
},
128+
},
129+
}
130+
131+
for _, tc := range testcases {
132+
t.Run(tc.name, func(t *testing.T) {
133+
mockCtrl := gomock.NewController(t)
134+
subnetMock := mock_subnets.NewMockClient(mockCtrl)
135+
rtMock := mock_routetables.NewMockClient(mockCtrl)
136+
sgMock := mock_securitygroups.NewMockClient(mockCtrl)
137+
138+
cluster := &clusterv1.Cluster{
139+
ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"},
140+
}
141+
142+
client := fake.NewFakeClient(cluster)
143+
144+
tc.expect(subnetMock.EXPECT(), rtMock.EXPECT(), sgMock.EXPECT())
145+
146+
clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{
147+
AzureClients: scope.AzureClients{
148+
SubscriptionID: "123",
149+
Authorizer: autorest.NullAuthorizer{},
150+
},
151+
Client: client,
152+
Cluster: cluster,
153+
AzureCluster: &infrav1.AzureCluster{
154+
Spec: infrav1.AzureClusterSpec{
155+
Location: "test-location",
156+
ResourceGroup: "my-rg",
157+
NetworkSpec: infrav1.NetworkSpec{
158+
Vnet: *tc.vnetSpec,
159+
Subnets: tc.subnets,
160+
},
161+
},
162+
},
163+
})
164+
if err != nil {
165+
t.Fatalf("Failed to create test context: %v", err)
166+
}
167+
168+
s := &Service{
169+
Scope: clusterScope,
170+
Client: subnetMock,
171+
SecurityGroupsClient: sgMock,
172+
RouteTablesClient: rtMock,
173+
}
174+
175+
if err := s.Reconcile(context.TODO(), &tc.subnetSpec); err != nil {
176+
if tc.expectedError != "" && err.Error() != tc.expectedError {
177+
t.Fatalf("got an unexpected error: %v", err)
178+
}
179+
}
180+
})
181+
}
182+
}
183+
184+
func TestDeleteSubnets(t *testing.T) {
185+
testcases := []struct {
186+
name string
187+
subnetSpec Spec
188+
vnetSpec *infrav1.VnetSpec
189+
expect func(m *mock_subnets.MockClientMockRecorder)
190+
}{
191+
{
192+
name: "subnet exists",
193+
subnetSpec: Spec{
194+
Name: "my-subnet",
195+
CIDR: "10.0.0.0/16",
196+
VnetName: "my-vnet",
197+
RouteTableName: "my-subent_route_table",
198+
SecurityGroupName: "my-sg",
199+
Role: infrav1.SubnetNode,
200+
InternalLBIPAddress: "10.0.0.10",
201+
},
202+
vnetSpec: &infrav1.VnetSpec{Name: "my-vnet"},
203+
expect: func(m *mock_subnets.MockClientMockRecorder) {
204+
m.Delete(context.TODO(), "", "my-vnet", "my-subnet")
205+
},
206+
},
207+
{
208+
name: "subnet already deleted",
209+
subnetSpec: Spec{
210+
Name: "my-subnet",
211+
CIDR: "10.0.0.0/16",
212+
VnetName: "my-vnet",
213+
RouteTableName: "my-subent_route_table",
214+
SecurityGroupName: "my-sg",
215+
Role: infrav1.SubnetNode,
216+
InternalLBIPAddress: "10.0.0.10",
217+
},
218+
vnetSpec: &infrav1.VnetSpec{Name: "my-vnet"},
219+
expect: func(m *mock_subnets.MockClientMockRecorder) {
220+
m.Delete(context.TODO(), "", "my-vnet", "my-subnet").
221+
Return(autorest.NewErrorWithResponse("", "my-vnet", &http.Response{StatusCode: 404}, "Not found"))
222+
},
223+
},
224+
{
225+
name: "skip delete if vnet is managed",
226+
subnetSpec: Spec{
227+
Name: "my-subnet",
228+
CIDR: "10.0.0.0/16",
229+
VnetName: "custom-vnet",
230+
RouteTableName: "my-subent_route_table",
231+
SecurityGroupName: "my-sg",
232+
Role: infrav1.SubnetNode,
233+
InternalLBIPAddress: "10.0.0.10",
234+
},
235+
vnetSpec: &infrav1.VnetSpec{ResourceGroup: "custom-vnet-rg", Name: "custom-vnet", ID: "id1"},
236+
expect: func(m *mock_subnets.MockClientMockRecorder) {},
237+
},
238+
}
239+
for _, tc := range testcases {
240+
t.Run(tc.name, func(t *testing.T) {
241+
mockCtrl := gomock.NewController(t)
242+
subnetMock := mock_subnets.NewMockClient(mockCtrl)
243+
244+
cluster := &clusterv1.Cluster{
245+
ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"},
246+
}
247+
248+
client := fake.NewFakeClient(cluster)
249+
250+
tc.expect(subnetMock.EXPECT())
251+
252+
clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{
253+
AzureClients: scope.AzureClients{
254+
SubscriptionID: "123",
255+
Authorizer: autorest.NullAuthorizer{},
256+
},
257+
Client: client,
258+
Cluster: cluster,
259+
AzureCluster: &infrav1.AzureCluster{
260+
Spec: infrav1.AzureClusterSpec{
261+
Location: "test-location",
262+
ResourceGroup: "my-rg",
263+
NetworkSpec: infrav1.NetworkSpec{
264+
Vnet: *tc.vnetSpec,
265+
},
266+
},
267+
},
268+
})
269+
if err != nil {
270+
t.Fatalf("Failed to create test context: %v", err)
271+
}
272+
273+
s := &Service{
274+
Scope: clusterScope,
275+
Client: subnetMock,
276+
}
277+
278+
if err := s.Delete(context.TODO(), &tc.subnetSpec); err != nil {
279+
t.Fatalf("got an unexpected error: %v", err)
280+
}
281+
})
282+
}
283+
}

0 commit comments

Comments
 (0)