sigs.k8s.io/cluster-api-provider-azure@v1.17.0/azure/services/networkinterfaces/networkinterfaces_test.go (about) 1 /* 2 Copyright 2020 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 networkinterfaces 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "net/http" 24 "strings" 25 "testing" 26 27 "github.com/Azure/azure-sdk-for-go/sdk/azcore" 28 "github.com/google/go-cmp/cmp" 29 . "github.com/onsi/gomega" 30 "go.uber.org/mock/gomock" 31 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 32 "sigs.k8s.io/cluster-api-provider-azure/azure" 33 "sigs.k8s.io/cluster-api-provider-azure/azure/services/async/mock_async" 34 "sigs.k8s.io/cluster-api-provider-azure/azure/services/networkinterfaces/mock_networkinterfaces" 35 gomockinternal "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock" 36 "sigs.k8s.io/cluster-api-provider-azure/util/reconciler" 37 ) 38 39 var ( 40 fakeNICSpec1 = NICSpec{ 41 Name: "nic-1", 42 ResourceGroup: "my-rg", 43 Location: "fake-location", 44 SubscriptionID: "123", 45 MachineName: "azure-test1", 46 SubnetName: "my-subnet", 47 VNetName: "my-vnet", 48 VNetResourceGroup: "my-rg", 49 AcceleratedNetworking: nil, 50 SKU: &fakeSku, 51 } 52 fakeNICSpec2 = NICSpec{ 53 Name: "nic-2", 54 ResourceGroup: "my-rg", 55 Location: "fake-location", 56 SubscriptionID: "123", 57 MachineName: "azure-test1", 58 SubnetName: "my-subnet", 59 VNetName: "my-vnet", 60 VNetResourceGroup: "my-rg", 61 AcceleratedNetworking: nil, 62 SKU: &fakeSku, 63 } 64 fakeNICSpec3 = NICSpec{ 65 Name: "nic-3", 66 ResourceGroup: "my-rg", 67 Location: "fake-location", 68 SubscriptionID: "123", 69 MachineName: "azure-test1", 70 VNetName: "my-vnet", 71 VNetResourceGroup: "my-rg", 72 AcceleratedNetworking: nil, 73 SKU: &fakeSku, 74 IPConfigs: []IPConfig{{}, {}}, 75 } 76 internalError = &azcore.ResponseError{ 77 RawResponse: &http.Response{ 78 Body: io.NopCloser(strings.NewReader("#: Internal Server Error: StatusCode=500")), 79 StatusCode: http.StatusInternalServerError, 80 }, 81 } 82 ) 83 84 func TestReconcileNetworkInterface(t *testing.T) { 85 testcases := []struct { 86 name string 87 expectedError string 88 expect func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) 89 }{ 90 { 91 name: "noop if no network interface specs are found", 92 expectedError: "", 93 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 94 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 95 s.NICSpecs().Return([]azure.ResourceSpecGetter{}) 96 }, 97 }, 98 { 99 name: "successfully create a network interface", 100 expectedError: "", 101 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 102 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 103 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1}) 104 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil, nil) 105 s.UpdatePutStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, nil) 106 }, 107 }, 108 { 109 name: "successfully create a network interface with multiple IPConfigs", 110 expectedError: "", 111 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 112 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 113 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec3}) 114 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec3, serviceName).Return(nil, nil) 115 s.UpdatePutStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, nil) 116 }, 117 }, 118 { 119 name: "successfully create multiple network interfaces", 120 expectedError: "", 121 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 122 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 123 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1, &fakeNICSpec2}) 124 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil, nil) 125 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec2, serviceName).Return(nil, nil) 126 s.UpdatePutStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, nil) 127 }, 128 }, 129 { 130 name: "network interface create fails", 131 expectedError: internalError.Error(), 132 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 133 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 134 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1, &fakeNICSpec2}) 135 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil, internalError) 136 r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeNICSpec2, serviceName).Return(nil, nil) 137 s.UpdatePutStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, internalError) 138 }, 139 }, 140 } 141 142 for _, tc := range testcases { 143 tc := tc 144 t.Run(tc.name, func(t *testing.T) { 145 g := NewWithT(t) 146 t.Parallel() 147 mockCtrl := gomock.NewController(t) 148 defer mockCtrl.Finish() 149 scopeMock := mock_networkinterfaces.NewMockNICScope(mockCtrl) 150 asyncMock := mock_async.NewMockReconciler(mockCtrl) 151 152 tc.expect(scopeMock.EXPECT(), asyncMock.EXPECT()) 153 154 s := &Service{ 155 Scope: scopeMock, 156 Reconciler: asyncMock, 157 } 158 159 err := s.Reconcile(context.TODO()) 160 if tc.expectedError != "" { 161 g.Expect(err).To(HaveOccurred()) 162 fmt.Print(cmp.Diff(err.Error(), tc.expectedError)) 163 164 g.Expect(err.Error()).To(Equal(tc.expectedError)) 165 } else { 166 g.Expect(err).NotTo(HaveOccurred()) 167 } 168 }) 169 } 170 } 171 172 func TestDeleteNetworkInterface(t *testing.T) { 173 testcases := []struct { 174 name string 175 expectedError string 176 expect func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) 177 }{ 178 { 179 name: "noop if no network interface specs are found", 180 expectedError: "", 181 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 182 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 183 s.NICSpecs().Return([]azure.ResourceSpecGetter{}) 184 }, 185 }, 186 { 187 name: "successfully delete an existing network interface", 188 expectedError: "", 189 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 190 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 191 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1}) 192 r.DeleteResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil) 193 s.UpdateDeleteStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, nil) 194 }, 195 }, 196 { 197 name: "successfully delete multiple existing network interfaces", 198 expectedError: "", 199 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 200 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 201 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1, &fakeNICSpec2}) 202 r.DeleteResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil) 203 r.DeleteResource(gomockinternal.AContext(), &fakeNICSpec2, serviceName).Return(nil) 204 s.UpdateDeleteStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, nil) 205 }, 206 }, 207 { 208 name: "network interface deletion fails", 209 expectedError: internalError.Error(), 210 expect: func(s *mock_networkinterfaces.MockNICScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) { 211 s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout) 212 s.NICSpecs().Return([]azure.ResourceSpecGetter{&fakeNICSpec1, &fakeNICSpec2}) 213 r.DeleteResource(gomockinternal.AContext(), &fakeNICSpec1, serviceName).Return(nil) 214 r.DeleteResource(gomockinternal.AContext(), &fakeNICSpec2, serviceName).Return(internalError) 215 s.UpdateDeleteStatus(infrav1.NetworkInterfaceReadyCondition, serviceName, internalError) 216 }, 217 }, 218 } 219 220 for _, tc := range testcases { 221 tc := tc 222 t.Run(tc.name, func(t *testing.T) { 223 g := NewWithT(t) 224 t.Parallel() 225 mockCtrl := gomock.NewController(t) 226 defer mockCtrl.Finish() 227 scopeMock := mock_networkinterfaces.NewMockNICScope(mockCtrl) 228 asyncMock := mock_async.NewMockReconciler(mockCtrl) 229 230 tc.expect(scopeMock.EXPECT(), asyncMock.EXPECT()) 231 232 s := &Service{ 233 Scope: scopeMock, 234 Reconciler: asyncMock, 235 } 236 237 err := s.Delete(context.TODO()) 238 if tc.expectedError != "" { 239 g.Expect(err).To(HaveOccurred()) 240 g.Expect(err).To(MatchError(tc.expectedError)) 241 } else { 242 g.Expect(err).NotTo(HaveOccurred()) 243 } 244 }) 245 } 246 }