diff --git a/internal/e2e/errors_test.go b/internal/e2e/errors_test.go index c87b7884e..c2aa273ed 100644 --- a/internal/e2e/errors_test.go +++ b/internal/e2e/errors_test.go @@ -9,7 +9,7 @@ import ( ) func TestStandardErrors(t *testing.T) { - client, _, err := newE2EClient(true) + client, _, _, err := newE2EClient(true) testhelpers.AssertNoError(t, err) t.Run("not found", func(t *testing.T) { diff --git a/internal/e2e/human_test.go b/internal/e2e/human_test.go index 379d37d74..3a8600ddc 100644 --- a/internal/e2e/human_test.go +++ b/internal/e2e/human_test.go @@ -8,13 +8,13 @@ import ( "github.com/scaleway/scaleway-sdk-go/scw" ) -func newE2EClient(withAuthInClient bool) (*test.API, string, error) { +func newE2EClient(withAuthInClient bool) (*test.API, string, string, error) { client, err := scw.NewClient( scw.WithDefaultRegion(scw.RegionFrPar), scw.WithUserAgent("sdk-e2e-test"), ) if err != nil { - return nil, "", err + return nil, "", "", err } testClient := test.NewAPI(client) @@ -22,31 +22,31 @@ func newE2EClient(withAuthInClient bool) (*test.API, string, error) { Username: "sidi", }) if err != nil { - return nil, "", err + return nil, "", "", err } if withAuthInClient { client, err = scw.NewClient( scw.WithDefaultRegion(scw.RegionFrPar), - scw.WithAuth("", registerResponse.SecretKey), + scw.WithAuth(registerResponse.AccessKey, registerResponse.SecretKey), scw.WithUserAgent("sdk-e2e-test"), ) testClient = test.NewAPI(client) } - return testClient, registerResponse.SecretKey, err + return testClient, registerResponse.AccessKey, registerResponse.SecretKey, err } func TestAuthInRequest(t *testing.T) { - client, secretKey, err := newE2EClient(false) + client, accessKey, secretKey, err := newE2EClient(false) testhelpers.AssertNoError(t, err) - requestWithAuth := scw.WithAuthRequest("", secretKey) + requestWithAuth := scw.WithAuthRequest(accessKey, secretKey) _, err = client.CreateHuman(&test.CreateHumanRequest{}, requestWithAuth) testhelpers.AssertNoError(t, err) } func TestHuman(t *testing.T) { - client, _, err := newE2EClient(true) + client, _, _, err := newE2EClient(true) testhelpers.AssertNoError(t, err) // create diff --git a/scw/client_option.go b/scw/client_option.go index e10ec59c8..782238be1 100644 --- a/scw/client_option.go +++ b/scw/client_option.go @@ -172,7 +172,17 @@ func (s *settings) apply(opts []ClientOption) { func (s *settings) validate() error { var err error if s.token == nil { - return errors.New("no credential option provided") + // It should not happen, WithoutAuth option is used by default. + panic(errors.New("no credential option provided")) + } + + if token, isToken := s.token.(*auth.Token); isToken { + if token.AccessKey == "" { + return &ClientCredentialError{errorType: clientCredentialError_EmptyAccessKey} + } + if token.SecretKey == "" { + return &ClientCredentialError{errorType: clientCredentialError_EmptySecreyKey} + } } _, err = url.Parse(s.apiURL) diff --git a/scw/client_option_test.go b/scw/client_option_test.go index bdf87a87a..1299a5357 100644 --- a/scw/client_option_test.go +++ b/scw/client_option_test.go @@ -15,8 +15,8 @@ const ( var ( defaultOrganizationID = "6170692e-7363-616c-6577-61792e636f6d" // hint: | xxd -ps -r - defaultRegion = RegionNlAms - defaultZone = ZoneNlAms1 + defaultRegion = RegionNlAms + defaultZone = ZoneNlAms1 ) func TestClientOptions(t *testing.T) { @@ -37,11 +37,20 @@ func TestClientOptions(t *testing.T) { }, }, { - name: "Should throw an credential error", + name: "Should throw an access key error", clientOption: func(s *settings) { s.apiURL = apiURL + s.token = auth.NewToken("", testSecretKey) }, - errStr: "scaleway-sdk-go: no credential option provided", + errStr: "scaleway-sdk-go: access key cannot be empty", + }, + { + name: "Should throw a secret key error", + clientOption: func(s *settings) { + s.apiURL = apiURL + s.token = auth.NewToken(testSecretKey, "") + }, + errStr: "scaleway-sdk-go: secret key cannot be empty", }, { name: "Should throw an url error", @@ -107,56 +116,56 @@ func TestCombinedClientOptions(t *testing.T) { env map[string]string files map[string]string - expectedError string - expectedAccessKey string - expectedSecretKey string - expectedAPIURL string + expectedError string + expectedAccessKey string + expectedSecretKey string + expectedAPIURL string expectedDefaultOrganizationID *string - expectedDefaultRegion *Region - expectedDefaultZone *Zone + expectedDefaultRegion *Region + expectedDefaultZone *Zone }{ { name: "Complete config file with env variables", env: map[string]string{ - "HOME": "{HOME}", - scwAccessKeyEnv: v2ValidAccessKey2, - scwSecretKeyEnv: v2ValidSecretKey2, - scwAPIURLEnv: v2ValidAPIURL2, + "HOME": "{HOME}", + scwAccessKeyEnv: v2ValidAccessKey2, + scwSecretKeyEnv: v2ValidSecretKey2, + scwAPIURLEnv: v2ValidAPIURL2, scwDefaultOrganizationIDEnv: v2ValidDefaultOrganizationID2, - scwDefaultRegionEnv: v2ValidDefaultRegion2, - scwDefaultZoneEnv: v2ValidDefaultZone2, + scwDefaultRegionEnv: v2ValidDefaultRegion2, + scwDefaultZoneEnv: v2ValidDefaultZone2, }, files: map[string]string{ ".config/scw/config.yaml": v2CompleteValidConfigFile, }, - expectedAccessKey: v2ValidAccessKey2, - expectedSecretKey: v2ValidSecretKey2, - expectedAPIURL: v2ValidAPIURL2, + expectedAccessKey: v2ValidAccessKey2, + expectedSecretKey: v2ValidSecretKey2, + expectedAPIURL: v2ValidAPIURL2, expectedDefaultOrganizationID: s(v2ValidDefaultOrganizationID2), - expectedDefaultRegion: r(Region(v2ValidDefaultRegion2)), - expectedDefaultZone: z(Zone(v2ValidDefaultZone2)), + expectedDefaultRegion: r(Region(v2ValidDefaultRegion2)), + expectedDefaultZone: z(Zone(v2ValidDefaultZone2)), }, { name: "Complete config with active profile env variable and all env variables", env: map[string]string{ - "HOME": "{HOME}", - scwActiveProfileEnv: v2ValidProfile, - scwAccessKeyEnv: v2ValidAccessKey, - scwSecretKeyEnv: v2ValidSecretKey, - scwAPIURLEnv: v2ValidAPIURL, + "HOME": "{HOME}", + scwActiveProfileEnv: v2ValidProfile, + scwAccessKeyEnv: v2ValidAccessKey, + scwSecretKeyEnv: v2ValidSecretKey, + scwAPIURLEnv: v2ValidAPIURL, scwDefaultOrganizationIDEnv: v2ValidDefaultOrganizationID, - scwDefaultRegionEnv: v2ValidDefaultRegion, - scwDefaultZoneEnv: v2ValidDefaultZone, + scwDefaultRegionEnv: v2ValidDefaultRegion, + scwDefaultZoneEnv: v2ValidDefaultZone, }, files: map[string]string{ ".config/scw/config.yaml": v2CompleteValidConfigFile, }, - expectedAccessKey: v2ValidAccessKey, - expectedSecretKey: v2ValidSecretKey, - expectedAPIURL: v2ValidAPIURL, + expectedAccessKey: v2ValidAccessKey, + expectedSecretKey: v2ValidSecretKey, + expectedAPIURL: v2ValidAPIURL, expectedDefaultOrganizationID: s(v2ValidDefaultOrganizationID), - expectedDefaultRegion: r(Region(v2ValidDefaultRegion)), - expectedDefaultZone: z(Zone(v2ValidDefaultZone)), + expectedDefaultRegion: r(Region(v2ValidDefaultRegion)), + expectedDefaultZone: z(Zone(v2ValidDefaultZone)), }, } diff --git a/scw/errors.go b/scw/errors.go index 86672113d..cd1e201e8 100644 --- a/scw/errors.go +++ b/scw/errors.go @@ -255,3 +255,21 @@ func (e *OutOfStockError) Error() string { func (e *OutOfStockError) GetRawBody() json.RawMessage { return e.RawBody } + +type clientCredentialErrorType string + +const ( + clientCredentialError_EmptyAccessKey = clientCredentialErrorType("access key cannot be empty") + clientCredentialError_EmptySecreyKey = clientCredentialErrorType("secret key cannot be empty") +) + +// clientCredentialError indicates that credentials have been badly provided for the client creation. +type ClientCredentialError struct { + errorType clientCredentialErrorType +} + +// IsScwSdkError implements the SdkError interface +func (e ClientCredentialError) IsScwSdkError() {} +func (e ClientCredentialError) Error() string { + return fmt.Sprintf("scaleway-sdk-go: %s", e.errorType) +}