diff --git a/pkg/providers/nutanix/validator.go b/pkg/providers/nutanix/validator.go index 5d8a91f8de5b8..0db741eca530a 100644 --- a/pkg/providers/nutanix/validator.go +++ b/pkg/providers/nutanix/validator.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/nutanix-cloud-native/prism-go-client/utils" + "github.com/nutanix-cloud-native/prism-go-client/v3" "k8s.io/apimachinery/pkg/api/resource" anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1" @@ -62,7 +63,7 @@ func (v *Validator) ValidateDatacenterConfig(ctx context.Context, config *anywhe func (v *Validator) validateEndpointAndPort(dcConf anywherev1.NutanixDatacenterConfigSpec) error { if !networkutils.IsPortValid(strconv.Itoa(dcConf.Port)) { - return fmt.Errorf("nutanix prism central port %q out of range", dcConf.Port) + return fmt.Errorf("nutanix prism central port %q out of range", strconv.Itoa(dcConf.Port)) } if dcConf.Endpoint == "" { diff --git a/pkg/providers/nutanix/validator_test.go b/pkg/providers/nutanix/validator_test.go index f283ade5eb9d3..004402c3b3aac 100644 --- a/pkg/providers/nutanix/validator_test.go +++ b/pkg/providers/nutanix/validator_test.go @@ -5,6 +5,7 @@ import ( _ "embed" "encoding/json" "errors" + "fmt" "net/http" "testing" @@ -337,29 +338,82 @@ func TestNutanixValidatorValidateDatacenterConfig(t *testing.T) { tests := []struct { name string dcConfFile string - expectErr bool + expectErr string + setup func(*MockClient, *mockCrypto.MockTlsValidator, *MockRoundTripper) *Validator }{ { name: "valid datacenter config without trust bundle", dcConfFile: nutanixDatacenterConfigSpec, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, }, { name: "valid datacenter config with trust bundle", dcConfFile: nutanixDatacenterConfigSpecWithTrustBundle, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, }, { name: "valid datacenter config with insecure", dcConfFile: nutanixDatacenterConfigSpecWithInsecure, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, }, { name: "valid datacenter config with invalid port", dcConfFile: nutanixDatacenterConfigSpecWithInvalidPort, - expectErr: true, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, + expectErr: "nutanix prism central port \"99999\" out of range", }, { name: "valid datacenter config with invalid endpoint", dcConfFile: nutanixDatacenterConfigSpecWithInvalidEndpoint, - expectErr: true, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, + expectErr: "nutanix prism central endpoint must be provided", + }, + { + name: "failed to validate endpoint using http.Get", + dcConfFile: nutanixDatacenterConfigSpecWithInsecure, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, fmt.Errorf("http error")).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, + expectErr: "http error", + }, + { + name: "failed to validate credentials using GetCurrentLoggedInUser", + dcConfFile: nutanixDatacenterConfigSpecWithInsecure, + setup: func(mockClient *MockClient, validator *mockCrypto.MockTlsValidator, transport *MockRoundTripper) *Validator { + mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(nil, fmt.Errorf("GetCurrentLoggedInUser failed")).AnyTimes() + validator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + transport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() + return NewValidator(mockClient, validator, &http.Client{Transport: transport}) + }, + expectErr: "GetCurrentLoggedInUser failed", }, } @@ -369,21 +423,11 @@ func TestNutanixValidatorValidateDatacenterConfig(t *testing.T) { require.NoError(t, err) mockClient := NewMockClient(ctrl) - mockClient.EXPECT().GetCurrentLoggedInUser(gomock.Any()).Return(&v3.UserIntentResponse{}, nil).AnyTimes() - - mockTLSValidator := mockCrypto.NewMockTlsValidator(ctrl) - mockTLSValidator.EXPECT().ValidateCert(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - - mockTransport := NewMockRoundTripper(ctrl) - mockTransport.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{}, nil).AnyTimes() - - mockHTTPClient := &http.Client{Transport: mockTransport} - validator := NewValidator(mockClient, mockTLSValidator, mockHTTPClient) - require.NotNil(t, validator) + validator := tt.setup(mockClient, mockCrypto.NewMockTlsValidator(ctrl), NewMockRoundTripper(ctrl)) err = validator.ValidateDatacenterConfig(context.Background(), dcConf) - if tt.expectErr { - assert.Error(t, err, tt.name) + if tt.expectErr != "" { + assert.Contains(t, err.Error(), tt.expectErr, tt.name) } else { assert.NoError(t, err, tt.name) }