sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/resourcehealth/resourcehealth_test.go (about)

     1  /*
     2  Copyright 2022 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 resourcehealth
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcehealth/armresourcehealth"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/pkg/errors"
    26  	"go.uber.org/mock/gomock"
    27  	utilfeature "k8s.io/component-base/featuregate/testing"
    28  	"k8s.io/utils/ptr"
    29  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    30  	"sigs.k8s.io/cluster-api-provider-azure/azure/services/resourcehealth/mock_resourcehealth"
    31  	"sigs.k8s.io/cluster-api-provider-azure/feature"
    32  	gomockinternal "sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers/gomock"
    33  	"sigs.k8s.io/cluster-api/util/conditions"
    34  )
    35  
    36  func TestReconcileResourceHealth(t *testing.T) {
    37  	testcases := []struct {
    38  		name            string
    39  		featureDisabled bool
    40  		filterEnabled   bool
    41  		expect          func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, m *mock_resourcehealth.MockclientMockRecorder, f *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder)
    42  		expectedError   string
    43  	}{
    44  		{
    45  			name: "available resource",
    46  			expect: func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, m *mock_resourcehealth.MockclientMockRecorder, _ *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder) {
    47  				s.AvailabilityStatusResource().Times(1)
    48  				s.AvailabilityStatusResourceURI().Times(1)
    49  				m.GetByResource(gomockinternal.AContext(), gomock.Any()).Times(1).Return(armresourcehealth.AvailabilityStatus{
    50  					Properties: &armresourcehealth.AvailabilityStatusProperties{
    51  						AvailabilityState: ptr.To(armresourcehealth.AvailabilityStateValuesAvailable),
    52  					},
    53  				}, nil)
    54  			},
    55  			expectedError: "",
    56  		},
    57  		{
    58  			name: "unavailable resource",
    59  			expect: func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, m *mock_resourcehealth.MockclientMockRecorder, _ *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder) {
    60  				s.AvailabilityStatusResource().Times(1)
    61  				s.AvailabilityStatusResourceURI().Times(1)
    62  				m.GetByResource(gomockinternal.AContext(), gomock.Any()).Times(1).Return(armresourcehealth.AvailabilityStatus{
    63  					Properties: &armresourcehealth.AvailabilityStatusProperties{
    64  						AvailabilityState: ptr.To(armresourcehealth.AvailabilityStateValuesUnavailable),
    65  						Summary:           ptr.To("summary"),
    66  					},
    67  				}, nil)
    68  			},
    69  			expectedError: "resource is not available: summary",
    70  		},
    71  		{
    72  			name: "API error",
    73  			expect: func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, m *mock_resourcehealth.MockclientMockRecorder, _ *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder) {
    74  				s.AvailabilityStatusResourceURI().Times(1).Return("myURI")
    75  				m.GetByResource(gomockinternal.AContext(), gomock.Any()).Times(1).Return(armresourcehealth.AvailabilityStatus{}, errors.New("some API error"))
    76  			},
    77  			expectedError: "failed to get availability status for resource myURI: some API error",
    78  		},
    79  		{
    80  			name:          "filter",
    81  			filterEnabled: true,
    82  			expect: func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, m *mock_resourcehealth.MockclientMockRecorder, f *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder) {
    83  				s.AvailabilityStatusResource().Times(1)
    84  				s.AvailabilityStatusResourceURI().Times(1)
    85  				m.GetByResource(gomockinternal.AContext(), gomock.Any()).Times(1).Return(armresourcehealth.AvailabilityStatus{
    86  					Properties: &armresourcehealth.AvailabilityStatusProperties{
    87  						AvailabilityState: ptr.To(armresourcehealth.AvailabilityStateValuesUnavailable),
    88  						Summary:           ptr.To("summary"),
    89  					},
    90  				}, nil)
    91  				// ignore the above status
    92  				f.AvailabilityStatusFilter(gomock.Any()).Return(conditions.TrueCondition(infrav1.AzureResourceAvailableCondition))
    93  			},
    94  			expectedError: "",
    95  		},
    96  		{
    97  			name:            "feature disabled",
    98  			featureDisabled: true,
    99  			expect: func(s *mock_resourcehealth.MockResourceHealthScopeMockRecorder, _ *mock_resourcehealth.MockclientMockRecorder, _ *mock_resourcehealth.MockAvailabilityStatusFiltererMockRecorder) {
   100  				s.AvailabilityStatusResource().Times(1)
   101  			},
   102  			expectedError: "",
   103  		},
   104  	}
   105  
   106  	for _, tc := range testcases {
   107  		t.Run(tc.name, func(t *testing.T) {
   108  			g := NewWithT(t)
   109  			mockCtrl := gomock.NewController(t)
   110  			defer mockCtrl.Finish()
   111  			scopeMock := mock_resourcehealth.NewMockResourceHealthScope(mockCtrl)
   112  			clientMock := mock_resourcehealth.NewMockclient(mockCtrl)
   113  			filtererMock := mock_resourcehealth.NewMockAvailabilityStatusFilterer(mockCtrl)
   114  
   115  			tc.expect(scopeMock.EXPECT(), clientMock.EXPECT(), filtererMock.EXPECT())
   116  
   117  			s := &Service{
   118  				Scope:  scopeMock,
   119  				client: clientMock,
   120  			}
   121  			if tc.filterEnabled {
   122  				s.Scope = struct {
   123  					ResourceHealthScope
   124  					AvailabilityStatusFilterer
   125  				}{scopeMock, filtererMock}
   126  			}
   127  
   128  			defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.AKSResourceHealth, !tc.featureDisabled)()
   129  
   130  			err := s.Reconcile(context.TODO())
   131  
   132  			if tc.expectedError != "" {
   133  				g.Expect(err).To(HaveOccurred())
   134  				g.Expect(err).To(MatchError(tc.expectedError))
   135  			} else {
   136  				g.Expect(err).NotTo(HaveOccurred())
   137  			}
   138  		})
   139  	}
   140  }