sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/routetables/routetables_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 routetables
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"testing"
    23  
    24  	. "github.com/onsi/gomega"
    25  	"go.uber.org/mock/gomock"
    26  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    27  	"sigs.k8s.io/cluster-api-provider-azure/azure"
    28  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/async/mock_async"
    29  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/routetables/mock_routetables"
    30  	gomockinternal "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock"
    31  	"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
    32  )
    33  
    34  var (
    35  	fakeRT = RouteTableSpec{
    36  		Name:          "test-rt-1",
    37  		ResourceGroup: "test-rg",
    38  		Location:      "fake-location",
    39  		ClusterName:   "test-cluster",
    40  		AdditionalTags: map[string]string{
    41  			"foo": "bar",
    42  		},
    43  	}
    44  	fakeRT2 = RouteTableSpec{
    45  		Name:          "test-rt-2",
    46  		ResourceGroup: "test-rg",
    47  		Location:      "fake-location",
    48  		ClusterName:   "test-cluster",
    49  	}
    50  	errFake      = errors.New("this is an error")
    51  	notDoneError = azure.NewOperationNotDoneError(&infrav1.Future{})
    52  )
    53  
    54  func TestReconcileRouteTables(t *testing.T) {
    55  	testcases := []struct {
    56  		name          string
    57  		tags          infrav1.Tags
    58  		expectedError string
    59  		expect        func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder)
    60  	}{
    61  		{
    62  			name:          "noop if no route table specs are found",
    63  			expectedError: "",
    64  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
    65  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
    66  				s.IsVnetManaged().Return(true)
    67  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{})
    68  			},
    69  		},
    70  		{
    71  			name:          "create multiple route tables succeeds",
    72  			expectedError: "",
    73  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
    74  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
    75  				s.IsVnetManaged().Return(true)
    76  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
    77  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(nil, nil)
    78  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(nil, nil)
    79  				s.UpdatePutStatus(infrav1.RouteTablesReadyCondition, serviceName, nil)
    80  			},
    81  		},
    82  		{
    83  			name:          "first route table create fails",
    84  			expectedError: errFake.Error(),
    85  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
    86  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
    87  				s.IsVnetManaged().Return(true)
    88  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
    89  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(nil, errFake)
    90  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(nil, nil)
    91  				s.UpdatePutStatus(infrav1.RouteTablesReadyCondition, serviceName, errFake)
    92  			},
    93  		},
    94  		{
    95  			name:          "second route table create not done",
    96  			expectedError: errFake.Error(),
    97  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
    98  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
    99  				s.IsVnetManaged().Return(true)
   100  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
   101  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(nil, errFake)
   102  				r.CreateOrUpdateResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(nil, notDoneError)
   103  				s.UpdatePutStatus(infrav1.RouteTablesReadyCondition, serviceName, errFake)
   104  			},
   105  		},
   106  		{
   107  			name:          "noop if vnet is not managed",
   108  			expectedError: "",
   109  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   110  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   111  				s.IsVnetManaged().Return(false)
   112  			},
   113  		},
   114  	}
   115  
   116  	for _, tc := range testcases {
   117  		tc := tc
   118  		t.Run(tc.name, func(t *testing.T) {
   119  			g := NewWithT(t)
   120  			t.Parallel()
   121  			mockCtrl := gomock.NewController(t)
   122  			defer mockCtrl.Finish()
   123  			scopeMock := mock_routetables.NewMockRouteTableScope(mockCtrl)
   124  			reconcilerMock := mock_async.NewMockReconciler(mockCtrl)
   125  
   126  			tc.expect(scopeMock.EXPECT(), reconcilerMock.EXPECT())
   127  
   128  			s := &Service{
   129  				Scope:      scopeMock,
   130  				Reconciler: reconcilerMock,
   131  			}
   132  
   133  			err := s.Reconcile(context.TODO())
   134  			if tc.expectedError != "" {
   135  				g.Expect(err).To(HaveOccurred())
   136  				g.Expect(err).To(MatchError(tc.expectedError))
   137  			} else {
   138  				g.Expect(err).NotTo(HaveOccurred())
   139  			}
   140  		})
   141  	}
   142  }
   143  
   144  func TestDeleteRouteTable(t *testing.T) {
   145  	testcases := []struct {
   146  		name          string
   147  		tags          infrav1.Tags
   148  		expectedError string
   149  		expect        func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder)
   150  	}{
   151  		{
   152  			name:          "noop if no route table specs are found",
   153  			expectedError: "",
   154  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   155  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   156  				s.IsVnetManaged().Return(true)
   157  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{})
   158  			},
   159  		},
   160  		{
   161  			name:          "delete multiple route tables succeeds",
   162  			expectedError: "",
   163  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   164  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   165  				s.IsVnetManaged().Return(true)
   166  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
   167  				r.DeleteResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(nil)
   168  				r.DeleteResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(nil)
   169  				s.UpdateDeleteStatus(infrav1.RouteTablesReadyCondition, serviceName, nil)
   170  			},
   171  		},
   172  		{
   173  			name:          "first route table delete fails",
   174  			expectedError: errFake.Error(),
   175  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   176  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   177  				s.IsVnetManaged().Return(true)
   178  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
   179  				r.DeleteResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(errFake)
   180  				r.DeleteResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(nil)
   181  				s.UpdateDeleteStatus(infrav1.RouteTablesReadyCondition, serviceName, errFake)
   182  			},
   183  		},
   184  		{
   185  			name:          "second route table delete not done",
   186  			expectedError: errFake.Error(),
   187  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   188  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   189  				s.IsVnetManaged().Return(true)
   190  				s.RouteTableSpecs().Return([]azure.ResourceSpecGetter{&fakeRT, &fakeRT2})
   191  				r.DeleteResource(gomockinternal.AContext(), &fakeRT, serviceName).Return(errFake)
   192  				r.DeleteResource(gomockinternal.AContext(), &fakeRT2, serviceName).Return(notDoneError)
   193  				s.UpdateDeleteStatus(infrav1.RouteTablesReadyCondition, serviceName, errFake)
   194  			},
   195  		},
   196  		{
   197  			name:          "noop if vnet is not managed",
   198  			expectedError: "",
   199  			expect: func(s *mock_routetables.MockRouteTableScopeMockRecorder, r *mock_async.MockReconcilerMockRecorder) {
   200  				s.DefaultedAzureServiceReconcileTimeout().Return(reconciler.DefaultAzureServiceReconcileTimeout)
   201  				s.IsVnetManaged().Return(false)
   202  			},
   203  		},
   204  	}
   205  
   206  	for _, tc := range testcases {
   207  		tc := tc
   208  		t.Run(tc.name, func(t *testing.T) {
   209  			g := NewWithT(t)
   210  			t.Parallel()
   211  			mockCtrl := gomock.NewController(t)
   212  			defer mockCtrl.Finish()
   213  			scopeMock := mock_routetables.NewMockRouteTableScope(mockCtrl)
   214  			reconcilerMock := mock_async.NewMockReconciler(mockCtrl)
   215  
   216  			tc.expect(scopeMock.EXPECT(), reconcilerMock.EXPECT())
   217  
   218  			s := &Service{
   219  				Scope:      scopeMock,
   220  				Reconciler: reconcilerMock,
   221  			}
   222  
   223  			err := s.Delete(context.TODO())
   224  			if tc.expectedError != "" {
   225  				g.Expect(err).To(HaveOccurred())
   226  				g.Expect(err).To(MatchError(tc.expectedError))
   227  			} else {
   228  				g.Expect(err).NotTo(HaveOccurred())
   229  			}
   230  		})
   231  	}
   232  }