diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index b85c1c6..b83a17e 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -11,13 +11,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-go@v3 with: - go-version: 1.17 + go-version: 1.21 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.39 + version: v1.55.2 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index c040754..8fc32ea 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -13,12 +13,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.16 + go-version: 1.21 - name: Run test run: make unittest diff --git a/.golangci.yml b/.golangci.yml index badbe7f..344f827 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,7 +21,6 @@ linters: - godox - goprintffuncname - gosimple - - ifshort - lll - makezero - nakedret @@ -55,8 +54,10 @@ linters-settings: - fieldalignment lll: tab-width: 4 - nolintlint: - allow-leading-space: false + dupl: + threshold: 500 + revive: + severity: error issues: max-issues-per-linter: 0 max-same-issues: 0 diff --git a/README.md b/README.md index 1c16c9c..5e6a42b 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,19 @@ The Go library documentation is available at [go.dev](https://pkg.go.dev/github. You can use this library to work with the following objects of the Selectel Managed Databases Service: -* datastore +* acl +* available extension +* configuration parameter * database -* user -* grant +* datastore * datastore type -* flavor * extension -* available extension -* configuration parameter -* prometheus metrics tokens +* flavor +* grant * logical replication slots +* prometheus metrics tokens +* topic +* user ## Getting started @@ -56,6 +58,7 @@ Selectel Managed Databases Service currently has the following API endpoint: | https://ru-9.dbaas.selcloud.ru/v1 | ru-9 | | https://nl-1.dbaas.selcloud.ru/v1 | nl-1 | | https://uz-1.dbaas.selcloud.ru/v1 | uz-1 | +| https://kz-1.dbaas.selcloud.ru/v1 | kz-1 | You can also retrieve all available API endpoints from the Identity catalog. diff --git a/acl.go b/acl.go index 02a2b6f..88c328f 100644 --- a/acl.go +++ b/acl.go @@ -49,9 +49,11 @@ type ACLQueryParams struct { Status Status `json:"status,omitempty"` } +const ACLsURI = "/acls" + // ACLs returns all ACLs. func (api *API) ACLs(ctx context.Context, params *ACLQueryParams) ([]ACL, error) { - uri, err := setQueryParams("/acls", params) + uri, err := setQueryParams(ACLsURI, params) if err != nil { return []ACL{}, err } @@ -74,7 +76,7 @@ func (api *API) ACLs(ctx context.Context, params *ACLQueryParams) ([]ACL, error) // ACL returns an ACL based on the ID. func (api *API) ACL(ctx context.Context, aclID string) (ACL, error) { - uri := fmt.Sprintf("/acls/%s", aclID) + uri := fmt.Sprintf("%s/%s", ACLsURI, aclID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -94,7 +96,6 @@ func (api *API) ACL(ctx context.Context, aclID string) (ACL, error) { // CreateACL creates a new acl. func (api *API) CreateACL(ctx context.Context, opts ACLCreateOpts) (ACL, error) { - uri := "/acls" createACLOpts := struct { ACL ACLCreateOpts `json:"acl"` }{ @@ -105,7 +106,7 @@ func (api *API) CreateACL(ctx context.Context, opts ACLCreateOpts) (ACL, error) return ACL{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, ACLsURI, requestBody) if err != nil { return ACL{}, err } @@ -123,7 +124,7 @@ func (api *API) CreateACL(ctx context.Context, opts ACLCreateOpts) (ACL, error) // UpdateACL updates an existing acl. func (api *API) UpdateACL(ctx context.Context, aclID string, opts ACLUpdateOpts) (ACL, error) { - uri := fmt.Sprintf("/acls/%s", aclID) + uri := fmt.Sprintf("%s/%s", ACLsURI, aclID) updateACLOpts := struct { ACL ACLUpdateOpts `json:"acl"` }{ @@ -152,7 +153,7 @@ func (api *API) UpdateACL(ctx context.Context, aclID string, opts ACLUpdateOpts) // DeleteACL deletes an existing acl. func (api *API) DeleteACL(ctx context.Context, aclID string) error { - uri := fmt.Sprintf("/acls/%s", aclID) + uri := fmt.Sprintf("%s/%s", ACLsURI, aclID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/acl_test.go b/acl_test.go index 249db76..dd547c2 100644 --- a/acl_test.go +++ b/acl_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const aclID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testACLNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "acl 123 not found." + "message": "acl %s not found." } }` @@ -119,7 +121,7 @@ func TestACLs(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/acls", + httpmock.RegisterResponder("GET", testClient.Endpoint+ACLsURI, httpmock.NewStringResponder(200, testACLsResponse)) expected := []ACL{ @@ -153,9 +155,8 @@ func TestACLs(t *testing.T) { actual, err := testClient.ACLs(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestACL(t *testing.T) { @@ -163,14 +164,13 @@ func TestACL(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/acls/"+aclID, + httpmock.RegisterResponder("GET", testClient.Endpoint+ACLsURI+"/"+aclID, httpmock.NewStringResponder(200, testACLResponse)) actual, err := testClient.ACL(context.Background(), aclID) - if assert.NoError(t, err) { - assert.Equal(t, ACLExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, ACLExpected, actual) } func TestACLNotFound(t *testing.T) { @@ -178,17 +178,18 @@ func TestACLNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/acls/123", - httpmock.NewStringResponder(404, testACLNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testACLNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+ACLsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "acl 123 not found." + expected.APIError.Message = fmt.Sprintf("acl %s not found.", NotFoundEntityID) - _, err := testClient.ACL(context.Background(), "123") + _, err := testClient.ACL(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateACL(t *testing.T) { @@ -196,7 +197,7 @@ func TestCreateACL(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/acls", + httpmock.RegisterResponder("POST", testClient.Endpoint+ACLsURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&ACLCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -228,9 +229,8 @@ func TestCreateACL(t *testing.T) { ACLCreateExpected := ACLExpected ACLCreateExpected.Status = StatusPendingCreate - if assert.NoError(t, err) { - assert.Equal(t, ACLCreateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, ACLCreateExpected, actual) } func TestCreateACLInvalidDatastoreID(t *testing.T) { @@ -238,7 +238,7 @@ func TestCreateACLInvalidDatastoreID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/acls", + httpmock.RegisterResponder("POST", testClient.Endpoint+ACLsURI, httpmock.NewStringResponder(400, testCreateACLInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -258,7 +258,7 @@ func TestCreateACLInvalidDatastoreID(t *testing.T) { _, err := testClient.CreateACL(context.Background(), createACLOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestUpdateACL(t *testing.T) { @@ -266,7 +266,7 @@ func TestUpdateACL(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/acls/"+aclID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+ACLsURI+"/"+aclID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&ACLUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -294,9 +294,8 @@ func TestUpdateACL(t *testing.T) { ACLUpdateExpexted := ACLExpected ACLUpdateExpexted.Status = StatusPendingUpdate - if assert.NoError(t, err) { - assert.Equal(t, ACLUpdateExpexted, actual) - } + require.NoError(t, err) + assert.Equal(t, ACLUpdateExpexted, actual) } func TestUpdateACLInvalidResponse(t *testing.T) { @@ -304,7 +303,7 @@ func TestUpdateACLInvalidResponse(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/acls/"+aclID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+ACLsURI+"/"+aclID, httpmock.NewStringResponder(400, testUpdateACLInvalidResponse)) expected := &DBaaSAPIError{} @@ -320,5 +319,5 @@ func TestUpdateACLInvalidResponse(t *testing.T) { _, err := testClient.UpdateACL(context.Background(), aclID, updateACLOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/available_extension.go b/available_extension.go index 2c01c48..dcf9a6a 100644 --- a/available_extension.go +++ b/available_extension.go @@ -15,11 +15,11 @@ type AvailableExtension struct { DependencyIDs []string `json:"dependency_ids"` } +const AvailableExtensionsURI = "/available-extensions" + // AvailableExtensions returns all available extensions. func (api *API) AvailableExtensions(ctx context.Context) ([]AvailableExtension, error) { - uri := "/available-extensions" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, AvailableExtensionsURI, nil) if err != nil { return []AvailableExtension{}, err } @@ -37,7 +37,7 @@ func (api *API) AvailableExtensions(ctx context.Context) ([]AvailableExtension, // AvailableExtension returns an available extension based on the ID. func (api *API) AvailableExtension(ctx context.Context, availableExtensionID string) (AvailableExtension, error) { - uri := fmt.Sprintf("/available-extensions/%s", availableExtensionID) + uri := fmt.Sprintf("%s/%s", AvailableExtensionsURI, availableExtensionID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { diff --git a/available_extension_test.go b/available_extension_test.go index 1bf369a..0d342bb 100644 --- a/available_extension_test.go +++ b/available_extension_test.go @@ -2,10 +2,12 @@ package dbaas import ( "context" + "fmt" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const availableExtensionID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -14,7 +16,7 @@ const testAvailableExtensionNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "availableextension 123 not found." + "message": "availableextension %s not found." } }` @@ -58,7 +60,7 @@ func TestAvailableExtensions(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/available-extensions", + httpmock.RegisterResponder("GET", testClient.Endpoint+AvailableExtensionsURI, httpmock.NewStringResponder(200, testAvailableExtensionsResponse)) expected := []AvailableExtension{ @@ -84,9 +86,8 @@ func TestAvailableExtensions(t *testing.T) { actual, err := testClient.AvailableExtensions(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestAvailableExtension(t *testing.T) { @@ -94,7 +95,7 @@ func TestAvailableExtension(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/available-extensions/"+datastoreTypeID, + httpmock.RegisterResponder("GET", testClient.Endpoint+AvailableExtensionsURI+"/"+datastoreTypeID, httpmock.NewStringResponder(200, testAvailableExtensionResponse)) expected := AvailableExtension{ @@ -109,9 +110,8 @@ func TestAvailableExtension(t *testing.T) { actual, err := testClient.AvailableExtension(context.Background(), availableExtensionID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestAvailableExtensionNotFound(t *testing.T) { @@ -119,15 +119,16 @@ func TestAvailableExtensionNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/available-extensions/123", - httpmock.NewStringResponder(404, testAvailableExtensionNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testAvailableExtensionNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+AvailableExtensionsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "availableextension 123 not found." + expected.APIError.Message = fmt.Sprintf("availableextension %s not found.", NotFoundEntityID) - _, err := testClient.AvailableExtension(context.Background(), "123") + _, err := testClient.AvailableExtension(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/configuration_parameter.go b/configuration_parameter.go index 466d5b5..be40ac7 100644 --- a/configuration_parameter.go +++ b/configuration_parameter.go @@ -22,11 +22,11 @@ type ConfigurationParameter struct { IsChangeable bool `json:"is_changeable"` } +const ConfigurationParametersURI = "/configuration-parameters" + // ConfigurationParameters returns all configuration parameters. func (api *API) ConfigurationParameters(ctx context.Context) ([]ConfigurationParameter, error) { - uri := "/configuration-parameters" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, ConfigurationParametersURI, nil) if err != nil { return []ConfigurationParameter{}, err } @@ -47,7 +47,7 @@ func (api *API) ConfigurationParameter( ctx context.Context, configurationParameterID string, ) (ConfigurationParameter, error) { - uri := fmt.Sprintf("/configuration-parameters/%s", configurationParameterID) + uri := fmt.Sprintf("%s/%s", ConfigurationParametersURI, configurationParameterID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { diff --git a/configuration_parameter_test.go b/configuration_parameter_test.go index 6bafdb5..027003a 100644 --- a/configuration_parameter_test.go +++ b/configuration_parameter_test.go @@ -2,10 +2,12 @@ package dbaas import ( "context" + "fmt" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const configurationParameterID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -14,7 +16,7 @@ const testConfigurationParameterNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "configurationparameter 123 not found." + "message": "configurationparameter %s not found." } }` @@ -77,7 +79,7 @@ func TestConfigurationParameters(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/configuration-parameters", + httpmock.RegisterResponder("GET", testClient.Endpoint+ConfigurationParametersURI, httpmock.NewStringResponder(200, testConfigurationParametersResponse)) choices := []interface{}{"NEVER", "AUTO", "ALWAYS", "0", "1", "2"} @@ -112,9 +114,8 @@ func TestConfigurationParameters(t *testing.T) { actual, err := testClient.ConfigurationParameters(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestConfigurationParameter(t *testing.T) { @@ -122,7 +123,7 @@ func TestConfigurationParameter(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/configuration-parameters/"+configurationParameterID, + httpmock.RegisterResponder("GET", testClient.Endpoint+ConfigurationParametersURI+"/"+configurationParameterID, httpmock.NewStringResponder(200, testConfigurationParameterResponse)) expected := ConfigurationParameter{ @@ -141,9 +142,8 @@ func TestConfigurationParameter(t *testing.T) { actual, err := testClient.ConfigurationParameter(context.Background(), configurationParameterID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestConfigurationParameterNotFound(t *testing.T) { @@ -151,15 +151,16 @@ func TestConfigurationParameterNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/configuration-parameters/123", - httpmock.NewStringResponder(404, testConfigurationParameterNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testConfigurationParameterNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+ConfigurationParametersURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "configurationparameter 123 not found." + expected.APIError.Message = fmt.Sprintf("configurationparameter %s not found.", NotFoundEntityID) - _, err := testClient.ConfigurationParameter(context.Background(), "123") + _, err := testClient.ConfigurationParameter(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/database.go b/database.go index 9037426..970168b 100644 --- a/database.go +++ b/database.go @@ -40,16 +40,15 @@ type DatabaseQueryParams struct { ID string `json:"id,omitempty"` ProjectID string `json:"project_id,omitempty"` Name string `json:"name,omitempty"` - OwnerID string `json:"owner_id,omitempty"` - LcCollate string `json:"lc_collate,omitempty"` - LcCtype string `json:"lc_ctype,omitempty"` DatastoreID string `json:"datastore_id,omitempty"` Status Status `json:"status,omitempty"` } +const DatabasesURI = "/databases" + // Databases returns all databases. func (api *API) Databases(ctx context.Context, params *DatabaseQueryParams) ([]Database, error) { - uri, err := setQueryParams("/databases", params) + uri, err := setQueryParams(DatabasesURI, params) if err != nil { return []Database{}, err } @@ -72,7 +71,7 @@ func (api *API) Databases(ctx context.Context, params *DatabaseQueryParams) ([]D // Database returns a database based on the ID. func (api *API) Database(ctx context.Context, databaseID string) (Database, error) { - uri := fmt.Sprintf("/databases/%s", databaseID) + uri := fmt.Sprintf("%s/%s", DatabasesURI, databaseID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -92,7 +91,6 @@ func (api *API) Database(ctx context.Context, databaseID string) (Database, erro // CreateDatabase creates a new database. func (api *API) CreateDatabase(ctx context.Context, opts DatabaseCreateOpts) (Database, error) { - uri := "/databases" createDatabaseOpts := struct { Database DatabaseCreateOpts `json:"database"` }{ @@ -103,7 +101,7 @@ func (api *API) CreateDatabase(ctx context.Context, opts DatabaseCreateOpts) (Da return Database{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, DatabasesURI, requestBody) if err != nil { return Database{}, err } @@ -121,7 +119,7 @@ func (api *API) CreateDatabase(ctx context.Context, opts DatabaseCreateOpts) (Da // UpdateDatabase updates an existing database. func (api *API) UpdateDatabase(ctx context.Context, databaseID string, opts DatabaseUpdateOpts) (Database, error) { - uri := fmt.Sprintf("/databases/%s", databaseID) + uri := fmt.Sprintf("%s/%s", DatabasesURI, databaseID) updateDatabaseOpts := struct { Database DatabaseUpdateOpts `json:"database"` }{ @@ -150,7 +148,7 @@ func (api *API) UpdateDatabase(ctx context.Context, databaseID string, opts Data // DeleteDatabase deletes an existing database. func (api *API) DeleteDatabase(ctx context.Context, databaseID string) error { - uri := fmt.Sprintf("/databases/%s", databaseID) + uri := fmt.Sprintf("%s/%s", DatabasesURI, databaseID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/database_test.go b/database_test.go index 76acb5a..1d9b96f 100644 --- a/database_test.go +++ b/database_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const databaseID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testDatabaseNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "database 123 not found." + "message": "database %s not found." } }` @@ -85,7 +87,7 @@ func TestDatabases(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/databases", + httpmock.RegisterResponder("GET", testClient.Endpoint+DatabasesURI, httpmock.NewStringResponder(200, testDatabasesResponse)) expected := []Database{ @@ -115,9 +117,8 @@ func TestDatabases(t *testing.T) { actual, err := testClient.Databases(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestDatabase(t *testing.T) { @@ -125,7 +126,7 @@ func TestDatabase(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/databases/"+databaseID, + httpmock.RegisterResponder("GET", testClient.Endpoint+DatabasesURI+"/"+databaseID, httpmock.NewStringResponder(200, testDatabaseResponse)) expected := Database{ @@ -142,9 +143,8 @@ func TestDatabase(t *testing.T) { actual, err := testClient.Database(context.Background(), databaseID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestDatabaseNotFound(t *testing.T) { @@ -152,17 +152,18 @@ func TestDatabaseNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/databases/123", - httpmock.NewStringResponder(404, testDatabaseNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testDatabaseNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+DatabasesURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "database 123 not found." + expected.APIError.Message = fmt.Sprintf("database %s not found.", NotFoundEntityID) - _, err := testClient.Database(context.Background(), "123") + _, err := testClient.Database(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateDatabase(t *testing.T) { @@ -170,7 +171,7 @@ func TestCreateDatabase(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/databases", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatabasesURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatabaseCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -217,9 +218,8 @@ func TestCreateDatabase(t *testing.T) { actual, err := testClient.CreateDatabase(context.Background(), createDatabaseOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestCreateDatabaseInvalidDatastoreID(t *testing.T) { @@ -227,7 +227,7 @@ func TestCreateDatabaseInvalidDatastoreID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/databases", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatabasesURI, httpmock.NewStringResponder(400, testCreateDatabaseInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -244,7 +244,7 @@ func TestCreateDatabaseInvalidDatastoreID(t *testing.T) { _, err := testClient.CreateDatabase(context.Background(), createDatabaseOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestUpdateDatabase(t *testing.T) { @@ -252,7 +252,7 @@ func TestUpdateDatabase(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/databases/"+databaseID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatabasesURI+"/"+databaseID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatabaseUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -297,9 +297,8 @@ func TestUpdateDatabase(t *testing.T) { actual, err := testClient.UpdateDatabase(context.Background(), databaseID, updateDatabaseOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUpdateDatabaseInvalidOwnerID(t *testing.T) { @@ -307,7 +306,7 @@ func TestUpdateDatabaseInvalidOwnerID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/databases/"+databaseID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatabasesURI+"/"+databaseID, httpmock.NewStringResponder(400, testUpdateDatabaseInvalidOwnerIDResponse)) expected := &DBaaSAPIError{} @@ -322,5 +321,5 @@ func TestUpdateDatabaseInvalidOwnerID(t *testing.T) { _, err := testClient.UpdateDatabase(context.Background(), databaseID, updateDatabaseOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/datastore.go b/datastore.go index 999416e..868cfe7 100644 --- a/datastore.go +++ b/datastore.go @@ -58,7 +58,9 @@ type Datastore struct { Flavor Flavor `json:"flavor"` NodeCount int `json:"node_count"` Enabled bool `json:"enabled"` + AllowRestore bool `json:"allow_restore"` IsMaintenance bool `json:"is_maintenance"` + IsProtected bool `json:"is_protected"` BackupRetentionDays int `json:"backup_retention_days"` } @@ -112,14 +114,18 @@ type DatastorePasswordOpts struct { // DatastoreQueryParams represents available query parameters for datastore. type DatastoreQueryParams struct { - ID string `json:"id,omitempty"` - ProjectID string `json:"project_id,omitempty"` - Name string `json:"name,omitempty"` - Status Status `json:"status,omitempty"` - Enabled string `json:"enabled,omitempty"` - TypeID string `json:"type_id,omitempty"` - SubnetID string `json:"subnet_id,omitempty"` - Deleted bool `json:"deleted,omitempty"` + ID string `json:"id,omitempty"` + ProjectID string `json:"project_id,omitempty"` + Name string `json:"name,omitempty"` + Status Status `json:"status,omitempty"` + Enabled string `json:"enabled,omitempty"` + TypeID string `json:"type_id,omitempty"` + FlavorID string `json:"flavor_id,omitempty"` + SubnetID string `json:"subnet_id,omitempty"` + AllowRestore bool `json:"allow_restore,omitempty"` + IsMaintenance bool `json:"is_maintenance,omitempty"` + IsProtected bool `json:"is_protected,omitempty"` + Deleted bool `json:"deleted,omitempty"` } // DatastoreBackupsOpts represents update options for the Datastore backups. @@ -127,9 +133,11 @@ type DatastoreBackupsOpts struct { BackupRetentionDays int `json:"backup_retention_days"` } +const DatastoresURI = "/datastores" + // Datastores returns all datastores. func (api *API) Datastores(ctx context.Context, params *DatastoreQueryParams) ([]Datastore, error) { - uri, err := setQueryParams("/datastores", params) + uri, err := setQueryParams(DatastoresURI, params) if err != nil { return []Datastore{}, err } @@ -152,7 +160,7 @@ func (api *API) Datastores(ctx context.Context, params *DatastoreQueryParams) ([ // Datastore returns a datastore based on the ID. func (api *API) Datastore(ctx context.Context, datastoreID string) (Datastore, error) { - uri := fmt.Sprintf("/datastores/%s", datastoreID) + uri := fmt.Sprintf("%s/%s", DatastoresURI, datastoreID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -172,7 +180,6 @@ func (api *API) Datastore(ctx context.Context, datastoreID string) (Datastore, e // CreateDatastore creates a new datastore. func (api *API) CreateDatastore(ctx context.Context, opts DatastoreCreateOpts) (Datastore, error) { - uri := "/datastores" config := convertConfigValues(opts.Config) createDatastoreOpts := struct { Datastore DatastoreCreateOpts `json:"datastore"` @@ -185,7 +192,7 @@ func (api *API) CreateDatastore(ctx context.Context, opts DatastoreCreateOpts) ( return Datastore{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, DatastoresURI, requestBody) if err != nil { return Datastore{}, err } @@ -203,7 +210,7 @@ func (api *API) CreateDatastore(ctx context.Context, opts DatastoreCreateOpts) ( // UpdateDatastore updates an existing datastore. func (api *API) UpdateDatastore(ctx context.Context, datastoreID string, opts DatastoreUpdateOpts) (Datastore, error) { - uri := fmt.Sprintf("/datastores/%s", datastoreID) + uri := fmt.Sprintf("%s/%s", DatastoresURI, datastoreID) updateDatastoreOpts := struct { Datastore DatastoreUpdateOpts `json:"datastore"` }{ @@ -232,7 +239,7 @@ func (api *API) UpdateDatastore(ctx context.Context, datastoreID string, opts Da // DeleteDatastore deletes an existing datastore. func (api *API) DeleteDatastore(ctx context.Context, datastoreID string) error { - uri := fmt.Sprintf("/datastores/%s", datastoreID) + uri := fmt.Sprintf("%s/%s", DatastoresURI, datastoreID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -244,7 +251,7 @@ func (api *API) DeleteDatastore(ctx context.Context, datastoreID string) error { // ResizeDatastore resizes an existing datastore. func (api *API) ResizeDatastore(ctx context.Context, datastoreID string, opts DatastoreResizeOpts) (Datastore, error) { - uri := fmt.Sprintf("/datastores/%s/resize", datastoreID) + uri := fmt.Sprintf("%s/%s/resize", DatastoresURI, datastoreID) resizeDatastoreOpts := struct { Datastore DatastoreResizeOpts `json:"resize"` }{ @@ -273,7 +280,7 @@ func (api *API) ResizeDatastore(ctx context.Context, datastoreID string, opts Da // PoolerDatastore updates pooler parameters of an existing datastore. func (api *API) PoolerDatastore(ctx context.Context, datastoreID string, opts DatastorePoolerOpts) (Datastore, error) { - uri := fmt.Sprintf("/datastores/%s/pooler", datastoreID) + uri := fmt.Sprintf("%s/%s/pooler", DatastoresURI, datastoreID) poolerDatastoreOpts := struct { Datastore DatastorePoolerOpts `json:"pooler"` }{ @@ -302,7 +309,7 @@ func (api *API) PoolerDatastore(ctx context.Context, datastoreID string, opts Da // FirewallDatastore updates firewall rules of an existing datastore. func (api *API) FirewallDatastore(ctx context.Context, datastoreID string, opts DatastoreFirewallOpts) (Datastore, error) { //nolint - uri := fmt.Sprintf("/datastores/%s/firewall", datastoreID) + uri := fmt.Sprintf("%s/%s/firewall", DatastoresURI, datastoreID) firewallDatastoreOpts := struct { Datastore DatastoreFirewallOpts `json:"firewall"` }{ @@ -331,7 +338,7 @@ func (api *API) FirewallDatastore(ctx context.Context, datastoreID string, opts // ConfigDatastore updates configuration parameters rules of an existing datastore. func (api *API) ConfigDatastore(ctx context.Context, datastoreID string, opts DatastoreConfigOpts) (Datastore, error) { //nolint - uri := fmt.Sprintf("/datastores/%s/config", datastoreID) + uri := fmt.Sprintf("%s/%s/config", DatastoresURI, datastoreID) opts.Config = convertConfigValues(opts.Config) requestBody, err := json.Marshal(opts) if err != nil { @@ -356,7 +363,7 @@ func (api *API) ConfigDatastore(ctx context.Context, datastoreID string, opts Da // PasswordDatastore updates password of an existing Redis datastore. func (api *API) PasswordDatastore(ctx context.Context, datastoreID string, opts DatastorePasswordOpts) (Datastore, error) { //nolint - uri := fmt.Sprintf("/datastores/%s/password", datastoreID) + uri := fmt.Sprintf("%s/%s/password", DatastoresURI, datastoreID) passwordDatastoreOpts := struct { Datastore DatastorePasswordOpts `json:"password"` }{ @@ -385,7 +392,7 @@ func (api *API) PasswordDatastore(ctx context.Context, datastoreID string, opts // BackupsDatastore updates backups parameters of an existing datastore. func (api *API) BackupsDatastore(ctx context.Context, datastoreID string, opts DatastoreBackupsOpts) (Datastore, error) { //nolint - uri := fmt.Sprintf("/datastores/%s/backups", datastoreID) + uri := fmt.Sprintf("%s/%s/backups", DatastoresURI, datastoreID) backupsDatastoreOpts := struct { Datastore DatastoreBackupsOpts `json:"backups"` }{ diff --git a/datastore_test.go b/datastore_test.go index df73329..8806bbe 100644 --- a/datastore_test.go +++ b/datastore_test.go @@ -3,18 +3,20 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const testDatastoreNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "database 123 not found." + "message": "database %s not found." } }` @@ -606,14 +608,13 @@ func TestDatastores(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastores", + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoresURI, httpmock.NewStringResponder(200, testDatastoresResponse)) actual, err := testClient.Datastores(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, datastoreListExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreListExpected, actual) } func TestDatastore(t *testing.T) { @@ -621,7 +622,7 @@ func TestDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastores/"+datastoreID, + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoresURI+"/"+datastoreID, httpmock.NewStringResponder(200, testDatastoreResponse)) expected := Datastore{ @@ -662,9 +663,8 @@ func TestDatastore(t *testing.T) { actual, err := testClient.Datastore(context.Background(), datastoreID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestMultiNodeDatastore(t *testing.T) { @@ -672,7 +672,7 @@ func TestMultiNodeDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastores/"+datastoreID, + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoresURI+"/"+datastoreID, httpmock.NewStringResponder(200, testMultiNodeDatastoreResponse)) expected := Datastore{ @@ -729,9 +729,8 @@ func TestMultiNodeDatastore(t *testing.T) { actual, err := testClient.Datastore(context.Background(), datastoreID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestDatastoreNotFound(t *testing.T) { @@ -739,17 +738,18 @@ func TestDatastoreNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastores/123", - httpmock.NewStringResponder(404, testDatastoreNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testDatastoreNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoresURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "datastore 123 not found." + expected.APIError.Message = fmt.Sprintf("datastore %s not found.", NotFoundEntityID) - _, err := testClient.Datastore(context.Background(), "123") + _, err := testClient.Datastore(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateDatastore(t *testing.T) { @@ -757,7 +757,7 @@ func TestCreateDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/datastores", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatastoresURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -783,9 +783,8 @@ func TestCreateDatastore(t *testing.T) { actual, err := testClient.CreateDatastore(context.Background(), createDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreCreateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreCreateExpected, actual) } func TestCreateDatatastoreInvalidTypeID(t *testing.T) { @@ -793,7 +792,7 @@ func TestCreateDatatastoreInvalidTypeID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/datastores", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatastoresURI, httpmock.NewStringResponder(400, testCreateDatastoreInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -812,7 +811,7 @@ func TestCreateDatatastoreInvalidTypeID(t *testing.T) { _, err := testClient.CreateDatastore(context.Background(), createDatastoreOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestUpdateDatastore(t *testing.T) { @@ -820,7 +819,7 @@ func TestUpdateDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -842,9 +841,8 @@ func TestUpdateDatastore(t *testing.T) { actual, err := testClient.UpdateDatastore(context.Background(), datastoreID, updateDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreUpdateExpected, actual) } func TestUpdateDatatastoreInvalidName(t *testing.T) { @@ -852,7 +850,7 @@ func TestUpdateDatatastoreInvalidName(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID, httpmock.NewStringResponder(400, testUpdateDatastoreInvalidName)) expected := &DBaaSAPIError{} @@ -866,7 +864,7 @@ func TestUpdateDatatastoreInvalidName(t *testing.T) { _, err := testClient.UpdateDatastore(context.Background(), datastoreID, updateDatastoreOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestResizeDatastore(t *testing.T) { @@ -874,7 +872,7 @@ func TestResizeDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/datastores/"+datastoreID+"/resize", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/resize", func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreResizeOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -897,9 +895,8 @@ func TestResizeDatastore(t *testing.T) { actual, err := testClient.ResizeDatastore(context.Background(), datastoreID, resizeDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreResizeExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreResizeExpected, actual) } func TestResizeDatatastoreInvalidNodeCount(t *testing.T) { @@ -907,7 +904,7 @@ func TestResizeDatatastoreInvalidNodeCount(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/datastores/"+datastoreID+"/resize", + httpmock.RegisterResponder("POST", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/resize", httpmock.NewStringResponder(400, testResizeDatastoreInvalidNodeCount)) expected := &DBaaSAPIError{} @@ -921,7 +918,7 @@ func TestResizeDatatastoreInvalidNodeCount(t *testing.T) { _, err := testClient.ResizeDatastore(context.Background(), datastoreID, resizeDatastoreOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestPoolerDatastore(t *testing.T) { @@ -929,7 +926,7 @@ func TestPoolerDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/pooler", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/pooler", func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastorePoolerOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -952,9 +949,8 @@ func TestPoolerDatastore(t *testing.T) { actual, err := testClient.PoolerDatastore(context.Background(), datastoreID, poolerDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreUpdateExpected, actual) } func TestPoolerDatatastoreInvalidMode(t *testing.T) { @@ -962,7 +958,7 @@ func TestPoolerDatatastoreInvalidMode(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/pooler", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/pooler", httpmock.NewStringResponder(400, testPoolerDatastoreInvalidMode)) expected := &DBaaSAPIError{} @@ -978,7 +974,7 @@ func TestPoolerDatatastoreInvalidMode(t *testing.T) { _, err := testClient.PoolerDatastore(context.Background(), datastoreID, poolerDatastoreOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestFirewallDatastore(t *testing.T) { @@ -986,7 +982,7 @@ func TestFirewallDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/firewall", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/firewall", func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreFirewallOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -1008,9 +1004,8 @@ func TestFirewallDatastore(t *testing.T) { actual, err := testClient.FirewallDatastore(context.Background(), datastoreID, firewallDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreUpdateExpected, actual) } func TestConfigDatastore(t *testing.T) { @@ -1018,7 +1013,7 @@ func TestConfigDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/config", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/config", func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreConfigOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -1043,9 +1038,8 @@ func TestConfigDatastore(t *testing.T) { actual, err := testClient.ConfigDatastore(context.Background(), datastoreID, configDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreUpdateConfigExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreUpdateConfigExpected, actual) } func TestPasswordDatastore(t *testing.T) { @@ -1053,7 +1047,7 @@ func TestPasswordDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/password", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/password", func(req *http.Request) (*http.Response, error) { tempPasswordOpts := struct { Password DatastorePasswordOpts `json:"password"` @@ -1080,9 +1074,8 @@ func TestPasswordDatastore(t *testing.T) { actual, err := testClient.PasswordDatastore(context.Background(), datastoreID, passwordDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, datastoreUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, datastoreUpdateExpected, actual) } func TestBackupsDatastore(t *testing.T) { @@ -1090,7 +1083,7 @@ func TestBackupsDatastore(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/datastores/"+datastoreID+"/backups", + httpmock.RegisterResponder("PUT", testClient.Endpoint+DatastoresURI+"/"+datastoreID+"/backups", func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&DatastoreBackupsOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -1111,8 +1104,7 @@ func TestBackupsDatastore(t *testing.T) { } actual, err := testClient.BackupsDatastore(context.Background(), datastoreID, backupsDatastoreOpts) - if assert.NoError(t, err) { - assert.Equal(t, httpmock.GetTotalCallCount(), 1) - assert.Equal(t, datastoreUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, 1, httpmock.GetTotalCallCount()) + assert.Equal(t, datastoreUpdateExpected, actual) } diff --git a/datastore_type.go b/datastore_type.go index 5349d41..d2fc775 100644 --- a/datastore_type.go +++ b/datastore_type.go @@ -14,11 +14,11 @@ type DatastoreType struct { Version string `json:"version"` } +const DatastoreTypesURI = "/datastore-types" + // DatastoreTypes returns all datastore types. func (api *API) DatastoreTypes(ctx context.Context) ([]DatastoreType, error) { - uri := "/datastore-types" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, DatastoreTypesURI, nil) if err != nil { return []DatastoreType{}, err } @@ -36,7 +36,7 @@ func (api *API) DatastoreTypes(ctx context.Context) ([]DatastoreType, error) { // DatastoreType returns a datastore type based on the ID. func (api *API) DatastoreType(ctx context.Context, datastoreTypeID string) (DatastoreType, error) { - uri := fmt.Sprintf("/datastore-types/%s", datastoreTypeID) + uri := fmt.Sprintf("%s/%s", DatastoreTypesURI, datastoreTypeID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { diff --git a/datastore_type_test.go b/datastore_type_test.go index d68435f..36af64f 100644 --- a/datastore_type_test.go +++ b/datastore_type_test.go @@ -2,10 +2,12 @@ package dbaas import ( "context" + "fmt" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const datastoreTypeID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -14,7 +16,7 @@ const testDatastoreTypeNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "datastoretype 123 not found." + "message": "datastoretype %s not found." } }` @@ -46,7 +48,7 @@ func TestDatastoreTypes(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastore-types", + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoreTypesURI, httpmock.NewStringResponder(200, testDatastoreTypesResponse)) expected := []DatastoreType{ @@ -64,9 +66,8 @@ func TestDatastoreTypes(t *testing.T) { actual, err := testClient.DatastoreTypes(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestDatastoreType(t *testing.T) { @@ -74,7 +75,7 @@ func TestDatastoreType(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastore-types/"+datastoreTypeID, + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoreTypesURI+"/"+datastoreTypeID, httpmock.NewStringResponder(200, testDatastoreTypeResponse)) expected := DatastoreType{ @@ -85,9 +86,8 @@ func TestDatastoreType(t *testing.T) { actual, err := testClient.DatastoreType(context.Background(), datastoreTypeID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestDatastoreTypeNotFound(t *testing.T) { @@ -95,15 +95,16 @@ func TestDatastoreTypeNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/datastore-types/123", - httpmock.NewStringResponder(404, testDatastoreTypeNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testDatastoreTypeNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+DatastoreTypesURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "datastoretype 123 not found." + expected.APIError.Message = fmt.Sprintf("datastoretype %s not found.", NotFoundEntityID) - _, err := testClient.DatastoreType(context.Background(), "123") + _, err := testClient.DatastoreType(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/dbaas.go b/dbaas.go index 685747d..4a62c9b 100644 --- a/dbaas.go +++ b/dbaas.go @@ -247,9 +247,8 @@ func convertFieldFromStringToType(fieldValue string) interface{} { return val } else if val, err := strconv.ParseBool(fieldValue); err == nil { return val - } else { - return fieldValue } + return fieldValue } // convertConfigValues convert config map values to the corresponding types. diff --git a/extension.go b/extension.go index c939d45..ebadeb9 100644 --- a/extension.go +++ b/extension.go @@ -10,6 +10,7 @@ import ( // Extension is the API response for the extension. type Extension struct { ID string `json:"id"` + ProjectID string `json:"project_id"` AvailableExtensionID string `json:"available_extension_id"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` @@ -28,15 +29,18 @@ type ExtensionCreateOpts struct { // ExtensionQueryParams represents available query parameters for extension. type ExtensionQueryParams struct { ID string `json:"id,omitempty"` + ProjectID string `json:"project_id,omitempty"` AvailableExtensionID string `json:"available_extension_id,omitempty"` DatastoreID string `json:"datastore_id,omitempty"` DatabaseID string `json:"database_id,omitempty"` Status Status `json:"status,omitempty"` } +const ExtensionsURI = "/extensions" + // Extensions returns all extensions. func (api *API) Extensions(ctx context.Context, params *ExtensionQueryParams) ([]Extension, error) { - uri, err := setQueryParams("/extensions", params) + uri, err := setQueryParams(ExtensionsURI, params) if err != nil { return []Extension{}, err } @@ -59,7 +63,7 @@ func (api *API) Extensions(ctx context.Context, params *ExtensionQueryParams) ([ // Extension returns a extension based on the ID. func (api *API) Extension(ctx context.Context, extensionID string) (Extension, error) { - uri := fmt.Sprintf("/extensions/%s", extensionID) + uri := fmt.Sprintf("%s/%s", ExtensionsURI, extensionID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -79,7 +83,6 @@ func (api *API) Extension(ctx context.Context, extensionID string) (Extension, e // CreateExtension creates a new extension. func (api *API) CreateExtension(ctx context.Context, opts ExtensionCreateOpts) (Extension, error) { - uri := "/extensions" createExtensionOpts := struct { Extension ExtensionCreateOpts `json:"extension"` }{ @@ -90,7 +93,7 @@ func (api *API) CreateExtension(ctx context.Context, opts ExtensionCreateOpts) ( return Extension{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, ExtensionsURI, requestBody) if err != nil { return Extension{}, err } @@ -108,7 +111,7 @@ func (api *API) CreateExtension(ctx context.Context, opts ExtensionCreateOpts) ( // DeleteExtension deletes an existing extension. func (api *API) DeleteExtension(ctx context.Context, extensionID string) error { - uri := fmt.Sprintf("/extensions/%s", extensionID) + uri := fmt.Sprintf("%s/%s", ExtensionsURI, extensionID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/extension_test.go b/extension_test.go index 51322ed..42adb43 100644 --- a/extension_test.go +++ b/extension_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const extensionID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testExtensionNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "extension 123 not found." + "message": "extension %s not found." } }` @@ -70,7 +72,7 @@ func TestExtensions(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/extensions", + httpmock.RegisterResponder("GET", testClient.Endpoint+ExtensionsURI, httpmock.NewStringResponder(200, testExtensionsResponse)) expected := []Extension{ @@ -96,9 +98,8 @@ func TestExtensions(t *testing.T) { actual, err := testClient.Extensions(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestExtension(t *testing.T) { @@ -106,7 +107,7 @@ func TestExtension(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/extensions/"+extensionID, + httpmock.RegisterResponder("GET", testClient.Endpoint+ExtensionsURI+"/"+extensionID, httpmock.NewStringResponder(200, testExtensionResponse)) expected := Extension{ @@ -121,9 +122,8 @@ func TestExtension(t *testing.T) { actual, err := testClient.Extension(context.Background(), extensionID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestExtensionNotFound(t *testing.T) { @@ -131,17 +131,18 @@ func TestExtensionNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/extensions/123", - httpmock.NewStringResponder(404, testExtensionNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testExtensionNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+ExtensionsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "extension 123 not found." + expected.APIError.Message = fmt.Sprintf("extension %s not found.", NotFoundEntityID) - _, err := testClient.Extension(context.Background(), "123") + _, err := testClient.Extension(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateExtension(t *testing.T) { @@ -149,7 +150,7 @@ func TestCreateExtension(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/extensions", + httpmock.RegisterResponder("POST", testClient.Endpoint+ExtensionsURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&ExtensionCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -190,9 +191,8 @@ func TestCreateExtension(t *testing.T) { actual, err := testClient.CreateExtension(context.Background(), createExtensionOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestCreateExtensionInvalidDatastoreID(t *testing.T) { @@ -200,7 +200,7 @@ func TestCreateExtensionInvalidDatastoreID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/extensions", + httpmock.RegisterResponder("POST", testClient.Endpoint+ExtensionsURI, httpmock.NewStringResponder(400, testCreateExtensionInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -217,5 +217,5 @@ func TestCreateExtensionInvalidDatastoreID(t *testing.T) { _, err := testClient.CreateExtension(context.Background(), createExtensionOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/flavor.go b/flavor.go index 631ce24..15a5e3a 100644 --- a/flavor.go +++ b/flavor.go @@ -18,11 +18,11 @@ type FlavorResponse struct { Disk int `json:"disk"` } +const FlavorsURI = "/flavors" + // Flavors returns all flavors. func (api *API) Flavors(ctx context.Context) ([]FlavorResponse, error) { - uri := "/flavors" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, FlavorsURI, nil) if err != nil { return []FlavorResponse{}, err } @@ -40,7 +40,7 @@ func (api *API) Flavors(ctx context.Context) ([]FlavorResponse, error) { // Flavor returns a flavor based on the ID. func (api *API) Flavor(ctx context.Context, flavorID string) (FlavorResponse, error) { - uri := fmt.Sprintf("/flavors/%s", flavorID) + uri := fmt.Sprintf("%s/%s", FlavorsURI, flavorID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { diff --git a/flavor_test.go b/flavor_test.go index 489f274..0669736 100644 --- a/flavor_test.go +++ b/flavor_test.go @@ -2,10 +2,12 @@ package dbaas import ( "context" + "fmt" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const flavorID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -14,7 +16,7 @@ const testFlavorNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "flavor 123 not found." + "message": "flavor %s not found." } }` @@ -67,7 +69,7 @@ func TestFlavors(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/flavors", + httpmock.RegisterResponder("GET", testClient.Endpoint+FlavorsURI, httpmock.NewStringResponder(200, testFlavorsResponse)) expected := []FlavorResponse{ @@ -99,9 +101,8 @@ func TestFlavors(t *testing.T) { actual, err := testClient.Flavors(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestFlavor(t *testing.T) { @@ -109,7 +110,7 @@ func TestFlavor(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/flavors/"+flavorID, + httpmock.RegisterResponder("GET", testClient.Endpoint+FlavorsURI+"/"+flavorID, httpmock.NewStringResponder(200, testFlavorResponse)) expected := FlavorResponse{ @@ -127,9 +128,8 @@ func TestFlavor(t *testing.T) { actual, err := testClient.Flavor(context.Background(), flavorID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestFlavorNotFound(t *testing.T) { @@ -137,15 +137,16 @@ func TestFlavorNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/flavors/123", - httpmock.NewStringResponder(404, testFlavorNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testFlavorNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+FlavorsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "flavor 123 not found." + expected.APIError.Message = fmt.Sprintf("flavor %s not found.", NotFoundEntityID) - _, err := testClient.Flavor(context.Background(), "123") + _, err := testClient.Flavor(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/grant.go b/grant.go index 741c5b2..c4ba44a 100644 --- a/grant.go +++ b/grant.go @@ -26,9 +26,11 @@ type Grant struct { Status Status `json:"status"` } +const GrantsURI = "/grants" + // Grant returns a grant based on the ID. func (api *API) Grant(ctx context.Context, grantID string) (Grant, error) { - uri := fmt.Sprintf("/grants/%s", grantID) + uri := fmt.Sprintf("%s/%s", GrantsURI, grantID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -48,9 +50,7 @@ func (api *API) Grant(ctx context.Context, grantID string) (Grant, error) { // Grants returns all grants. func (api *API) Grants(ctx context.Context) ([]Grant, error) { - uri := "/grants" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, GrantsURI, nil) if err != nil { return []Grant{}, err } @@ -68,7 +68,6 @@ func (api *API) Grants(ctx context.Context) ([]Grant, error) { // CreateGrant creates a new grant. func (api *API) CreateGrant(ctx context.Context, opts GrantCreateOpts) (Grant, error) { - uri := "/grants" createGrantOpts := struct { Grant GrantCreateOpts `json:"grant"` }{ @@ -79,7 +78,7 @@ func (api *API) CreateGrant(ctx context.Context, opts GrantCreateOpts) (Grant, e return Grant{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, GrantsURI, requestBody) if err != nil { return Grant{}, err } @@ -97,7 +96,7 @@ func (api *API) CreateGrant(ctx context.Context, opts GrantCreateOpts) (Grant, e // DeleteGrant deletes an existing grant. func (api *API) DeleteGrant(ctx context.Context, grantID string) error { - uri := fmt.Sprintf("/grants/%s", grantID) + uri := fmt.Sprintf("%s/%s", GrantsURI, grantID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/grant_test.go b/grant_test.go index f096e57..71c2f5c 100644 --- a/grant_test.go +++ b/grant_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const grantID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testGrantNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "grant 123 not found." + "message": "grant %s not found." } }` @@ -65,7 +67,7 @@ func TestGrants(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/grants", + httpmock.RegisterResponder("GET", testClient.Endpoint+GrantsURI, httpmock.NewStringResponder(200, testGrantsResponse)) expected := []Grant{ @@ -93,9 +95,8 @@ func TestGrants(t *testing.T) { actual, err := testClient.Grants(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestGrant(t *testing.T) { @@ -103,7 +104,7 @@ func TestGrant(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/grants/"+grantID, + httpmock.RegisterResponder("GET", testClient.Endpoint+GrantsURI+"/"+grantID, httpmock.NewStringResponder(200, testGrantResponse)) expected := Grant{ @@ -119,9 +120,8 @@ func TestGrant(t *testing.T) { actual, err := testClient.Grant(context.Background(), grantID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestGrantNotFound(t *testing.T) { @@ -129,17 +129,18 @@ func TestGrantNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/grants/123", - httpmock.NewStringResponder(404, testGrantNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testGrantNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+GrantsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "grant 123 not found." + expected.APIError.Message = fmt.Sprintf("grant %s not found.", NotFoundEntityID) - _, err := testClient.Grant(context.Background(), "123") + _, err := testClient.Grant(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateGrant(t *testing.T) { @@ -147,7 +148,7 @@ func TestCreateGrant(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/grants", + httpmock.RegisterResponder("POST", testClient.Endpoint+GrantsURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&GrantCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -192,7 +193,6 @@ func TestCreateGrant(t *testing.T) { actual, err := testClient.CreateGrant(context.Background(), createGrantOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } diff --git a/logical_replication_slot.go b/logical_replication_slot.go index 6cf4c1e..3f05975 100644 --- a/logical_replication_slot.go +++ b/logical_replication_slot.go @@ -27,18 +27,21 @@ type LogicalReplicationSlotCreateOpts struct { type LogicalReplicationSlotQueryParams struct { ID string `json:"id,omitempty"` + ProjectID string `json:"project_id,omitempty"` Name string `json:"name,omitempty"` DatastoreID string `json:"datastore_id,omitempty"` DatabaseID string `json:"database_id,omitempty"` Status Status `json:"status,omitempty"` } +const LogicalReplicationSlotsURI = "/logical-replication-slots" + // LogicalReplicationSlots returns all slots. func (api *API) LogicalReplicationSlots( ctx context.Context, params *LogicalReplicationSlotQueryParams, ) ([]LogicalReplicationSlot, error) { - uri, err := setQueryParams("/logical-replication-slots", params) + uri, err := setQueryParams(LogicalReplicationSlotsURI, params) if err != nil { return []LogicalReplicationSlot{}, err } @@ -61,7 +64,7 @@ func (api *API) LogicalReplicationSlots( // LogicalReplicationSlot returns a slot based on the ID. func (api *API) LogicalReplicationSlot(ctx context.Context, slotID string) (LogicalReplicationSlot, error) { - uri := fmt.Sprintf("/logical-replication-slots/%s", slotID) + uri := fmt.Sprintf("%s/%s", LogicalReplicationSlotsURI, slotID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -84,7 +87,6 @@ func (api *API) CreateLogicalReplicationSlot( ctx context.Context, opts LogicalReplicationSlotCreateOpts, ) (LogicalReplicationSlot, error) { - uri := "/logical-replication-slots" createLogicalReplicationSlotsOpts := struct { LogicalReplicationSlot LogicalReplicationSlotCreateOpts `json:"logical-replication-slot"` }{ @@ -95,7 +97,7 @@ func (api *API) CreateLogicalReplicationSlot( return LogicalReplicationSlot{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, LogicalReplicationSlotsURI, requestBody) if err != nil { return LogicalReplicationSlot{}, err } @@ -112,7 +114,7 @@ func (api *API) CreateLogicalReplicationSlot( // DeleteLogicalReplicationSlot deletes an existing slot. func (api *API) DeleteLogicalReplicationSlot(ctx context.Context, slotID string) error { - uri := fmt.Sprintf("/logical-replication-slots/%s", slotID) + uri := fmt.Sprintf("%s/%s", LogicalReplicationSlotsURI, slotID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/logical_replication_slot_test.go b/logical_replication_slot_test.go index 3222c2d..8c8e8a0 100644 --- a/logical_replication_slot_test.go +++ b/logical_replication_slot_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const slotID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testLogicalReplicationSlotNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "logicalreplicationslot 123 not found." + "message": "logicalreplicationslot %s not found." } }` @@ -65,7 +67,7 @@ func TestLogicalReplicationSlots(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/logical-replication-slots", + httpmock.RegisterResponder("GET", testClient.Endpoint+LogicalReplicationSlotsURI, httpmock.NewStringResponder(200, testLogicalReplicationSlotsResponse)) expected := []LogicalReplicationSlot{ @@ -93,9 +95,8 @@ func TestLogicalReplicationSlots(t *testing.T) { actual, err := testClient.LogicalReplicationSlots(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestLogicalReplicationSlot(t *testing.T) { @@ -103,7 +104,7 @@ func TestLogicalReplicationSlot(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/logical-replication-slots/"+slotID, + httpmock.RegisterResponder("GET", testClient.Endpoint+LogicalReplicationSlotsURI+"/"+slotID, httpmock.NewStringResponder(200, testLogicalReplicationSlotResponse)) expected := LogicalReplicationSlot{ @@ -119,9 +120,8 @@ func TestLogicalReplicationSlot(t *testing.T) { actual, err := testClient.LogicalReplicationSlot(context.Background(), slotID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestLogicalReplicationSlotNotFound(t *testing.T) { @@ -129,17 +129,18 @@ func TestLogicalReplicationSlotNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/logical-replication-slots/123", - httpmock.NewStringResponder(404, testLogicalReplicationSlotNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testLogicalReplicationSlotNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+LogicalReplicationSlotsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "logicalreplicationslot 123 not found." + expected.APIError.Message = fmt.Sprintf("logicalreplicationslot %s not found.", NotFoundEntityID) - _, err := testClient.LogicalReplicationSlot(context.Background(), "123") + _, err := testClient.LogicalReplicationSlot(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateLogicalReplicationSlot(t *testing.T) { @@ -158,7 +159,7 @@ func TestCreateLogicalReplicationSlot(t *testing.T) { Status: StatusPendingCreate, } - httpmock.RegisterResponder("POST", testClient.Endpoint+"/logical-replication-slots", + httpmock.RegisterResponder("POST", testClient.Endpoint+LogicalReplicationSlotsURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&LogicalReplicationSlotCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -183,7 +184,6 @@ func TestCreateLogicalReplicationSlot(t *testing.T) { actual, err := testClient.CreateLogicalReplicationSlot(context.Background(), createLogicalReplicationSlotOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } diff --git a/prometheus_metrics_token.go b/prometheus_metrics_token.go index c65b801..9da3695 100644 --- a/prometheus_metrics_token.go +++ b/prometheus_metrics_token.go @@ -27,12 +27,14 @@ type PrometheusMetricToken struct { Value string `json:"value"` } +const PrometheusMetricsTokensURI = "prometheus-metrics-tokens" + // PrometheusMetricToken returns a token based on the ID. func (api *API) PrometheusMetricToken( ctx context.Context, prometheusMetricTokenID string, ) (PrometheusMetricToken, error) { - uri := fmt.Sprintf("/prometheus-metrics-tokens/%s", prometheusMetricTokenID) + uri := fmt.Sprintf("%s/%s", PrometheusMetricsTokensURI, prometheusMetricTokenID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -50,9 +52,7 @@ func (api *API) PrometheusMetricToken( // PrometheusMetricTokens returns all tokens. func (api *API) PrometheusMetricTokens(ctx context.Context) ([]PrometheusMetricToken, error) { - uri := "/prometheus-metrics-tokens" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, PrometheusMetricsTokensURI, nil) if err != nil { return []PrometheusMetricToken{}, err } @@ -73,7 +73,6 @@ func (api *API) CreatePrometheusMetricToken( ctx context.Context, opts PrometheusMetricTokenCreateOpts, ) (PrometheusMetricToken, error) { - uri := "/prometheus-metrics-tokens" createPrometheusMetricTokensOpts := struct { PrometheusMetricToken PrometheusMetricTokenCreateOpts `json:"prometheus-metrics-token"` }{ @@ -84,7 +83,7 @@ func (api *API) CreatePrometheusMetricToken( return PrometheusMetricToken{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, PrometheusMetricsTokensURI, requestBody) if err != nil { return PrometheusMetricToken{}, err } @@ -102,7 +101,7 @@ func (api *API) CreatePrometheusMetricToken( // DeletePrometheusMetricToken deletes an existing token. func (api *API) DeletePrometheusMetricToken(ctx context.Context, prometheusMetricTokenID string) error { - uri := fmt.Sprintf("/prometheus-metrics-tokens/%s", prometheusMetricTokenID) + uri := fmt.Sprintf("%s/%s", PrometheusMetricsTokensURI, prometheusMetricTokenID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -118,7 +117,7 @@ func (api *API) UpdatePrometheusMetricToken( prometheusMetricTokenID string, opts PrometheusMetricTokenUpdateOpts, ) (PrometheusMetricToken, error) { - uri := fmt.Sprintf("/prometheus-metrics-tokens/%s", prometheusMetricTokenID) + uri := fmt.Sprintf("%s/%s", PrometheusMetricsTokensURI, prometheusMetricTokenID) updatePrometheusMetricTokensOpts := struct { PrometheusMetricToken PrometheusMetricTokenUpdateOpts `json:"prometheus-metrics-token"` }{ diff --git a/prometheus_metrics_token_test.go b/prometheus_metrics_token_test.go index 904ec8b..19fc3e2 100644 --- a/prometheus_metrics_token_test.go +++ b/prometheus_metrics_token_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const prometheusMetricTokenID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testPrometheusMetricTokenNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "prometheusmetrictoken 123 not found." + "message": "prometheusmetrictoken %s not found." } }` @@ -55,7 +57,7 @@ func TestPrometheusMetricTokens(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/prometheus-metrics-tokens", + httpmock.RegisterResponder("GET", testClient.Endpoint+PrometheusMetricsTokensURI, httpmock.NewStringResponder(200, testPrometheusMetricTokensResponse)) expected := []PrometheusMetricToken{ @@ -79,9 +81,8 @@ func TestPrometheusMetricTokens(t *testing.T) { actual, err := testClient.PrometheusMetricTokens(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestPrometheusMetricToken(t *testing.T) { @@ -89,7 +90,7 @@ func TestPrometheusMetricToken(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/prometheus-metrics-tokens/"+prometheusMetricTokenID, + httpmock.RegisterResponder("GET", testClient.Endpoint+PrometheusMetricsTokensURI+"/"+prometheusMetricTokenID, httpmock.NewStringResponder(200, testPrometheusMetricTokenResponse)) expected := PrometheusMetricToken{ @@ -103,9 +104,8 @@ func TestPrometheusMetricToken(t *testing.T) { actual, err := testClient.PrometheusMetricToken(context.Background(), prometheusMetricTokenID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestPrometheusMetricTokenNotFound(t *testing.T) { @@ -113,17 +113,18 @@ func TestPrometheusMetricTokenNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/prometheus-metrics-tokens/123", - httpmock.NewStringResponder(404, testPrometheusMetricTokenNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testPrometheusMetricTokenNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+PrometheusMetricsTokensURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "prometheusmetrictoken 123 not found." + expected.APIError.Message = fmt.Sprintf("prometheusmetrictoken %s not found.", NotFoundEntityID) - _, err := testClient.PrometheusMetricToken(context.Background(), "123") + _, err := testClient.PrometheusMetricToken(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreatePrometheusMetricToken(t *testing.T) { @@ -131,7 +132,7 @@ func TestCreatePrometheusMetricToken(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/prometheus-metrics-tokens", + httpmock.RegisterResponder("POST", testClient.Endpoint+PrometheusMetricsTokensURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&PrometheusMetricTokenCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -170,9 +171,8 @@ func TestCreatePrometheusMetricToken(t *testing.T) { actual, err := testClient.CreatePrometheusMetricToken(context.Background(), createPrometheusMetricTokenOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUpdatePrometheusMetricToken(t *testing.T) { @@ -180,7 +180,7 @@ func TestUpdatePrometheusMetricToken(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/prometheus-metrics-tokens/"+prometheusMetricTokenID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+PrometheusMetricsTokensURI+"/"+prometheusMetricTokenID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&PrometheusMetricTokenUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -222,7 +222,6 @@ func TestUpdatePrometheusMetricToken(t *testing.T) { updatePrometheusMetricTokenOpts, ) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } diff --git a/test.go b/test.go new file mode 100644 index 0000000..67fb054 --- /dev/null +++ b/test.go @@ -0,0 +1,3 @@ +package dbaas + +const NotFoundEntityID = "0721fd40-77e9-4012-8f4d-6bb3bd9ea1fa" diff --git a/topic.go b/topic.go index 11d4bb3..f932a4f 100644 --- a/topic.go +++ b/topic.go @@ -40,9 +40,11 @@ type TopicQueryParams struct { Status Status `json:"status,omitempty"` } +const TopicsURI = "/topics" + // Topics returns all topics. func (api *API) Topics(ctx context.Context, params *TopicQueryParams) ([]Topic, error) { - uri, err := setQueryParams("/topics", params) + uri, err := setQueryParams(TopicsURI, params) if err != nil { return []Topic{}, err } @@ -65,7 +67,7 @@ func (api *API) Topics(ctx context.Context, params *TopicQueryParams) ([]Topic, // Topic returns a topic based on the ID. func (api *API) Topic(ctx context.Context, topicID string) (Topic, error) { - uri := fmt.Sprintf("/topics/%s", topicID) + uri := fmt.Sprintf("%s/%s", TopicsURI, topicID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -85,7 +87,6 @@ func (api *API) Topic(ctx context.Context, topicID string) (Topic, error) { // CreateTopic creates a new topic. func (api *API) CreateTopic(ctx context.Context, opts TopicCreateOpts) (Topic, error) { - uri := "/topics" createTopicOpts := struct { Topic TopicCreateOpts `json:"topic"` }{ @@ -96,7 +97,7 @@ func (api *API) CreateTopic(ctx context.Context, opts TopicCreateOpts) (Topic, e return Topic{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, TopicsURI, requestBody) if err != nil { return Topic{}, err } @@ -114,7 +115,7 @@ func (api *API) CreateTopic(ctx context.Context, opts TopicCreateOpts) (Topic, e // UpdateTopic updates an existing topic. func (api *API) UpdateTopic(ctx context.Context, topicID string, opts TopicUpdateOpts) (Topic, error) { - uri := fmt.Sprintf("/topics/%s", topicID) + uri := fmt.Sprintf("%s/%s", TopicsURI, topicID) updateTopicOpts := struct { Topic TopicUpdateOpts `json:"topic"` }{ @@ -143,7 +144,7 @@ func (api *API) UpdateTopic(ctx context.Context, topicID string, opts TopicUpdat // DeleteTopic deletes an existing topic. func (api *API) DeleteTopic(ctx context.Context, topicID string) error { - uri := fmt.Sprintf("/topics/%s", topicID) + uri := fmt.Sprintf("%s/%s", TopicsURI, topicID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/topic_test.go b/topic_test.go index 41b94d7..e7707f1 100644 --- a/topic_test.go +++ b/topic_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const topicID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testTopicNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "topic 123 not found." + "message": "topic %s not found." } }` @@ -104,7 +106,7 @@ func TestTopics(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/topics", + httpmock.RegisterResponder("GET", testClient.Endpoint+TopicsURI, httpmock.NewStringResponder(200, testTopicsResponse)) expected := []Topic{ @@ -132,9 +134,8 @@ func TestTopics(t *testing.T) { actual, err := testClient.Topics(context.Background(), nil) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestTopic(t *testing.T) { @@ -142,14 +143,13 @@ func TestTopic(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/topics/"+topicID, + httpmock.RegisterResponder("GET", testClient.Endpoint+TopicsURI+"/"+topicID, httpmock.NewStringResponder(200, testTopicResponse)) actual, err := testClient.Topic(context.Background(), topicID) - if assert.NoError(t, err) { - assert.Equal(t, TopicExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, TopicExpected, actual) } func TestTopicNotFound(t *testing.T) { @@ -157,17 +157,18 @@ func TestTopicNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/topics/123", - httpmock.NewStringResponder(404, testTopicNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testTopicNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+TopicsURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "topic 123 not found." + expected.APIError.Message = fmt.Sprintf("topic %s not found.", NotFoundEntityID) - _, err := testClient.Topic(context.Background(), "123") + _, err := testClient.Topic(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateToopic(t *testing.T) { @@ -175,7 +176,7 @@ func TestCreateToopic(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/topics", + httpmock.RegisterResponder("POST", testClient.Endpoint+TopicsURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&TopicCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -204,9 +205,8 @@ func TestCreateToopic(t *testing.T) { TopicCreateExpexted := TopicExpected TopicCreateExpexted.Status = StatusPendingCreate - if assert.NoError(t, err) { - assert.Equal(t, TopicExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, TopicExpected, actual) } func TestCreateTopicInvalidDatastoreID(t *testing.T) { @@ -214,7 +214,7 @@ func TestCreateTopicInvalidDatastoreID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/topics", + httpmock.RegisterResponder("POST", testClient.Endpoint+TopicsURI, httpmock.NewStringResponder(400, testCreateTopicInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -231,7 +231,7 @@ func TestCreateTopicInvalidDatastoreID(t *testing.T) { _, err := testClient.CreateTopic(context.Background(), createTopicOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestUpdateTopic(t *testing.T) { @@ -239,7 +239,7 @@ func TestUpdateTopic(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/topics/"+topicID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+TopicsURI+"/"+topicID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&TopicUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -266,9 +266,8 @@ func TestUpdateTopic(t *testing.T) { TopicUpdateExpected := TopicExpected TopicUpdateExpected.Status = StatusPendingUpdate - if assert.NoError(t, err) { - assert.Equal(t, TopicUpdateExpected, actual) - } + require.NoError(t, err) + assert.Equal(t, TopicUpdateExpected, actual) } func TestUpdateTopicInvalidPartitions(t *testing.T) { @@ -276,7 +275,7 @@ func TestUpdateTopicInvalidPartitions(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/topics/"+topicID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+TopicsURI+"/"+topicID, httpmock.NewStringResponder(400, testUpdateTopicInvalidPartitionsResponse)) expected := &DBaaSAPIError{} @@ -291,5 +290,5 @@ func TestUpdateTopicInvalidPartitions(t *testing.T) { _, err := testClient.UpdateTopic(context.Background(), topicID, updateTopicOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } diff --git a/user.go b/user.go index 29fee1b..d59becc 100644 --- a/user.go +++ b/user.go @@ -30,9 +30,11 @@ type User struct { Status Status `json:"status"` } +const UsersURI = "/users" + // User returns a user based on the ID. func (api *API) User(ctx context.Context, userID string) (User, error) { - uri := fmt.Sprintf("/users/%s", userID) + uri := fmt.Sprintf("%s/%s", UsersURI, userID) resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) if err != nil { @@ -52,9 +54,7 @@ func (api *API) User(ctx context.Context, userID string) (User, error) { // Users returns all users. func (api *API) Users(ctx context.Context) ([]User, error) { - uri := "/users" - - resp, err := api.makeRequest(ctx, http.MethodGet, uri, nil) + resp, err := api.makeRequest(ctx, http.MethodGet, UsersURI, nil) if err != nil { return []User{}, err } @@ -72,7 +72,6 @@ func (api *API) Users(ctx context.Context) ([]User, error) { // CreateUser creates a new user. func (api *API) CreateUser(ctx context.Context, opts UserCreateOpts) (User, error) { - uri := "/users" createUserOpts := struct { User UserCreateOpts `json:"user"` }{ @@ -83,7 +82,7 @@ func (api *API) CreateUser(ctx context.Context, opts UserCreateOpts) (User, erro return User{}, fmt.Errorf("Error marshalling params to JSON, %w", err) } - resp, err := api.makeRequest(ctx, http.MethodPost, uri, requestBody) + resp, err := api.makeRequest(ctx, http.MethodPost, UsersURI, requestBody) if err != nil { return User{}, err } @@ -101,7 +100,7 @@ func (api *API) CreateUser(ctx context.Context, opts UserCreateOpts) (User, erro // DeleteUser deletes an existing user. func (api *API) DeleteUser(ctx context.Context, userID string) error { - uri := fmt.Sprintf("/users/%s", userID) + uri := fmt.Sprintf("%s/%s", UsersURI, userID) _, err := api.makeRequest(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -113,7 +112,7 @@ func (api *API) DeleteUser(ctx context.Context, userID string) error { // UpdateUser updates an existing user. func (api *API) UpdateUser(ctx context.Context, userID string, opts UserUpdateOpts) (User, error) { - uri := fmt.Sprintf("/users/%s", userID) + uri := fmt.Sprintf("%s/%s", UsersURI, userID) updateUserOpts := struct { User UserUpdateOpts `json:"user"` }{ diff --git a/user_test.go b/user_test.go index d08334a..e08e394 100644 --- a/user_test.go +++ b/user_test.go @@ -3,11 +3,13 @@ package dbaas import ( "context" "encoding/json" + "fmt" "net/http" "testing" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const userID = "20d7bcf4-f8d6-4bf6-b8f6-46cb440a87f4" @@ -16,7 +18,7 @@ const testUserNotFoundResponse = `{ "error": { "code": 404, "title": "Not Found", - "message": "user 123 not found." + "message": "user %s not found." } }` @@ -71,7 +73,7 @@ func TestUsers(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/users", + httpmock.RegisterResponder("GET", testClient.Endpoint+UsersURI, httpmock.NewStringResponder(200, testUsersResponse)) expected := []User{ @@ -97,9 +99,8 @@ func TestUsers(t *testing.T) { actual, err := testClient.Users(context.Background()) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUser(t *testing.T) { @@ -107,7 +108,7 @@ func TestUser(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/users/"+userID, + httpmock.RegisterResponder("GET", testClient.Endpoint+UsersURI+"/"+userID, httpmock.NewStringResponder(200, testUserResponse)) expected := User{ @@ -122,9 +123,8 @@ func TestUser(t *testing.T) { actual, err := testClient.User(context.Background(), userID) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUserNotFound(t *testing.T) { @@ -132,17 +132,18 @@ func TestUserNotFound(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("GET", testClient.Endpoint+"/users/123", - httpmock.NewStringResponder(404, testUserNotFoundResponse)) + notFoundResponse := fmt.Sprintf(testUserNotFoundResponse, NotFoundEntityID) + httpmock.RegisterResponder("GET", testClient.Endpoint+UsersURI+"/"+NotFoundEntityID, + httpmock.NewStringResponder(404, notFoundResponse)) expected := &DBaaSAPIError{} expected.APIError.Code = 404 expected.APIError.Title = ErrorNotFoundTitle - expected.APIError.Message = "user 123 not found." + expected.APIError.Message = fmt.Sprintf("user %s not found.", NotFoundEntityID) - _, err := testClient.User(context.Background(), "123") + _, err := testClient.User(context.Background(), NotFoundEntityID) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestCreateUser(t *testing.T) { @@ -150,7 +151,7 @@ func TestCreateUser(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/users", + httpmock.RegisterResponder("POST", testClient.Endpoint+UsersURI, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&UserCreateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -193,9 +194,8 @@ func TestCreateUser(t *testing.T) { actual, err := testClient.CreateUser(context.Background(), createUserOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestCreateUserInvalidDatastoreID(t *testing.T) { @@ -203,7 +203,7 @@ func TestCreateUserInvalidDatastoreID(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("POST", testClient.Endpoint+"/users", + httpmock.RegisterResponder("POST", testClient.Endpoint+UsersURI, httpmock.NewStringResponder(400, testCreateUserInvalidDatastoreIDResponse)) expected := &DBaaSAPIError{} @@ -220,7 +220,7 @@ func TestCreateUserInvalidDatastoreID(t *testing.T) { _, err := testClient.CreateUser(context.Background(), createUserOpts) - assert.ErrorAs(t, err, &expected) + require.ErrorAs(t, err, &expected) } func TestUpdateUser(t *testing.T) { @@ -228,7 +228,7 @@ func TestUpdateUser(t *testing.T) { testClient := SetupTestClient() defer httpmock.DeactivateAndReset() - httpmock.RegisterResponder("PUT", testClient.Endpoint+"/users/"+userID, + httpmock.RegisterResponder("PUT", testClient.Endpoint+UsersURI+"/"+userID, func(req *http.Request) (*http.Response, error) { if err := json.NewDecoder(req.Body).Decode(&UserUpdateOpts{}); err != nil { return httpmock.NewStringResponse(400, ""), err @@ -269,7 +269,6 @@ func TestUpdateUser(t *testing.T) { actual, err := testClient.UpdateUser(context.Background(), userID, updateUserOpts) - if assert.NoError(t, err) { - assert.Equal(t, expected, actual) - } + require.NoError(t, err) + assert.Equal(t, expected, actual) }