@@ -172,6 +172,10 @@ func TestReconcileInboundNATRule(t *testing.T) {
172172 Name : "my-machine-nat-rule" ,
173173 LoadBalancerName : "my-public-lb" ,
174174 },
175+ {
176+ Name : "my-other-nat-rule" ,
177+ LoadBalancerName : "my-other-public-lb" ,
178+ },
175179 })
176180 s .ResourceGroup ().AnyTimes ().Return ("my-rg" )
177181 s .Location ().AnyTimes ().Return ("fake-location" )
@@ -202,7 +206,19 @@ func TestReconcileInboundNATRule(t *testing.T) {
202206 },
203207 },
204208 },
205- }}, nil ))
209+ }}, nil ),
210+ mLoadBalancer .Get (context .TODO (), "my-rg" , "my-other-public-lb" ).Return (network.LoadBalancer {
211+ Name : to .StringPtr ("my-other-public-lb" ),
212+ ID : pointer .StringPtr ("my-public-lb-id" ),
213+ LoadBalancerPropertiesFormat : & network.LoadBalancerPropertiesFormat {
214+ FrontendIPConfigurations : & []network.FrontendIPConfiguration {
215+ {
216+ ID : to .StringPtr ("frontend-ip-config-id" ),
217+ },
218+ },
219+ InboundNatRules : & []network.InboundNatRule {},
220+ }}, nil ),
221+ m .CreateOrUpdate (context .TODO (), "my-rg" , "my-other-public-lb" , "my-other-nat-rule" , gomock .AssignableToTypeOf (network.InboundNatRule {})))
206222 },
207223 },
208224 }
@@ -325,3 +341,201 @@ func TestDeleteNetworkInterface(t *testing.T) {
325341 })
326342 }
327343}
344+
345+ func TestNatRuleExists (t * testing.T ) {
346+ testcases := []struct {
347+ name string
348+ ruleName string
349+ existingRules []network.InboundNatRule
350+ expectedResult bool
351+ expectedPorts map [int32 ]struct {}
352+ expect func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
353+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder )
354+ }{
355+ {
356+ name : "Rule exists" ,
357+ ruleName : "my-rule" ,
358+ existingRules : []network.InboundNatRule {
359+ {
360+ InboundNatRulePropertiesFormat : & network.InboundNatRulePropertiesFormat {
361+ FrontendPort : to .Int32Ptr (2201 ),
362+ },
363+ Name : to .StringPtr ("some-rule" ),
364+ },
365+ {
366+ InboundNatRulePropertiesFormat : & network.InboundNatRulePropertiesFormat {
367+ FrontendPort : to .Int32Ptr (22 ),
368+ },
369+ Name : to .StringPtr ("my-rule" ),
370+ },
371+ },
372+ expectedResult : true ,
373+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
374+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
375+ s .V (gomock .AssignableToTypeOf (2 )).Return (klogr .New ())
376+ },
377+ },
378+ {
379+ name : "Rule doesn't exist" ,
380+ ruleName : "my-rule" ,
381+ existingRules : []network.InboundNatRule {
382+ {
383+ InboundNatRulePropertiesFormat : & network.InboundNatRulePropertiesFormat {
384+ FrontendPort : to .Int32Ptr (22 ),
385+ },
386+ Name : to .StringPtr ("other-rule" ),
387+ },
388+ {
389+ InboundNatRulePropertiesFormat : & network.InboundNatRulePropertiesFormat {
390+ FrontendPort : to .Int32Ptr (2205 ),
391+ },
392+ Name : to .StringPtr ("other-rule-2" ),
393+ },
394+ },
395+ expectedResult : false ,
396+ expectedPorts : map [int32 ]struct {}{
397+ 22 : {},
398+ 2205 : {},
399+ },
400+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
401+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
402+ },
403+ },
404+ {
405+ name : "No rules exist" ,
406+ ruleName : "my-rule" ,
407+ existingRules : []network.InboundNatRule {},
408+ expectedResult : false ,
409+ expectedPorts : map [int32 ]struct {}{},
410+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
411+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
412+ },
413+ },
414+ }
415+
416+ for _ , tc := range testcases {
417+ tc := tc
418+ t .Run (tc .name , func (t * testing.T ) {
419+ g := NewWithT (t )
420+ t .Parallel ()
421+ mockCtrl := gomock .NewController (t )
422+ defer mockCtrl .Finish ()
423+ scopeMock := mock_inboundnatrules .NewMockInboundNatScope (mockCtrl )
424+ clientMock := mock_inboundnatrules .NewMockClient (mockCtrl )
425+ loadBalancerMock := mock_loadbalancers .NewMockClient (mockCtrl )
426+
427+ tc .expect (scopeMock .EXPECT (), clientMock .EXPECT (), loadBalancerMock .EXPECT ())
428+
429+ s := & Service {
430+ Scope : scopeMock ,
431+ Client : clientMock ,
432+ LoadBalancersClient : loadBalancerMock ,
433+ }
434+
435+ ports := make (map [int32 ]struct {})
436+ exists := s .natRuleExists (ports )(tc .existingRules , tc .ruleName )
437+ g .Expect (exists ).To (Equal (tc .expectedResult ))
438+ if ! exists {
439+ g .Expect (ports ).To (Equal (tc .expectedPorts ))
440+ }
441+ })
442+ }
443+ }
444+
445+ func TestGetAvailablePort (t * testing.T ) {
446+ testcases := []struct {
447+ name string
448+ portsInput map [int32 ]struct {}
449+ expectedError string
450+ expectedPortResult int32
451+ expect func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
452+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder )
453+ }{
454+ {
455+ name : "Empty ports" ,
456+ portsInput : map [int32 ]struct {}{},
457+ expectedError : "" ,
458+ expectedPortResult : 22 ,
459+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
460+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
461+ s .V (gomock .AssignableToTypeOf (2 )).Return (klogr .New ())
462+ },
463+ },
464+ {
465+ name : "22 taken" ,
466+ portsInput : map [int32 ]struct {}{
467+ 22 : {},
468+ },
469+ expectedError : "" ,
470+ expectedPortResult : 2201 ,
471+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
472+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
473+ s .V (gomock .AssignableToTypeOf (2 )).Return (klogr .New ())
474+ },
475+ },
476+ {
477+ name : "Existing ports" ,
478+ portsInput : map [int32 ]struct {}{
479+ 22 : {},
480+ 2201 : {},
481+ 2202 : {},
482+ 2204 : {},
483+ },
484+ expectedError : "" ,
485+ expectedPortResult : 2203 ,
486+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
487+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
488+ s .V (gomock .AssignableToTypeOf (2 )).Return (klogr .New ())
489+ },
490+ },
491+ {
492+ name : "No ports available" ,
493+ portsInput : getFullPortsMap (),
494+ expectedError : "No available SSH Frontend ports" ,
495+ expectedPortResult : 0 ,
496+ expect : func (s * mock_inboundnatrules.MockInboundNatScopeMockRecorder ,
497+ m * mock_inboundnatrules.MockClientMockRecorder , mLoadBalancer * mock_loadbalancers.MockClientMockRecorder ) {
498+ },
499+ },
500+ }
501+
502+ for _ , tc := range testcases {
503+ tc := tc
504+ t .Run (tc .name , func (t * testing.T ) {
505+ g := NewWithT (t )
506+ t .Parallel ()
507+ mockCtrl := gomock .NewController (t )
508+ defer mockCtrl .Finish ()
509+ scopeMock := mock_inboundnatrules .NewMockInboundNatScope (mockCtrl )
510+ clientMock := mock_inboundnatrules .NewMockClient (mockCtrl )
511+ loadBalancerMock := mock_loadbalancers .NewMockClient (mockCtrl )
512+
513+ tc .expect (scopeMock .EXPECT (), clientMock .EXPECT (), loadBalancerMock .EXPECT ())
514+
515+ s := & Service {
516+ Scope : scopeMock ,
517+ Client : clientMock ,
518+ LoadBalancersClient : loadBalancerMock ,
519+ }
520+
521+ res , err := s .getAvailablePort (tc .portsInput )
522+ if tc .expectedError != "" {
523+ g .Expect (err ).To (HaveOccurred ())
524+ g .Expect (err ).To (MatchError (tc .expectedError ))
525+ } else {
526+ g .Expect (err ).NotTo (HaveOccurred ())
527+ g .Expect (res ).To (Equal (tc .expectedPortResult ))
528+ }
529+ })
530+ }
531+ }
532+
533+ func getFullPortsMap () map [int32 ]struct {} {
534+ res := map [int32 ]struct {}{
535+ 22 : {},
536+ }
537+ for i := 2201 ; i < 2220 ; i ++ {
538+ res [int32 (i )] = struct {}{}
539+ }
540+ return res
541+ }
0 commit comments