sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/inboundnatrules/spec_test.go (about) 1 /* 2 Copyright 2021 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 inboundnatrules 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 23 24 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4" 25 "github.com/google/go-cmp/cmp" 26 . "github.com/onsi/gomega" 27 "k8s.io/utils/ptr" 28 ) 29 30 func TestParameters(t *testing.T) { 31 testcases := []struct { 32 name string 33 spec InboundNatSpec 34 existing interface{} 35 expected interface{} 36 errorMsg string 37 }{ 38 { 39 name: "no existing InboundNatRule", 40 spec: fakeInboundNatSpec(true), 41 existing: nil, 42 expected: fakeNatRule(), 43 }, 44 { 45 name: "no existing InboundNatRule and FrontendIPConfigurationID not set", 46 spec: fakeInboundNatSpec(false), 47 existing: nil, 48 errorMsg: "FrontendIPConfigurationID is not set", 49 }, 50 { 51 name: "existing is not an InboundNatRule", 52 spec: fakeInboundNatSpec(true), 53 existing: "wrong type", 54 errorMsg: "string is not an armnetwork.InboundNatRule", 55 }, 56 { 57 name: "existing InboundNatRule", 58 spec: fakeInboundNatSpec(false), 59 existing: fakeNatRule(), 60 expected: nil, 61 }, 62 } 63 for _, tc := range testcases { 64 tc := tc 65 t.Run(tc.name, func(t *testing.T) { 66 g := NewWithT(t) 67 t.Parallel() 68 69 result, err := tc.spec.Parameters(context.Background(), tc.existing) 70 if tc.errorMsg != "" { 71 g.Expect(err).To(HaveOccurred()) 72 g.Expect(err.Error()).To(ContainSubstring(tc.errorMsg)) 73 } else { 74 g.Expect(err).NotTo(HaveOccurred()) 75 } 76 if !reflect.DeepEqual(result, tc.expected) { 77 t.Errorf("Got difference between expected result and computed result:\n%s", cmp.Diff(tc.expected, result)) 78 } 79 }) 80 } 81 } 82 83 func fakeInboundNatSpec(frontendIPConfigID bool) InboundNatSpec { 84 spec := InboundNatSpec{ 85 Name: "my-machine-1", 86 LoadBalancerName: "my-lb-1", 87 ResourceGroup: fakeGroupName, 88 } 89 if frontendIPConfigID { 90 spec.FrontendIPConfigurationID = ptr.To("frontend-ip-config-id-1") 91 } 92 return spec 93 } 94 95 // fakeNatRule returns a fake InboundNatRule, associated with `fakeInboundNatSpec()`. 96 func fakeNatRule() armnetwork.InboundNatRule { 97 return armnetwork.InboundNatRule{ 98 Name: ptr.To("my-machine-1"), 99 Properties: &armnetwork.InboundNatRulePropertiesFormat{ 100 BackendPort: ptr.To[int32](22), 101 EnableFloatingIP: ptr.To(false), 102 FrontendIPConfiguration: &armnetwork.SubResource{ 103 ID: ptr.To("frontend-ip-config-id-1"), 104 }, 105 IdleTimeoutInMinutes: ptr.To[int32](4), 106 Protocol: ptr.To(armnetwork.TransportProtocolTCP), 107 }, 108 } 109 } 110 111 func TestGetAvailablePort(t *testing.T) { 112 testcases := []struct { 113 name string 114 portsInput map[int32]struct{} 115 expectedError string 116 expectedPortResult int32 117 }{ 118 { 119 name: "Empty ports", 120 portsInput: map[int32]struct{}{}, 121 expectedError: "", 122 expectedPortResult: 22, 123 }, 124 { 125 name: "22 taken", 126 portsInput: map[int32]struct{}{ 127 22: {}, 128 }, 129 expectedError: "", 130 expectedPortResult: 2201, 131 }, 132 { 133 name: "Existing ports", 134 portsInput: map[int32]struct{}{ 135 22: {}, 136 2201: {}, 137 2202: {}, 138 2204: {}, 139 }, 140 expectedError: "", 141 expectedPortResult: 2203, 142 }, 143 { 144 name: "No ports available", 145 portsInput: getFullPortsMap(), 146 expectedError: "No available SSH Frontend ports", 147 expectedPortResult: 0, 148 }, 149 } 150 for _, tc := range testcases { 151 tc := tc 152 t.Run(tc.name, func(t *testing.T) { 153 g := NewWithT(t) 154 t.Parallel() 155 156 res, err := getAvailableSSHFrontendPort(tc.portsInput) 157 if tc.expectedError != "" { 158 g.Expect(err).To(HaveOccurred()) 159 g.Expect(err).To(MatchError(tc.expectedError)) 160 } else { 161 g.Expect(err).NotTo(HaveOccurred()) 162 g.Expect(res).To(Equal(tc.expectedPortResult)) 163 } 164 }) 165 } 166 } 167 168 func getFullPortsMap() map[int32]struct{} { 169 res := map[int32]struct{}{ 170 22: {}, 171 } 172 for i := 2201; i < 2220; i++ { 173 res[int32(i)] = struct{}{} 174 } 175 return res 176 }