@@ -19,9 +19,16 @@ package compute
19
19
import (
20
20
"testing"
21
21
22
+ "github.com/go-logr/logr"
23
+ "github.com/golang/mock/gomock"
24
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
25
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
26
+ . "github.com/onsi/gomega"
22
27
"k8s.io/utils/pointer"
23
28
24
29
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha4"
30
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
31
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking/mock_networking"
25
32
)
26
33
27
34
func Test_getPortName (t * testing.T ) {
@@ -64,3 +71,359 @@ func Test_getPortName(t *testing.T) {
64
71
})
65
72
}
66
73
}
74
+
75
+ func TestService_getServerNetworks (t * testing.T ) {
76
+ const testClusterTag = "cluster=mycluster"
77
+
78
+ // Network A:
79
+ // Network is tagged
80
+ // Has 3 subnets
81
+ // Subnets A1 and A2 are tagged
82
+ // Subnet A3 is not tagged
83
+ // Network B:
84
+ // Network is tagged
85
+ // Has 1 subnet, B1, which is also tagged
86
+ // Network C:
87
+ // Network is not tagged
88
+ // Has 1 subnet, C1, which is also not tagged
89
+
90
+ networkAUUID := "7f0a7cc9-d7c8-41d2-87a2-2fc7f5ec544e"
91
+ networkBUUID := "607559d9-a5a4-4a0b-a92d-75eba89e3343"
92
+ networkCUUID := "9d7b0284-b22e-4bc7-b90e-28a652cac7cc"
93
+ subnetA1UUID := "869f6790-17a9-44d5-83a1-89e180514515"
94
+ subnetA2UUID := "bd926900-5277-47a5-bd71-c6f713165dbd"
95
+ subnetA3UUID := "79dfde1b-07f1-48a0-97fd-07e2f6018c46"
96
+ subnetB1UUID := "efc2cc7d-c6e0-45c6-8147-0e08b8530664"
97
+ subnetC1UUID := "b33271f4-6bb1-430a-88bf-789394815aaf"
98
+
99
+ testNetworkA := networks.Network {
100
+ ID : networkAUUID ,
101
+ Name : "network-a" ,
102
+ Subnets : []string {subnetA1UUID , subnetA2UUID },
103
+ Tags : []string {testClusterTag },
104
+ }
105
+ testNetworkB := networks.Network {
106
+ ID : networkBUUID ,
107
+ Name : "network-b" ,
108
+ Subnets : []string {subnetB1UUID },
109
+ Tags : []string {testClusterTag },
110
+ }
111
+ testNetworkC := networks.Network {
112
+ ID : networkCUUID ,
113
+ Name : "network-c" ,
114
+ Subnets : []string {subnetC1UUID },
115
+ }
116
+
117
+ testSubnetA1 := subnets.Subnet {
118
+ ID : subnetA1UUID ,
119
+ Name : "subnet-a1" ,
120
+ NetworkID : networkAUUID ,
121
+ Tags : []string {testClusterTag },
122
+ }
123
+ testSubnetA2 := subnets.Subnet {
124
+ ID : subnetA2UUID ,
125
+ Name : "subnet-a2" ,
126
+ NetworkID : networkAUUID ,
127
+ Tags : []string {testClusterTag },
128
+ }
129
+ testSubnetA3 := subnets.Subnet {
130
+ ID : subnetA3UUID ,
131
+ Name : "subnet-a3" ,
132
+ NetworkID : networkAUUID ,
133
+ }
134
+ testSubnetB1 := subnets.Subnet {
135
+ ID : subnetB1UUID ,
136
+ Name : "subnet-b1" ,
137
+ NetworkID : networkBUUID ,
138
+ Tags : []string {testClusterTag },
139
+ }
140
+ testSubnetC1 := subnets.Subnet {
141
+ ID : subnetC1UUID ,
142
+ Name : "subnet-c1" ,
143
+ NetworkID : networkCUUID ,
144
+ }
145
+
146
+ // Define arbitrary test network and subnet filters for use in multiple tests,
147
+ // the gophercloud ListOpts they should translate to, and the arbitrary returned networks/subnets.
148
+ testNetworkFilter := infrav1.Filter {Tags : testClusterTag }
149
+ testNetworkListOpts := networks.ListOpts {Tags : testClusterTag }
150
+ testSubnetFilter := infrav1.SubnetFilter {Tags : testClusterTag }
151
+ testSubnetListOpts := subnets.ListOpts {Tags : testClusterTag }
152
+
153
+ // Expect a list query by network UUID which returns the network with the same UUID
154
+ expectNetworkListByUUID := func (m * mock_networking.MockNetworkClientMockRecorder , network * networks.Network ) {
155
+ m .ListNetwork (& networks.ListOpts {ID : network .ID }).
156
+ Return ([]networks.Network {* network }, nil )
157
+ }
158
+
159
+ // Expect a list query by subnet and network UUID which returns the subnet with the same UUID
160
+ expectSubnetListByUUID := func (m * mock_networking.MockNetworkClientMockRecorder , subnet * subnets.Subnet ) {
161
+ m .ListSubnet (& subnets.ListOpts {ID : subnet .ID , NetworkID : subnet .NetworkID }).
162
+ Return ([]subnets.Subnet {* subnet }, nil )
163
+ }
164
+
165
+ tests := []struct {
166
+ name string
167
+ networkParams []infrav1.NetworkParam
168
+ want []infrav1.Network
169
+ expect func (m * mock_networking.MockNetworkClientMockRecorder )
170
+ wantErr bool
171
+ }{
172
+ {
173
+ name : "Network UUID without subnet" ,
174
+ networkParams : []infrav1.NetworkParam {
175
+ {UUID : networkAUUID },
176
+ },
177
+ want : []infrav1.Network {
178
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {}},
179
+ },
180
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
181
+ expectNetworkListByUUID (m , & testNetworkA )
182
+ },
183
+ wantErr : false ,
184
+ },
185
+ {
186
+ name : "Network filter without subnet" ,
187
+ networkParams : []infrav1.NetworkParam {
188
+ {Filter : testNetworkFilter },
189
+ },
190
+ want : []infrav1.Network {
191
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {}},
192
+ {ID : networkBUUID , Subnet : & infrav1.Subnet {}},
193
+ },
194
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
195
+ // List tagged networks (A & B)
196
+ m .ListNetwork (& testNetworkListOpts ).
197
+ Return ([]networks.Network {testNetworkA , testNetworkB }, nil )
198
+ },
199
+ wantErr : false ,
200
+ },
201
+ {
202
+ name : "Subnet by filter without network" ,
203
+ networkParams : []infrav1.NetworkParam {
204
+ {
205
+ Subnets : []infrav1.SubnetParam {{Filter : testSubnetFilter }},
206
+ },
207
+ },
208
+ want : nil ,
209
+ /* We expect this to return all tagged subnets in any network, but it returns error
210
+
211
+ []infrav1.Network{
212
+ {ID: networkAUUID, Subnet: &infrav1.Subnet{ID: subnetA1UUID}},
213
+ {ID: networkAUUID, Subnet: &infrav1.Subnet{ID: subnetA2UUID}},
214
+ {ID: networkAUUID, Subnet: &infrav1.Subnet{ID: subnetB1UUID}},
215
+ },
216
+ */
217
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
218
+ // Empty list query returns all networks
219
+ m .ListNetwork (& networks.ListOpts {}).
220
+ Return ([]networks.Network {testNetworkA , testNetworkB , testNetworkC }, nil )
221
+
222
+ // List tagged subnets in network A (A1 & A2)
223
+ networkAFilter := testSubnetListOpts
224
+ networkAFilter .NetworkID = networkAUUID
225
+ m .ListSubnet (& networkAFilter ).
226
+ Return ([]subnets.Subnet {testSubnetA1 , testSubnetA2 }, nil )
227
+
228
+ // List tagged subnets in network B (B1)
229
+ networkBFilter := testSubnetListOpts
230
+ networkBFilter .NetworkID = networkBUUID
231
+ m .ListSubnet (& networkBFilter ).
232
+ Return ([]subnets.Subnet {testSubnetB1 }, nil )
233
+
234
+ // List tagged subnets in network C (none)
235
+ networkCFilter := testSubnetListOpts
236
+ networkCFilter .NetworkID = networkCUUID
237
+ m .ListSubnet (& networkCFilter ).
238
+ Return ([]subnets.Subnet {}, nil )
239
+ },
240
+ wantErr : true ,
241
+ },
242
+ {
243
+ name : "Network UUID and subnet filter" ,
244
+ networkParams : []infrav1.NetworkParam {
245
+ {
246
+ UUID : networkAUUID ,
247
+ Subnets : []infrav1.SubnetParam {
248
+ {Filter : testSubnetFilter },
249
+ },
250
+ },
251
+ },
252
+ want : []infrav1.Network {
253
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA1UUID }},
254
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA2UUID }},
255
+ },
256
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
257
+ // List network A by UUID
258
+ expectNetworkListByUUID (m , & testNetworkA )
259
+
260
+ // List tagged subnets in network A (A1 & A2)
261
+ networkAFilter := testSubnetListOpts
262
+ networkAFilter .NetworkID = networkAUUID
263
+ m .ListSubnet (& networkAFilter ).
264
+ Return ([]subnets.Subnet {testSubnetA1 , testSubnetA2 }, nil )
265
+ },
266
+ wantErr : false ,
267
+ },
268
+ {
269
+ name : "Network UUID and subnet UUID" ,
270
+ networkParams : []infrav1.NetworkParam {
271
+ {
272
+ UUID : networkAUUID ,
273
+ Subnets : []infrav1.SubnetParam {
274
+ {UUID : subnetA1UUID },
275
+ },
276
+ },
277
+ },
278
+ want : []infrav1.Network {
279
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA1UUID }},
280
+ },
281
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
282
+ // List network A by uuid
283
+ expectNetworkListByUUID (m , & testNetworkA )
284
+
285
+ // List subnet A1 by uuid
286
+ expectSubnetListByUUID (m , & testSubnetA1 )
287
+ },
288
+ wantErr : false ,
289
+ },
290
+ {
291
+ name : "Network UUID and multiple subnet params" ,
292
+ networkParams : []infrav1.NetworkParam {
293
+ {
294
+ UUID : networkAUUID ,
295
+ Subnets : []infrav1.SubnetParam {
296
+ {UUID : subnetA3UUID },
297
+ {Filter : testSubnetFilter },
298
+ },
299
+ },
300
+ },
301
+ want : []infrav1.Network {
302
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA3UUID }},
303
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA1UUID }},
304
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA2UUID }},
305
+ },
306
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
307
+ // List network A by uuid
308
+ expectNetworkListByUUID (m , & testNetworkA )
309
+
310
+ // List subnet A3 by uuid
311
+ expectSubnetListByUUID (m , & testSubnetA3 )
312
+
313
+ // List tagged subnets in network A
314
+ networkAFilter := testSubnetListOpts
315
+ networkAFilter .NetworkID = networkAUUID
316
+ m .ListSubnet (& networkAFilter ).
317
+ Return ([]subnets.Subnet {testSubnetA1 , testSubnetA2 }, nil )
318
+ },
319
+ wantErr : false ,
320
+ },
321
+ {
322
+ name : "Multiple network params" ,
323
+ networkParams : []infrav1.NetworkParam {
324
+ {
325
+ UUID : networkCUUID ,
326
+ Subnets : []infrav1.SubnetParam {
327
+ {UUID : subnetC1UUID },
328
+ },
329
+ },
330
+ {
331
+ Filter : testNetworkFilter ,
332
+ Subnets : []infrav1.SubnetParam {
333
+ {Filter : testSubnetFilter },
334
+ },
335
+ },
336
+ },
337
+ want : []infrav1.Network {
338
+ {ID : networkCUUID , Subnet : & infrav1.Subnet {ID : subnetC1UUID }},
339
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA1UUID }},
340
+ {ID : networkAUUID , Subnet : & infrav1.Subnet {ID : subnetA2UUID }},
341
+ {ID : networkBUUID , Subnet : & infrav1.Subnet {ID : subnetB1UUID }},
342
+ },
343
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
344
+ // List network C by uuid
345
+ expectNetworkListByUUID (m , & testNetworkC )
346
+
347
+ // List subnet C1 by uuid
348
+ expectSubnetListByUUID (m , & testSubnetC1 )
349
+
350
+ // List tagged networks (A & B)
351
+ m .ListNetwork (& testNetworkListOpts ).
352
+ Return ([]networks.Network {testNetworkA , testNetworkB }, nil )
353
+
354
+ // List tagged subnets in network A (A1 & A2)
355
+ networkAFilter := testSubnetListOpts
356
+ networkAFilter .NetworkID = networkAUUID
357
+ m .ListSubnet (& networkAFilter ).
358
+ Return ([]subnets.Subnet {testSubnetA1 , testSubnetA2 }, nil )
359
+
360
+ // List tagged subnets in network B (B1)
361
+ networkBFilter := testSubnetListOpts
362
+ networkBFilter .NetworkID = networkBUUID
363
+ m .ListSubnet (& networkBFilter ).
364
+ Return ([]subnets.Subnet {testSubnetB1 }, nil )
365
+ },
366
+ wantErr : false ,
367
+ },
368
+ {
369
+ // Expect an error if a network filter doesn't match any networks
370
+ name : "Network filter matches no networks" ,
371
+ networkParams : []infrav1.NetworkParam {
372
+ {Filter : testNetworkFilter },
373
+ },
374
+ want : nil ,
375
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
376
+ // List tagged networks (none for this test)
377
+ m .ListNetwork (& testNetworkListOpts ).Return ([]networks.Network {}, nil )
378
+ },
379
+ wantErr : true ,
380
+ },
381
+ {
382
+ // Expect an error if a subnet filter doesn't match any subnets
383
+ name : "Subnet filter matches no subnets" ,
384
+ networkParams : []infrav1.NetworkParam {
385
+ {
386
+ UUID : networkAUUID ,
387
+ Subnets : []infrav1.SubnetParam {
388
+ {Filter : testSubnetFilter },
389
+ },
390
+ },
391
+ },
392
+ want : nil ,
393
+ expect : func (m * mock_networking.MockNetworkClientMockRecorder ) {
394
+ // List network A by UUID
395
+ expectNetworkListByUUID (m , & testNetworkA )
396
+
397
+ // List tagged subnets in network A
398
+ networkAFilter := testSubnetListOpts
399
+ networkAFilter .NetworkID = networkAUUID
400
+ m .ListSubnet (& networkAFilter ).Return ([]subnets.Subnet {}, nil )
401
+ },
402
+ wantErr : true ,
403
+ },
404
+ }
405
+
406
+ for _ , tt := range tests {
407
+ t .Run (tt .name , func (t * testing.T ) {
408
+ mockCtrl := gomock .NewController (t )
409
+ mockNetworkClient := mock_networking .NewMockNetworkClient (mockCtrl )
410
+ tt .expect (mockNetworkClient .EXPECT ())
411
+
412
+ networkingService := networking .NewTestService (
413
+ "" , mockNetworkClient , logr .Discard (),
414
+ )
415
+ s := & Service {
416
+ networkingService : networkingService ,
417
+ }
418
+
419
+ got , err := s .getServerNetworks (tt .networkParams )
420
+ g := NewWithT (t )
421
+ if tt .wantErr {
422
+ g .Expect (err ).To (HaveOccurred ())
423
+ } else {
424
+ g .Expect (err ).NotTo (HaveOccurred ())
425
+ }
426
+ g .Expect (got ).To (Equal (tt .want ))
427
+ })
428
+ }
429
+ }
0 commit comments