From 831abf4540d520c4d8faf4b103193b87a4bbe885 Mon Sep 17 00:00:00 2001 From: Vitaliy Saveliev <70613571+milkrage@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:17:47 +0300 Subject: [PATCH] Add X-Auth-Token support (#164) * Add X-Auth-Token support - removed old Resell client - removed old QuotaManager client - created one client (all in one) that includes clients Resell and QuotaManager - new client uses X-Auth-Token instead of X-Token - updated Go version (1.14 -> 1.20) - Resell URL is taken from the identity service - added support auth with user from another domain (different from scope) - removed context for every request, because gophercloud doesn't support it --- .github/workflows/golangci-lint.yml | 4 +- .github/workflows/tests.yml | 2 +- .golangci.yml | 18 +- README.md | 160 +++-------- go.mod | 9 +- go.sum | 11 +- selvpcclient/clients/quotamanager.go | 39 +++ selvpcclient/clients/resell.go | 40 +++ selvpcclient/clients/services/catalog.go | 104 +++++++ selvpcclient/clients/services/requests.go | 63 +++++ .../clients/services/serviceclient.go | 141 ++++++++++ selvpcclient/doc.go | 37 ++- selvpcclient/quotamanager/client.go | 130 --------- selvpcclient/quotamanager/doc.go | 13 - selvpcclient/quotamanager/identity.go | 130 --------- selvpcclient/quotamanager/quotas/doc.go | 6 +- selvpcclient/quotamanager/quotas/requests.go | 54 ++-- .../quotamanager/quotas/testing/fixtures.go | 2 +- .../quotas/testing/requests_test.go | 116 ++++---- selvpcclient/resell/doc.go | 2 +- selvpcclient/resell/resell.go | 15 - selvpcclient/resell/v2/capabilities/doc.go | 11 +- .../resell/v2/capabilities/requests.go | 19 +- .../v2/capabilities/testing/requests_test.go | 27 +- selvpcclient/resell/v2/client.go | 57 ---- selvpcclient/resell/v2/client_test.go | 58 ---- selvpcclient/resell/v2/floatingips/doc.go | 8 +- .../resell/v2/floatingips/requests.go | 70 +++-- .../resell/v2/floatingips/requests_opts.go | 2 +- selvpcclient/resell/v2/floatingips/schemas.go | 2 +- .../resell/v2/floatingips/testing/fixtures.go | 4 +- .../v2/floatingips/testing/requests_test.go | 100 +++---- selvpcclient/resell/v2/keypairs/doc.go | 6 +- selvpcclient/resell/v2/keypairs/requests.go | 47 +++- .../resell/v2/keypairs/testing/fixtures.go | 2 +- .../v2/keypairs/testing/requests_test.go | 73 ++--- selvpcclient/resell/v2/licenses/doc.go | 8 +- selvpcclient/resell/v2/licenses/requests.go | 70 +++-- .../resell/v2/licenses/requests_opts.go | 2 +- selvpcclient/resell/v2/licenses/schemas.go | 2 +- .../resell/v2/licenses/testing/fixtures.go | 4 +- .../v2/licenses/testing/requests_test.go | 95 +++---- selvpcclient/resell/v2/projects/doc.go | 10 +- selvpcclient/resell/v2/projects/requests.go | 75 +++-- selvpcclient/resell/v2/projects/schemas.go | 2 +- .../resell/v2/projects/testing/fixtures.go | 2 +- .../v2/projects/testing/requests_test.go | 122 ++++---- selvpcclient/resell/v2/roles/doc.go | 12 +- selvpcclient/resell/v2/roles/requests.go | 89 ++++-- .../resell/v2/roles/testing/fixtures.go | 2 +- .../resell/v2/roles/testing/requests_test.go | 149 ++++------ selvpcclient/resell/v2/subnets/doc.go | 8 +- selvpcclient/resell/v2/subnets/requests.go | 70 +++-- .../resell/v2/subnets/requests_opts.go | 4 +- selvpcclient/resell/v2/subnets/schemas.go | 2 +- .../resell/v2/subnets/testing/fixtures.go | 6 +- .../v2/subnets/testing/requests_test.go | 95 +++---- selvpcclient/resell/v2/tokens/doc.go | 6 +- selvpcclient/resell/v2/tokens/requests.go | 33 ++- .../resell/v2/tokens/testing/fixtures.go | 2 +- .../resell/v2/tokens/testing/requests_test.go | 44 ++- selvpcclient/resell/v2/traffic/doc.go | 2 +- selvpcclient/resell/v2/traffic/requests.go | 19 +- selvpcclient/resell/v2/traffic/schemas.go | 2 +- .../resell/v2/traffic/testing/fixtures.go | 4 +- .../v2/traffic/testing/requests_test.go | 37 +-- selvpcclient/resell/v2/users/doc.go | 10 +- selvpcclient/resell/v2/users/requests.go | 75 +++-- .../resell/v2/users/testing/fixtures.go | 2 +- .../resell/v2/users/testing/requests_test.go | 117 ++++---- selvpcclient/resell/v2/vrrpsubnets/doc.go | 8 +- .../resell/v2/vrrpsubnets/requests.go | 70 +++-- .../resell/v2/vrrpsubnets/requests_opts.go | 4 +- selvpcclient/resell/v2/vrrpsubnets/schemas.go | 4 +- .../resell/v2/vrrpsubnets/testing/fixtures.go | 8 +- .../v2/vrrpsubnets/testing/requests_test.go | 90 +++--- selvpcclient/selvpc.go | 262 +++++------------- selvpcclient/testing/client_test.go | 95 ------- selvpcclient/testutils/clients.go | 62 ++--- selvpcclient/testutils/environment.go | 71 +++-- selvpcclient/testutils/fakes.go | 63 +++++ selvpcclient/testutils/handlers.go | 4 +- 82 files changed, 1712 insertions(+), 1793 deletions(-) create mode 100644 selvpcclient/clients/quotamanager.go create mode 100644 selvpcclient/clients/resell.go create mode 100644 selvpcclient/clients/services/catalog.go create mode 100644 selvpcclient/clients/services/requests.go create mode 100644 selvpcclient/clients/services/serviceclient.go delete mode 100644 selvpcclient/quotamanager/client.go delete mode 100644 selvpcclient/quotamanager/identity.go delete mode 100644 selvpcclient/resell/resell.go delete mode 100644 selvpcclient/resell/v2/client.go delete mode 100644 selvpcclient/resell/v2/client_test.go delete mode 100644 selvpcclient/testing/client_test.go diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index c72b649..0ef695c 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -13,9 +13,9 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.14' + go-version: '1.20' - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.49.0 + version: v1.53.3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 35db5b1..6c7d2a4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.14' + go-version: '1.20' - name: Run test run: go test -v ./... diff --git a/.golangci.yml b/.golangci.yml index e713439..2ea07ae 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,7 +10,7 @@ linters: - dogsled - errcheck - exportloopref -# - gci + - gci - gocognit - goconst - gocritic @@ -32,7 +32,7 @@ linters: - misspell - nakedret - noctx -# - nolintlint + - nolintlint - prealloc - rowserrcheck - scopelint @@ -45,3 +45,17 @@ linters: - unused - varcheck - whitespace + +linters-settings: + depguard: + rules: + main: + allow: + - $gostd + - github.com/selectel/go-selvpcclient + - github.com/gophercloud/gophercloud + - github.com/google/go-querystring + goimports: + local-prefixes: github.com/selectel/go-selvpcclient + gci: + local-prefixes: github.com/selectel/go-selvpcclient diff --git a/README.md b/README.md index 6da0c9f..7edd1ac 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,37 @@ # go-selvpcclient: a Go library for the Selectel VPC API -[![GoDoc](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient?status.svg)](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient) -[![Go Report Card](https://goreportcard.com/badge/github.com/selectel/go-selvpcclient)](https://goreportcard.com/report/github.com/selectel/go-selvpcclient) -[![Build Status](https://travis-ci.org/selectel/go-selvpcclient.svg?branch=master)](https://travis-ci.org/selectel/go-selvpcclient) +[![GoDoc](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient?status.svg)](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient) +[![Go Report Card](https://goreportcard.com/badge/github.com/selectel/go-selvpcclient/v3)](https://goreportcard.com/report/github.com/selectel/go-selvpcclient/v3) [![Coverage Status](https://coveralls.io/repos/github/selectel/go-selvpcclient/badge.svg?branch=master)](https://coveralls.io/github/selectel/go-selvpcclient?branch=master) -Package go-selvpcclient provides a Go library to work with the Selectel VPC API. +Package go-selvpcclient provides a Go library to work with the Selectel API: + - [Cloud Management API](https://developers.selectel.ru/docs/selectel-cloud-platform/main-services/selectel_cloud_management_api/) + - [Cloud Quota Management API ](https://developers.selectel.ru/docs/selectel-cloud-platform/main-services/cloud-quota-management/) ## Documentation -The Go library documentation is available at [godoc.org](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient). - -The API usage examples are available at [knowledge base](https://kb.selectel.com/24381383.html). -API documentation is also available at the [VPC page](https://my.selectel.ru/vpc/docs) (if you've created an account on the [registration page](https://my.selectel.ru/registration)). +The Go library documentation is available at [godoc.org](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient). ## What this library is capable of -You can use this library to work with the following objects of the Selectel VPC API: - -* [capabilities](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/capabilities) -* [floating ips](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/floatingips) -* [keypairs](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/keypairs) -* [licenses](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/licenses) -* [projects](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/projects) -* [quotas](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager/quotas) -* [roles](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/roles) -* [subnets](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/subnets) -* [tokens](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/tokens) -* [traffic](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/traffic) -* [users](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/users) -* [vrrp subnets](https://godoc.org/github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/vrrpsubnets) +You can use this library to work with the following objects of the +[Cloud Management API](https://developers.selectel.ru/docs/selectel-cloud-platform/main-services/selectel_cloud_management_api/) and +[Cloud Quota Management API](https://developers.selectel.ru/docs/selectel-cloud-platform/main-services/cloud-quota-management/). + +Cloud Management API: +* [capabilities](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/capabilities) +* [floating ips](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/floatingips) +* [keypairs](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/keypairs) +* [licenses](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/licenses) +* [projects](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/projects) +* [roles](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/roles) +* [subnets](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/subnets) +* [tokens](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/tokens) +* [traffic](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/traffic) +* [users](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/users) +* [vrrp subnets](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/vrrpsubnets) + +Cloud Quota Management API: +* [quotas](https://godoc.org/github.com/selectel/go-selvpcclient/v3/selvpcclient/quotamanager/quotas) Selectel VPC Cloud is based on the [OpenStack](https://www.openstack.org), so you don't need this library to work with actual servers, volumes, networks, etc. You can use the [Gophercloud](https://github.com/gophercloud/gophercloud) project to work with the OpenStack objects. @@ -40,7 +43,7 @@ You can use the [Gophercloud](https://github.com/gophercloud/gophercloud) projec You can install `go-selvpcclient` as a Go package: ```bash -go get github.com/selectel/go-selvpcclient/selvpcclient/v2 +go get github.com/selectel/go-selvpcclient/selvpcclient/v3 ``` ### Authentication @@ -48,7 +51,7 @@ go get github.com/selectel/go-selvpcclient/selvpcclient/v2 To work with the Selectel VPC API you first need to: * create a Selectel account: [registration page](https://my.selectel.ru/registration) -* obtain an API token: [api keys](http://my.selectel.ru/profile/apikeys) +* create the service user: [users and roles](https://docs.selectel.ru/control-panel-actions/users-and-roles) ### Usage example @@ -60,115 +63,34 @@ import ( "fmt" "log" - resell "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/projects" -) - -// API token from the https://my.selectel.ru. -var token = "token_key" - -func main() { - // Initialize the Resell V2 client. - resellClient := resell.NewV2ResellClient(token) - - // Get and print all projects. - ctx := context.Background() - allProjects, _, err := projects.List(ctx, resellClient) - if err != nil { - log.Fatal(err) - } - for _, myProject := range allProjects { - fmt.Println(myProject) - } -} -``` - -### Quota usage example - -```go -package main - -import ( - "context" - "fmt" - "log" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager/quotas" - resell "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2" - reselTokens "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/tokens" -) - -// token from the https://my.selectel.ru. -var ( - token = "token_key" - accountName = "account_name" - projectID = "project_uuid" - region = "region_name" - ramQuotaZone = "zone_name" - ramQuotaValue = 123 + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/projects" ) func main() { - // Init resell client with API token. - resellClient := resell.NewV2ResellClient(token) ctx := context.Background() - - APIToken, _, err := reselTokens.Create(ctx, resellClient, reselTokens.TokenOpts{ - AccountName: accountName, - }) - if err != nil { - log.Fatal(err) - } - - // Init Identity and Quota Manager. - client := resell.NewOpenstackClient(APIToken.ID) - identity := quotamanager.NewIdentityManager(resellClient, client, accountName) - quotaMgr := quotamanager.NewQuotaRegionalClient(selvpcclient.NewHTTPClient(), identity) - - // Get limits for project in region . - limits, _, err := quotas.GetLimits(ctx, quotaMgr, projectID, region) - if err != nil { - log.Fatal(err) - } - for _, limit := range limits { - fmt.Println(limit.Name, limit.ResourceQuotasEntities) + options := &selvpcclient.ClientOptions{ + Context: ctx, + DomainName: "999999", + Username: "admin", + Password: "m1-sup3r-p@ssw0rd-p3w-p3w", } - // Get quotas for project in region . - quotasData, _, err := quotas.GetProjectQuotas(ctx, quotaMgr, projectID, region) + client, err := selvpcclient.NewClient(options) if err != nil { log.Fatal(err) } - for _, quota := range quotasData { - fmt.Println(quota.Name, quota.ResourceQuotasEntities) - } - - // Update quotas for project in region . - UpdateQuotasOpts := quotas.UpdateProjectQuotasOpts{ - QuotasOpts: []quotas.QuotaOpts{ - { - Name: "compute_cores", - ResourceQuotasOpts: []quotas.ResourceQuotaOpts{ - { - Zone: &ramQuotaZone, - Value: &ramQuotaValue, - }, - }, - }, - }, - } - updatedQuotasData, _, err := quotas.UpdateProjectQuotas(ctx, quotaMgr, - projectID, region, UpdateQuotasOpts) + result, resp, err := projects.List(client) if err != nil { log.Fatal(err) } - - for _, quota := range updatedQuotasData { - fmt.Println(quota.Name, quota.ResourceQuotasEntities) + + fmt.Printf("Response StatusCode: %d \n", resp.StatusCode) + + for _, project := range result { + fmt.Printf("Project name: %s, enabled: %t \n", project.Name, project.Enabled) } } ``` diff --git a/go.mod b/go.mod index d1b0c65..1c8d38d 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,8 @@ -module github.com/selectel/go-selvpcclient/v2 +module github.com/selectel/go-selvpcclient/v3 -go 1.14 +go 1.20 -require github.com/gophercloud/gophercloud v1.0.0 +require ( + github.com/google/go-querystring v1.1.0 + github.com/gophercloud/gophercloud v1.5.0 +) diff --git a/go.sum b/go.sum index 057f5ab..7af7e3f 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ -github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k= -github.com/gophercloud/gophercloud v1.0.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= +github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -8,5 +12,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/selvpcclient/clients/quotamanager.go b/selvpcclient/clients/quotamanager.go new file mode 100644 index 0000000..04e3372 --- /dev/null +++ b/selvpcclient/clients/quotamanager.go @@ -0,0 +1,39 @@ +package clients + +import ( + "fmt" + + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" +) + +const ( + QuotaManagerServiceType = "quota-manager" +) + +// QuotaManagerClient quota-manager client with X-Auth-Token authorization. +type QuotaManagerClient struct { + Requests *clientservices.RequestService + catalog *clientservices.CatalogService +} + +func NewQuotaManagerClient( + requestService *clientservices.RequestService, + catalogService *clientservices.CatalogService, +) *QuotaManagerClient { + return &QuotaManagerClient{ + Requests: requestService, + catalog: catalogService, + } +} + +// GetEndpoint - returns service url in specific region. +func (c *QuotaManagerClient) GetEndpoint(regionName string) (string, error) { + endpoint, err := c.catalog.GetEndpoint(QuotaManagerServiceType, regionName) + if err != nil { + return "", fmt.Errorf( + "failed to resolve endpoint for %s in %s, err: %w", QuotaManagerServiceType, regionName, err, + ) + } + + return endpoint.URL, nil +} diff --git a/selvpcclient/clients/resell.go b/selvpcclient/clients/resell.go new file mode 100644 index 0000000..90cda82 --- /dev/null +++ b/selvpcclient/clients/resell.go @@ -0,0 +1,40 @@ +package clients + +import ( + "fmt" + + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" +) + +const ( + ResellServiceType = "resell" + ResellAPIVersion = "v2" +) + +// ResellClient resell client with X-Auth-Token authorization. +type ResellClient struct { + Requests *clientservices.RequestService + catalog *clientservices.CatalogService +} + +func NewResellClient( + requestService *clientservices.RequestService, + catalogService *clientservices.CatalogService, +) *ResellClient { + return &ResellClient{ + Requests: requestService, + catalog: catalogService, + } +} + +// GetEndpoint - returns service url. +func (c *ResellClient) GetEndpoint() (string, error) { + endpoints, err := c.catalog.GetEndpoints(ResellServiceType) + if err != nil { + return "", fmt.Errorf("failed to resolve endpoint for %s, err: %w", ResellServiceType, err) + } + + url := fmt.Sprintf("%s/%s", endpoints[0].URL, ResellAPIVersion) + + return url, nil +} diff --git a/selvpcclient/clients/services/catalog.go b/selvpcclient/clients/services/catalog.go new file mode 100644 index 0000000..7b9a96a --- /dev/null +++ b/selvpcclient/clients/services/catalog.go @@ -0,0 +1,104 @@ +package clientservices + +import ( + "errors" + "fmt" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" +) + +const publicInterface = string(gophercloud.AvailabilityPublic) + +var ( + ErrEndpointNotFound = errors.New("endpoint not found") + ErrEndpointsNotFound = errors.New("endpoint not found") + ErrServiceTypeNotFound = errors.New("service type not found") +) + +type CatalogService struct { + serviceClient *gophercloud.ServiceClient + catalog *tokens.ServiceCatalog +} + +func NewCatalogService(serviceClient *gophercloud.ServiceClient) (*CatalogService, error) { + service := &CatalogService{serviceClient: serviceClient} + + // Cache warming. + _, err := service.GetCatalog() + if err != nil { + return nil, fmt.Errorf("failed to get endpoints catalog from identity service, err: %w", err) + } + + return service, nil +} + +// GetEndpoint - returns endpoint url from Keystone catalog for ServiceType in RegionName. +// ServiceType is type of service (for example: compute, storage, quota-manager), not their names (nova, cinder). +func (cs *CatalogService) GetEndpoint(serviceType, regionName string) (tokens.Endpoint, error) { + errMsg := "failed to get endpoint for %s in %s, err: %w" + + endpoints, err := cs.findServiceTypeEndpoints(serviceType) + if err != nil { + return tokens.Endpoint{}, fmt.Errorf(errMsg, serviceType, regionName, err) + } + + endpoint, err := cs.findRegionalEndpoint(endpoints, regionName) + if err != nil { + return tokens.Endpoint{}, fmt.Errorf(errMsg, serviceType, regionName, err) + } + + return endpoint, nil +} + +// GetEndpoints - returns endpoints from Keystone catalog for ServiceType from all regions. +func (cs *CatalogService) GetEndpoints(serviceType string) ([]tokens.Endpoint, error) { + endpoints, err := cs.findServiceTypeEndpoints(serviceType) + if err != nil { + return nil, fmt.Errorf("failed to get endpoints for %s, err: %w", serviceType, err) + } + + if len(endpoints) == 0 { + return nil, ErrEndpointsNotFound + } + + return endpoints, nil +} + +// GetCatalog - returns endpoints catalog from Keystone or cache. +func (cs *CatalogService) GetCatalog() (*tokens.ServiceCatalog, error) { + if cs.catalog != nil { + return cs.catalog, nil + } + + catalog, err := tokens.Get(cs.serviceClient, cs.serviceClient.Token()).ExtractServiceCatalog() + if err != nil { + return nil, fmt.Errorf("failed to get endpoints catalog, err: %w", err) + } + + cs.catalog = catalog + + return catalog, nil +} + +// findServiceTypeEndpoints - returns all endpoints for ServiceType from endpoints catalog. +func (cs *CatalogService) findServiceTypeEndpoints(serviceType string) ([]tokens.Endpoint, error) { + for _, service := range cs.catalog.Entries { + if service.Type == serviceType { + return service.Endpoints, nil + } + } + + return nil, ErrServiceTypeNotFound +} + +// findRegionalEndpoint - returns one endpoint for service in the specified region. +func (cs *CatalogService) findRegionalEndpoint(endpoints []tokens.Endpoint, regionName string) (tokens.Endpoint, error) { + for _, endpoint := range endpoints { + if endpoint.Interface == publicInterface && endpoint.RegionID == regionName { + return endpoint, nil + } + } + + return tokens.Endpoint{}, ErrEndpointNotFound +} diff --git a/selvpcclient/clients/services/requests.go b/selvpcclient/clients/services/requests.go new file mode 100644 index 0000000..6e4e254 --- /dev/null +++ b/selvpcclient/clients/services/requests.go @@ -0,0 +1,63 @@ +package clientservices + +import ( + "encoding/json" + "errors" + "io" + "net/http" + + "github.com/gophercloud/gophercloud" +) + +type RequestService struct { + serviceClient *gophercloud.ServiceClient +} + +type RequestOptions struct { + Body io.Reader + OkCodes []int +} + +func NewRequestService(serviceClient *gophercloud.ServiceClient) *RequestService { + return &RequestService{serviceClient: serviceClient} +} + +func (s *RequestService) Do(method, url string, options *RequestOptions) (*ResponseResult, error) { + requestOpts := gophercloud.RequestOpts{ + OkCodes: options.OkCodes, + RawBody: options.Body, + KeepResponseBody: true, + } + + response, err := s.serviceClient.Request(method, url, &requestOpts) + if err != nil && !errors.As(err, &gophercloud.ErrUnexpectedResponseCode{}) { + return nil, err + } + + responseResult := &ResponseResult{response, err} + + return responseResult, nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ResponseResult represents a result of a HTTP request. +// It embedded standard http.Response and adds a custom error description. +type ResponseResult struct { + *http.Response + + // Err contains error that can be provided to a caller. + Err error +} + +// ExtractResult allows to provide an object into which ResponseResult body will be extracted. +func (result *ResponseResult) ExtractResult(to interface{}) error { + body, err := io.ReadAll(result.Body) + defer result.Body.Close() + if err != nil { + return err + } + + err = json.Unmarshal(body, to) + return err +} diff --git a/selvpcclient/clients/services/serviceclient.go b/selvpcclient/clients/services/serviceclient.go new file mode 100644 index 0000000..c185483 --- /dev/null +++ b/selvpcclient/clients/services/serviceclient.go @@ -0,0 +1,141 @@ +package clientservices + +import ( + "fmt" + "net" + "net/http" + "time" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" +) + +type ServiceClientOptions struct { + // The name of the domain in which the token will be issued. + DomainName string + + // Credentials to auth with. + Username string + Password string + + // Optional field for setting project scope. + ProjectID string + + // Optional field. The name of the domain where the user resides (Identity v3). + UserDomainName string + + // Optional field for setting a non-default Identity endpoint. + AuthURL string + + // Optional field. + HTTPClient *http.Client + + // Optional field. + UserAgent string +} + +const AuthURL = "https://api.selvpc.ru/identity/v3/" + +func NewServiceClient(options *ServiceClientOptions) (*gophercloud.ServiceClient, error) { + if options.AuthURL == "" { + options.AuthURL = AuthURL + } + + // UserDomainName field to specify the domain name where the user is located. + // If this field is not specified, then we will think that the token will be + // issued in the same domain where the user is located. + if options.UserDomainName == "" { + options.UserDomainName = options.DomainName + } + + authOptions := gophercloud.AuthOptions{ + AllowReauth: true, + IdentityEndpoint: options.AuthURL, + Username: options.Username, + Password: options.Password, + DomainName: options.UserDomainName, + Scope: &gophercloud.AuthScope{ + ProjectID: options.ProjectID, + }, + } + + // If project scope is not set, we use domain scope. + if authOptions.Scope.ProjectID == "" { + authOptions.Scope.DomainName = options.DomainName + } + + authProvider, err := openstack.AuthenticatedClient(authOptions) + if err != nil { + return nil, fmt.Errorf("failed to create auth provider, err: %w", err) + } + + serviceClient, err := openstack.NewIdentityV3(authProvider, gophercloud.EndpointOpts{ + Availability: gophercloud.AvailabilityPublic, + }) + if err != nil { + return nil, fmt.Errorf("failed to create service client, err: %w", err) + } + + httpClient := options.HTTPClient + if httpClient == nil { + httpClient = NewHTTPClient() + } + serviceClient.HTTPClient = *httpClient + + if options.UserAgent != "" { + userAgent := gophercloud.UserAgent{} + userAgent.Prepend(options.UserAgent) + serviceClient.UserAgent = userAgent + } + + return serviceClient, nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +const ( + // httpTimeout represents the default timeout (in seconds) for HTTP + // requests. + httpTimeout = 120 + + // dialTimeout represents the default timeout (in seconds) for HTTP + // connection establishments. + dialTimeout = 60 + + // keepaliveTimeout represents the default keep-alive period for an active + // network connection. + keepaliveTimeout = 60 + + // maxIdleConns represents the maximum number of idle (keep-alive) + // connections. + maxIdleConns = 100 + + // idleConnTimeout represents the maximum amount of time an idle + // (keep-alive) connection will remain idle before closing itself. + idleConnTimeout = 100 + + // tlsHandshakeTimeout represents the default timeout (in seconds) + // for TLS handshake. + tlsHandshakeTimeout = 60 + + // expectContinueTimeout represents the default amount of time to + // wait for a server's first response headers. + expectContinueTimeout = 1 +) + +func NewHTTPClient() *http.Client { + return &http.Client{ + Timeout: time.Second * httpTimeout, + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: dialTimeout * time.Second, + KeepAlive: keepaliveTimeout * time.Second, + }).DialContext, + MaxIdleConns: maxIdleConns, + IdleConnTimeout: idleConnTimeout * time.Second, + TLSHandshakeTimeout: tlsHandshakeTimeout * time.Second, + ExpectContinueTimeout: expectContinueTimeout * time.Second, + }, + } +} diff --git a/selvpcclient/doc.go b/selvpcclient/doc.go index d9408bd..f8daecb 100644 --- a/selvpcclient/doc.go +++ b/selvpcclient/doc.go @@ -3,23 +3,36 @@ Package selvpcclient provides a library to work with the Selectel VPC API. # Authentication -To work with the Selectel VPC API you first need to: + To work with the Selectel VPC API you first need to: - - create a Selectel account: https://my.selectel.ru/registration - - obtain an API token: http://my.selectel.ru/profile/apikeys + - create a Selectel account: https://my.selectel.ru/registration + - create the service user: https://docs.selectel.ru/control-panel-actions/users-and-roles/add-user/ -You can then provide the API token to the selvpc service client. +# Usage example -# Service clients + ctx := context.Background() -Service client is a special struct that implements a client for different part -of the Selectel VPC API. -You need to initialize the needed service client prior to do any requests: + options := &selvpcclient.ClientOptions{ + Context: ctx, + DomainName: "999999", + Username: "admin", + Password: "m1-sup3r-p@ssw0rd-p3w-p3w", + } - token := "token_string" - resellClient := resell.NewV2ResellClient(token) + client, err := selvpcclient.NewClient(options) + if err != nil { + log.Fatal(err) + } -All methods of service clients uses the Go context to provide end-user of the -library with a native way to work with the cancellation signals + result, resp, err := projects.List(client) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Response StatusCode: %d \n", resp.StatusCode) + + for _, project := range result { + fmt.Printf("Project name: %s, enabled: %t \n", project.Name, project.Enabled) + } */ package selvpcclient diff --git a/selvpcclient/quotamanager/client.go b/selvpcclient/quotamanager/client.go deleted file mode 100644 index f46f184..0000000 --- a/selvpcclient/quotamanager/client.go +++ /dev/null @@ -1,130 +0,0 @@ -package quotamanager - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" //nolint:staticcheck - "net/http" - "strings" - "unicode" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell" -) - -var errServiceResponse = errors.New("status code from the server") - -const ( - projectURL = "projects" -) - -// QuotaRegionalClient stores details that are needed to work with quotas Selectel APIs. -type QuotaRegionalClient struct { - UserAgent string - HTTPClient *http.Client - IdentityMgr IdentityManagerInterface -} - -// NewQuotaRegionalClient creates regional quota client with Openstack identity and HTTP client. -func NewQuotaRegionalClient(httpClient *http.Client, identityMgr IdentityManagerInterface) *QuotaRegionalClient { - return &QuotaRegionalClient{ - UserAgent: resell.UserAgent, - IdentityMgr: identityMgr, - HTTPClient: httpClient, - } -} - -type ResponseResult struct { - *http.Response - - // Err contains error that can be provided to a caller. - Err error -} - -// ExtractResult allows to provide an object into which ResponseResult body will be extracted. -func (result *ResponseResult) ExtractResult(to interface{}) error { - body, err := ioutil.ReadAll(result.Body) - defer result.Body.Close() - if err != nil { - return err - } - - err = json.Unmarshal(body, to) - return err -} - -func (result *ResponseResult) ExtractErr() (string, error) { - body, err := ioutil.ReadAll(result.Body) - defer result.Body.Close() - if err != nil { - return "", err - } - - resp := string(body) - - var builder strings.Builder - builder.Grow(len(resp)) - for _, ch := range resp { - if !unicode.IsSpace(ch) { - builder.WriteRune(ch) - } - } - - return builder.String(), nil -} - -// DoRequest performs the HTTP request with the current ServiceClient's HTTPClient. -// Authentication and optional headers will be added automatically. -func (mgr *QuotaRegionalClient) DoRequest(ctx context.Context, method, path string, body io.Reader) (*ResponseResult, error) { - tokenID, err := mgr.IdentityMgr.GetToken() - if err != nil { - return nil, err - } - - request, err := http.NewRequest(method, path, body) - if err != nil { - return nil, err - } - request.Header.Set("User-Agent", mgr.UserAgent) - request.Header.Set("X-Auth-Token", tokenID) - if body != nil { - request.Header.Set("Content-Type", "application/json") - } - request = request.WithContext(ctx) - - // Send HTTP request and populate the ResponseResult. - response, err := mgr.HTTPClient.Do(request) - if err != nil { - return nil, err - } - responseResult := &ResponseResult{ - response, - nil, - } - - // Check status code and populate extended error message if it's possible. - if response.StatusCode >= 400 && response.StatusCode <= 599 { - extendedError, err := responseResult.ExtractErr() - if err != nil { - responseResult.Err = fmt.Errorf("selvpcclient: got the %d %w", response.StatusCode, errServiceResponse) - } else { - responseResult.Err = fmt.Errorf("selvpcclient: got the %d %w: %s", response.StatusCode, errServiceResponse, extendedError) - } - } - - return responseResult, nil -} - -// BuildPath builds quotas url for specific region and project. -func (mgr *QuotaRegionalClient) BuildPath(region, projectID, path string) (string, error) { - baseURL, err := mgr.IdentityMgr.GetEndpointForRegion(region) - if err != nil { - return "", err - } - - path = strings.Join([]string{baseURL, projectURL, projectID, path}, "/") - - return path, nil -} diff --git a/selvpcclient/quotamanager/doc.go b/selvpcclient/quotamanager/doc.go index 413caa9..def0569 100644 --- a/selvpcclient/quotamanager/doc.go +++ b/selvpcclient/quotamanager/doc.go @@ -1,17 +1,4 @@ /* Package quotamanager provides methods and structures to work with the Quotas Manager API. - -Example of creating QuotaRegional client - - resellClient := resell.NewV2ResellClient(APIToken) - ctx := context.Background() - accountName := "123456" - token, _, _ := reselTokens.Create(ctx, resellClient, reselTokens.TokenOpts{ - AccountName: accountName, - }) - - OpenstackClient := resell.NewOpenstackClient(token.ID) - identity := quotamanager.NewIdentityManager(resellClient, OpenstackClient, accountName) - QuotaRegionalClient := quotamanager.NewQuotaRegionalClient(selvpcclient.NewHTTPClient(), identity) */ package quotamanager diff --git a/selvpcclient/quotamanager/identity.go b/selvpcclient/quotamanager/identity.go deleted file mode 100644 index cd28722..0000000 --- a/selvpcclient/quotamanager/identity.go +++ /dev/null @@ -1,130 +0,0 @@ -package quotamanager - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - reselTokens "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/tokens" -) - -var ( - NoSuchRegionErr = "no such region: %s" - GetCatalogErr = "failed to get endpoints: %v" - ExtractTokenErr = "failed to extract token: %v" - CreateTokenErr = "failed to create token: %v" -) - -const ( - MinTokenTTL = 180 - QuotaServiceType = "quota-manager" - PublicInterface = "public" -) - -type IdentityManagerInterface interface { - GetToken() (string, error) - GetEndpointForRegion(region string) (string, error) -} - -// IdentityManager stores details that are needed to authenticate in quotas Selectel APIs. -type IdentityManager struct { - AccountName string - Token *tokens.Token - OpenstackClient *gophercloud.ServiceClient - ResellClient *selvpcclient.ServiceClient - syncer *sync.Mutex -} - -// NewIdentityManager creates client for Openstack authentication. -func NewIdentityManager(resellClient *selvpcclient.ServiceClient, openstackClient *gophercloud.ServiceClient, - accountName string, -) *IdentityManager { - mgr := &IdentityManager{ - AccountName: accountName, - OpenstackClient: openstackClient, - ResellClient: resellClient, - syncer: &sync.Mutex{}, - } - - return mgr -} - -// GetToken returns Openstack token. -func (mgr *IdentityManager) GetToken() (string, error) { - mgr.syncer.Lock() - defer mgr.syncer.Unlock() - - if mgr.needReAuth() { - err := mgr.auth(context.Background()) - if err != nil { - return "", err - } - } - - return mgr.Token.ID, nil -} - -// GetEndpointForRegion returns quotas url for specific region. -func (mgr *IdentityManager) GetEndpointForRegion(region string) (string, error) { - token, err := mgr.GetToken() - if err != nil { - return "", err - } - - catalog, err := tokens.Get(mgr.OpenstackClient, token).ExtractServiceCatalog() - if err != nil { - return "", fmt.Errorf(GetCatalogErr, err) - } - - quotaEndpoints := getEndpoints(catalog) - regionEndpoint, err := findEndpointForRegion(quotaEndpoints, region) - - return regionEndpoint, err -} - -func (mgr *IdentityManager) auth(ctx context.Context) error { - resellToken, _, err := reselTokens.Create(ctx, mgr.ResellClient, reselTokens.TokenOpts{ - AccountName: mgr.AccountName, - }) - if err != nil { - return fmt.Errorf(CreateTokenErr, err) - } - - tokenInfo := tokens.Get(mgr.OpenstackClient, resellToken.ID) - - mgr.Token, err = tokenInfo.ExtractToken() //nolint:staticcheck - if err != nil { - return fmt.Errorf(ExtractTokenErr, err) - } - - return nil -} - -func (mgr *IdentityManager) needReAuth() bool { - return mgr.Token == nil || time.Until(mgr.Token.ExpiresAt).Seconds() <= MinTokenTTL -} - -func getEndpoints(catalog *tokens.ServiceCatalog) []tokens.Endpoint { - for _, service := range catalog.Entries { - if service.Type == QuotaServiceType { - return service.Endpoints - } - } - - return nil -} - -func findEndpointForRegion(endpoints []tokens.Endpoint, region string) (string, error) { - for _, endpoint := range endpoints { - if endpoint.Interface == PublicInterface && endpoint.RegionID == region { - return endpoint.URL, nil - } - } - - return "", fmt.Errorf(NoSuchRegionErr, region) -} diff --git a/selvpcclient/quotamanager/quotas/doc.go b/selvpcclient/quotamanager/quotas/doc.go index 07f85d7..6090d95 100644 --- a/selvpcclient/quotamanager/quotas/doc.go +++ b/selvpcclient/quotamanager/quotas/doc.go @@ -4,7 +4,7 @@ Quota Manager API. Example of getting quota limits for a single project - limits, _, err := quotas.GetLimits(ctx, QuotaRegionalClient) + limits, _, err := quotas.GetLimits(client, projectID, regionName) if err != nil { log.Fatal(err) } @@ -14,7 +14,7 @@ Example of getting quota limits for a single project Example of getting quotas for a single project in specific region - singleProjectQuotas, _, err := quotas.GetProjectQuotas(ctx, ResellClient, QuotaRegionalClient, projectID, regionName) + singleProjectQuotas, _, err := quotas.GetProjectQuotas(client, projectID, regionName) if err != nil { log.Fatal(err) } @@ -39,7 +39,7 @@ Example of updating quotas for a single project in specific region }, }, } - updatedProjectQuotas, _, err := quotas.UpdateProjectQuotas(context, ResellClient, QuotaRegionalClient, projectID, regionName, projectQuotaUpdateOpts) + updatedProjectQuotas, _, err := quotas.UpdateProjectQuotas(context, client, projectID, regionName, projectQuotaUpdateOpts) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/quotamanager/quotas/requests.go b/selvpcclient/quotamanager/quotas/requests.go index 4aef08e..2cfbaf5 100644 --- a/selvpcclient/quotamanager/quotas/requests.go +++ b/selvpcclient/quotamanager/quotas/requests.go @@ -2,22 +2,31 @@ package quotas import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" + "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) +const resourcePrefix = "projects" + // GetLimits returns limits for a single project referenced by id in specific region. -func GetLimits(ctx context.Context, client *quotamanager.QuotaRegionalClient, projectID, region string, -) ([]*Quota, *quotamanager.ResponseResult, error) { - url, err := client.BuildPath(region, projectID, "limits") +func GetLimits(client *selvpcclient.Client, projectID, region string, +) ([]*Quota, *clientservices.ResponseResult, error) { + endpoint, err := client.QuotaManager.GetEndpoint(region) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url := strings.Join([]string{endpoint, resourcePrefix, projectID, "limits"}, "/") + + responseResult, err := client.QuotaManager.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -37,17 +46,23 @@ func GetLimits(ctx context.Context, client *quotamanager.QuotaRegionalClient, pr } // GetProjectQuotas returns the quotas info for a single project referenced by id in specific region. -func GetProjectQuotas(ctx context.Context, client *quotamanager.QuotaRegionalClient, projectID, region string, -) ([]*Quota, *quotamanager.ResponseResult, error) { - url, err := client.BuildPath(region, projectID, "quotas") +func GetProjectQuotas(client *selvpcclient.Client, projectID, region string, +) ([]*Quota, *clientservices.ResponseResult, error) { + endpoint, err := client.QuotaManager.GetEndpoint(region) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url := strings.Join([]string{endpoint, resourcePrefix, projectID, "quotas"}, "/") + + responseResult, err := client.QuotaManager.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } + if responseResult.Err != nil { return nil, responseResult, responseResult.Err } @@ -63,20 +78,25 @@ func GetProjectQuotas(ctx context.Context, client *quotamanager.QuotaRegionalCli } // UpdateProjectQuotas updates the quotas info for a single project referenced by id in specific region. -func UpdateProjectQuotas(ctx context.Context, client *quotamanager.QuotaRegionalClient, projectID, region string, +func UpdateProjectQuotas(client *selvpcclient.Client, projectID, region string, updateOpts UpdateProjectQuotasOpts, -) ([]*Quota, *quotamanager.ResponseResult, error) { +) ([]*Quota, *clientservices.ResponseResult, error) { requestBody, err := json.Marshal(&updateOpts) if err != nil { return nil, nil, err } - url, err := client.BuildPath(region, projectID, "quotas") + endpoint, err := client.QuotaManager.GetEndpoint(region) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) } - responseResult, err := client.DoRequest(ctx, http.MethodPatch, url, bytes.NewReader(requestBody)) + url := strings.Join([]string{endpoint, resourcePrefix, projectID, "quotas"}, "/") + + responseResult, err := client.QuotaManager.Requests.Do(http.MethodPatch, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } diff --git a/selvpcclient/quotamanager/quotas/testing/fixtures.go b/selvpcclient/quotamanager/quotas/testing/fixtures.go index eecc6d3..f64dbaa 100644 --- a/selvpcclient/quotamanager/quotas/testing/fixtures.go +++ b/selvpcclient/quotamanager/quotas/testing/fixtures.go @@ -1,7 +1,7 @@ package testing import ( - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager/quotas" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/quotamanager/quotas" ) // TestGetLimitsQuotasResponseRaw represents a raw response from the GetAll request. diff --git a/selvpcclient/quotamanager/quotas/testing/requests_test.go b/selvpcclient/quotamanager/quotas/testing/requests_test.go index b0fdacd..a3ddf1d 100644 --- a/selvpcclient/quotamanager/quotas/testing/requests_test.go +++ b/selvpcclient/quotamanager/quotas/testing/requests_test.go @@ -1,14 +1,13 @@ package testing import ( - "context" "net/http" "reflect" "strings" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager/quotas" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/quotamanager/quotas" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) const ( @@ -20,9 +19,9 @@ const ( func TestGetLimitsQuotas(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "limits"}, "/"), @@ -32,8 +31,7 @@ func TestGetLimitsQuotas(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := quotas.GetLimits(ctx, testEnv.Client, testProjectID, testRegion) + actual, _, err := quotas.GetLimits(testEnv.Client, testProjectID, testRegion) if err != nil { t.Fatal(err) } @@ -61,9 +59,9 @@ func TestGetLimitsQuotas(t *testing.T) { func TestGetLimitsQuotasHTTPError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "limits"}, "/"), @@ -73,8 +71,7 @@ func TestGetLimitsQuotasHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, httpResponse, err := quotas.GetLimits(ctx, testEnv.Client, testProjectID, testRegion) + actual, httpResponse, err := quotas.GetLimits(testEnv.Client, testProjectID, testRegion) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -92,13 +89,12 @@ func TestGetLimitsQuotasHTTPError(t *testing.T) { } func TestGetLimitsQuotasTimeoutError(t *testing.T) { - testEnv := testutils.SetupTestQuotasEnv() - testEnv.Server.Close() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allQuotas, _, err := quotas.GetLimits(ctx, testEnv.Client, "", "ru-1") + allQuotas, _, err := quotas.GetLimits(testEnv.Client, "", "ru-1") if allQuotas != nil { t.Fatal("expected no quotas from the GetAll method") @@ -111,9 +107,9 @@ func TestGetLimitsQuotasTimeoutError(t *testing.T) { func TestGetLimitsQuotasUnmarshalError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "limits"}, "/"), @@ -123,8 +119,7 @@ func TestGetLimitsQuotasUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allQuotas, _, err := quotas.GetLimits(ctx, testEnv.Client, testProjectID, testRegion) + allQuotas, _, err := quotas.GetLimits(testEnv.Client, testProjectID, testRegion) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -140,9 +135,9 @@ func TestGetLimitsQuotasUnmarshalError(t *testing.T) { func TestGetProjectQuotas(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -152,8 +147,7 @@ func TestGetProjectQuotas(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := quotas.GetProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion) + actual, _, err := quotas.GetProjectQuotas(testEnv.Client, testProjectID, testRegion) if err != nil { t.Fatal(err) } @@ -181,9 +175,9 @@ func TestGetProjectQuotas(t *testing.T) { func TestGetProjectQuotasSingle(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -193,8 +187,7 @@ func TestGetProjectQuotasSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := quotas.GetProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion) + actual, _, err := quotas.GetProjectQuotas(testEnv.Client, testProjectID, testRegion) if err != nil { t.Fatal(err) } @@ -212,9 +205,9 @@ func TestGetProjectQuotasSingle(t *testing.T) { func TestGetProjectQuotasHTTPError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -224,8 +217,7 @@ func TestGetProjectQuotasHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allQuotas, httpResponse, err := quotas.GetProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion) + allQuotas, httpResponse, err := quotas.GetProjectQuotas(testEnv.Client, testProjectID, testRegion) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -243,13 +235,12 @@ func TestGetProjectQuotasHTTPError(t *testing.T) { } func TestGetProjectQuotasTimeoutError(t *testing.T) { - testEnv := testutils.SetupTestQuotasEnv() - testEnv.Server.Close() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allQuotas, _, err := quotas.GetProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion) + allQuotas, _, err := quotas.GetProjectQuotas(testEnv.Client, testProjectID, testRegion) if allQuotas != nil { t.Fatal("expected no quotas from the GetProjectQuotas method") @@ -262,9 +253,9 @@ func TestGetProjectQuotasTimeoutError(t *testing.T) { func TestGetProjectQuotasUnmarshalError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -274,8 +265,7 @@ func TestGetProjectQuotasUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allQuotas, _, err := quotas.GetProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion) + allQuotas, _, err := quotas.GetProjectQuotas(testEnv.Client, testProjectID, testRegion) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -291,9 +281,9 @@ func TestGetProjectQuotasUnmarshalError(t *testing.T) { func TestUpdateProjectQuotas(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/projects/c83243b3c18a4d109a5f0fe45336af85/quotas", @@ -304,9 +294,8 @@ func TestUpdateProjectQuotas(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateQuotasOpts - actualResponse, _, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + actualResponse, _, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if err != nil { t.Fatal(err) } @@ -324,9 +313,9 @@ func TestUpdateProjectQuotas(t *testing.T) { func TestUpdateProjectQuotasNilLocation(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -337,9 +326,8 @@ func TestUpdateProjectQuotasNilLocation(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateQuotasOptsNilLocationParams - actualResponse, _, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + actualResponse, _, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if err != nil { t.Fatal(err) } @@ -357,9 +345,9 @@ func TestUpdateProjectQuotasNilLocation(t *testing.T) { func TestUpdateProjectQuotasHTTPError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -369,9 +357,8 @@ func TestUpdateProjectQuotasHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateQuotasOpts - allQuotas, httpResponse, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + allQuotas, httpResponse, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -388,14 +375,13 @@ func TestUpdateProjectQuotasHTTPError(t *testing.T) { } func TestUpdateProjectQuotasTimeoutError(t *testing.T) { - testEnv := testutils.SetupTestQuotasEnv() - testEnv.Server.Close() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() updateOpts := TestUpdateQuotasOpts - allQuotas, _, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + allQuotas, _, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if allQuotas != nil { t.Fatal("expected no quotas from the Update method") @@ -408,9 +394,9 @@ func TestUpdateProjectQuotasTimeoutError(t *testing.T) { func TestUpdateProjectQuotasUnmarshalError(t *testing.T) { endpointCalled := false - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: strings.Join([]string{testBaseURL, "quotas"}, "/"), @@ -421,9 +407,8 @@ func TestUpdateProjectQuotasUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateQuotasOpts - allQuotas, _, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + allQuotas, _, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -437,13 +422,12 @@ func TestUpdateProjectQuotasUnmarshalError(t *testing.T) { } func TestUpdateProjectQuotasMarshallError(t *testing.T) { - testEnv := testutils.SetupTestQuotasEnv() + testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestRegionalClient() + testEnv.NewSelVPCClient() - ctx := context.Background() updateOpts := TestUpdateQuotasInvalidOpts - allQuotas, _, err := quotas.UpdateProjectQuotas(ctx, testEnv.Client, testProjectID, testRegion, updateOpts) + allQuotas, _, err := quotas.UpdateProjectQuotas(testEnv.Client, testProjectID, testRegion, updateOpts) if allQuotas != nil { t.Fatal("expected no quotas from the Update method") diff --git a/selvpcclient/resell/doc.go b/selvpcclient/resell/doc.go index 6b7cecd..978785b 100644 --- a/selvpcclient/resell/doc.go +++ b/selvpcclient/resell/doc.go @@ -1,5 +1,5 @@ /* Package resell provides all needed method and structures to work with the -Selectel VPC Resell API. +Selectel Cloud Management API (Resell) API. */ package resell diff --git a/selvpcclient/resell/resell.go b/selvpcclient/resell/resell.go deleted file mode 100644 index c081715..0000000 --- a/selvpcclient/resell/resell.go +++ /dev/null @@ -1,15 +0,0 @@ -package resell - -import "github.com/selectel/go-selvpcclient/v2/selvpcclient" - -const ( - // ServiceType contains the name of the Selectel VPC service for which this - // package is intended. - ServiceType = "resell" - - // Endpoint contains the base url for all versions of the Resell client. - Endpoint = selvpcclient.DefaultEndpoint + "/" + ServiceType - - // UserAgent contains the user agent for all versions of the Resell client. - UserAgent = selvpcclient.DefaultUserAgent -) diff --git a/selvpcclient/resell/v2/capabilities/doc.go b/selvpcclient/resell/v2/capabilities/doc.go index f498d82..10674f0 100644 --- a/selvpcclient/resell/v2/capabilities/doc.go +++ b/selvpcclient/resell/v2/capabilities/doc.go @@ -4,10 +4,11 @@ through the Resell v2 API. Example of getting domain capabilities - domainCapabilities, _, err := capabilities.Get(ctx, resellClient) - if err != nil { - log.Fatal(err) - } - fmt.Println(domainCapabilities) + domainCapabilities, _, err := capabilities.Get(client) + if err != nil { + log.Fatal(err) + } + + fmt.Println(domainCapabilities) */ package capabilities diff --git a/selvpcclient/resell/v2/capabilities/requests.go b/selvpcclient/resell/v2/capabilities/requests.go index 1f67216..bb20583 100644 --- a/selvpcclient/resell/v2/capabilities/requests.go +++ b/selvpcclient/resell/v2/capabilities/requests.go @@ -1,19 +1,28 @@ package capabilities import ( - "context" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "capabilities" // Get returns the domain capabilities. -func Get(ctx context.Context, client *selvpcclient.ServiceClient) (*Capabilities, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client) (*Capabilities, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } diff --git a/selvpcclient/resell/v2/capabilities/testing/requests_test.go b/selvpcclient/resell/v2/capabilities/testing/requests_test.go index 2eb9cab..348c98e 100644 --- a/selvpcclient/resell/v2/capabilities/testing/requests_test.go +++ b/selvpcclient/resell/v2/capabilities/testing/requests_test.go @@ -1,12 +1,11 @@ package testing import ( - "context" "net/http" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/capabilities" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/capabilities" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetCapabilities(t *testing.T) { @@ -14,7 +13,7 @@ func TestGetCapabilities(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/capabilities", @@ -24,8 +23,7 @@ func TestGetCapabilities(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - c, _, err := capabilities.Get(ctx, testEnv.Client) + c, _, err := capabilities.Get(testEnv.Client) if err != nil { t.Fatal(err) } @@ -58,7 +56,7 @@ func TestGetCapabilitiesHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/capabilities", @@ -68,8 +66,7 @@ func TestGetCapabilitiesHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - c, httpResponse, err := capabilities.Get(ctx, testEnv.Client) + c, httpResponse, err := capabilities.Get(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -88,12 +85,11 @@ func TestGetCapabilitiesHTTPError(t *testing.T) { func TestGetCapabilitiesTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - c, _, err := capabilities.Get(ctx, testEnv.Client) + c, _, err := capabilities.Get(testEnv.Client) if c != nil { t.Fatal("expected no capabilities from the Get method") @@ -108,7 +104,7 @@ func TestGetCapabilitiesUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/capabilities", @@ -118,8 +114,7 @@ func TestGetCapabilitiesUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - c, _, err := capabilities.Get(ctx, testEnv.Client) + c, _, err := capabilities.Get(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") diff --git a/selvpcclient/resell/v2/client.go b/selvpcclient/resell/v2/client.go deleted file mode 100644 index de12b63..0000000 --- a/selvpcclient/resell/v2/client.go +++ /dev/null @@ -1,57 +0,0 @@ -package v2 - -import ( - "github.com/gophercloud/gophercloud" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell" -) - -// APIVersion sets the version of the Resell client. -const ( - APIVersion = "v2" -) - -// NewV2ResellClient initializes a new Resell client for the V2 API. -func NewV2ResellClient(tokenID string) *selvpcclient.ServiceClient { - return &selvpcclient.ServiceClient{ - HTTPClient: selvpcclient.NewHTTPClient(), - Endpoint: resell.Endpoint + "/" + APIVersion, - TokenID: tokenID, - UserAgent: resell.UserAgent, - } -} - -// NewV2ResellClientWithEndpoint initializes a new Resell client for the V2 API with a custom endpoint. -func NewV2ResellClientWithEndpoint(tokenID, endpoint string) *selvpcclient.ServiceClient { - resellClient := &selvpcclient.ServiceClient{ - HTTPClient: selvpcclient.NewHTTPClient(), - Endpoint: endpoint, - TokenID: tokenID, - UserAgent: resell.UserAgent, - } - - return resellClient -} - -func NewOpenstackClient(tokenID string) *gophercloud.ServiceClient { - return &gophercloud.ServiceClient{ - ProviderClient: &gophercloud.ProviderClient{ - TokenID: tokenID, - HTTPClient: *selvpcclient.NewHTTPClient(), - }, - Endpoint: selvpcclient.DefaultOpenstackIdentityEndpoint, - MoreHeaders: map[string]string{"User-agent": selvpcclient.DefaultUserAgent}, - } -} - -func NewOpenstackClientWithEndpoint(tokenID, endpoint string) *gophercloud.ServiceClient { - return &gophercloud.ServiceClient{ - ProviderClient: &gophercloud.ProviderClient{ - TokenID: tokenID, - HTTPClient: *selvpcclient.NewHTTPClient(), - }, - Endpoint: endpoint, - MoreHeaders: map[string]string{"User-agent": selvpcclient.DefaultUserAgent}, - } -} diff --git a/selvpcclient/resell/v2/client_test.go b/selvpcclient/resell/v2/client_test.go deleted file mode 100644 index 9abe0a0..0000000 --- a/selvpcclient/resell/v2/client_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/gophercloud/gophercloud/testhelper" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" -) - -const ( - token = "fakeID" - endpoint = "http://example.org" -) - -func TestNewV2ResellClient(t *testing.T) { - expected := &selvpcclient.ServiceClient{ - Endpoint: resell.Endpoint + "/" + APIVersion, - TokenID: token, - UserAgent: resell.UserAgent, - } - - actual := NewV2ResellClient(token) - if actual.HTTPClient == nil { - t.Errorf("expected initialised HTTPClient but it's nil") - } - - testutils.CompareClients(t, expected, actual) -} - -func TestNewV2ResellClientWithEndpoint(t *testing.T) { - expected := &selvpcclient.ServiceClient{ - Endpoint: endpoint, - TokenID: token, - UserAgent: resell.UserAgent, - } - - actual := NewV2ResellClientWithEndpoint(token, endpoint) - if actual.HTTPClient == nil { - t.Errorf("expected initialised HTTPClient but it's nil") - } - - testutils.CompareClients(t, expected, actual) -} - -func TestNewOpenstackClient(t *testing.T) { - actual := NewOpenstackClient(token) - - testhelper.AssertEquals(t, selvpcclient.DefaultOpenstackIdentityEndpoint, actual.Endpoint) -} - -func TestNewOpenstackClientWithEndpoint(t *testing.T) { - actual := NewOpenstackClientWithEndpoint(token, endpoint) - - testhelper.AssertEquals(t, endpoint, actual.Endpoint) -} diff --git a/selvpcclient/resell/v2/floatingips/doc.go b/selvpcclient/resell/v2/floatingips/doc.go index 688a12d..3a8617d 100644 --- a/selvpcclient/resell/v2/floatingips/doc.go +++ b/selvpcclient/resell/v2/floatingips/doc.go @@ -4,7 +4,7 @@ the Resell v2 API. Example of getting a single floating ip referenced by its id - floatingIP, _, err := floatingips.Get(context, resellClient, fipID) + floatingIP, _, err := floatingips.Get(context, client, fipID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single floating ip referenced by its id Example of getting all floating ips - allFloatingIPs, _, err := floatingips.List(ctx, resellClient, floatingips.ListOpts{}) + allFloatingIPs, _, err := floatingips.List(client, floatingips.ListOpts{}) if err != nil { log.Fatal(err) } @@ -31,7 +31,7 @@ Example of creating floating ips in a project }, } projectID := "49338ac045f448e294b25d013f890317" - newFloatingIPs, _, err := floatingips.Create(ctx, resellClient, projectID, newFloatingIPsOpts) + newFloatingIPs, _, err := floatingips.Create(client, projectID, newFloatingIPsOpts) if err != nil { log.Fatal(err) } @@ -41,7 +41,7 @@ Example of creating floating ips in a project Example of deleting a single floating ip - _, err = floatingips.Delete(ctx, resellClient, "412a04ba-4cb2-4823-abd1-fcd48952b882") + _, err = floatingips.Delete(client, "412a04ba-4cb2-4823-abd1-fcd48952b882") if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/floatingips/requests.go b/selvpcclient/resell/v2/floatingips/requests.go index 85773a1..66103a0 100644 --- a/selvpcclient/resell/v2/floatingips/requests.go +++ b/selvpcclient/resell/v2/floatingips/requests.go @@ -2,20 +2,31 @@ package floatingips import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/google/go-querystring/query" + + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "floatingips" // Get returns a single floating ip by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*FloatingIP, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*FloatingIP, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,18 +47,25 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*F } // List gets a list of floating ips in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts) ([]*FloatingIP, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") +func List(client *selvpcclient.Client, opts ListOpts) ([]*FloatingIP, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } - queryParams, err := selvpcclient.BuildQueryParameters(opts) + url := strings.Join([]string{endpoint, resourceURL}, "/") + + queryParams, err := query.Values(opts) if err != nil { return nil, nil, err } - if queryParams != "" { - url = strings.Join([]string{url, queryParams}, "?") - } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url = strings.Join([]string{url, queryParams.Encode()}, "?") + + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -68,15 +86,23 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts } // Create requests a creation of the floating ip in the specified project. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID string, createOpts FloatingIPOpts) ([]*FloatingIP, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, projectID string, createOpts FloatingIPOpts) ([]*FloatingIP, *clientservices.ResponseResult, error) { createFloatingIPOpts := &createOpts requestBody, err := json.Marshal(createFloatingIPOpts) if err != nil { return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", projectID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", projectID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -97,9 +123,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID s } // Delete deletes a single floating ip by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/floatingips/requests_opts.go b/selvpcclient/resell/v2/floatingips/requests_opts.go index 254a180..fe3bf03 100644 --- a/selvpcclient/resell/v2/floatingips/requests_opts.go +++ b/selvpcclient/resell/v2/floatingips/requests_opts.go @@ -17,5 +17,5 @@ type FloatingIPOpt struct { // ListOpts represents options for the floating ips List request. type ListOpts struct { - Detailed bool `param:"detailed"` + Detailed bool `url:"detailed"` } diff --git a/selvpcclient/resell/v2/floatingips/schemas.go b/selvpcclient/resell/v2/floatingips/schemas.go index 7652e45..ae67fb6 100644 --- a/selvpcclient/resell/v2/floatingips/schemas.go +++ b/selvpcclient/resell/v2/floatingips/schemas.go @@ -1,6 +1,6 @@ package floatingips -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" // FloatingIP represents a single Resell Floating IP. type FloatingIP struct { diff --git a/selvpcclient/resell/v2/floatingips/testing/fixtures.go b/selvpcclient/resell/v2/floatingips/testing/fixtures.go index b49a4c3..7fa48a0 100644 --- a/selvpcclient/resell/v2/floatingips/testing/fixtures.go +++ b/selvpcclient/resell/v2/floatingips/testing/fixtures.go @@ -3,8 +3,8 @@ package testing import ( "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/floatingips" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/floatingips" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" ) // TestGetFloatingIPResponseRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/floatingips/testing/requests_test.go b/selvpcclient/resell/v2/floatingips/testing/requests_test.go index 0ef48ff..302751b 100644 --- a/selvpcclient/resell/v2/floatingips/testing/requests_test.go +++ b/selvpcclient/resell/v2/floatingips/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/floatingips" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/floatingips" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetFloatingIP(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetFloatingIP(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -25,8 +24,7 @@ func TestGetFloatingIP(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := floatingips.Get(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + actual, _, err := floatingips.Get(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err != nil { t.Fatal(err) } @@ -46,7 +44,7 @@ func TestGetFloatingIPWithLB(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -56,8 +54,7 @@ func TestGetFloatingIPWithLB(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := floatingips.Get(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + actual, _, err := floatingips.Get(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err != nil { t.Fatal(err) } @@ -77,7 +74,7 @@ func TestGetFloatingIPHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -87,8 +84,7 @@ func TestGetFloatingIPHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - floatingIP, httpResponse, err := floatingips.Get(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + floatingIP, httpResponse, err := floatingips.Get(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -107,12 +103,11 @@ func TestGetFloatingIPHTTPError(t *testing.T) { func TestGetFloatingIPTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - floatingIP, _, err := floatingips.Get(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + floatingIP, _, err := floatingips.Get(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if floatingIP != nil { t.Fatal("expected no floating ip from the Get method") @@ -127,7 +122,7 @@ func TestGetFloatingIPUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -137,8 +132,7 @@ func TestGetFloatingIPUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - floatingIP, _, err := floatingips.Get(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + floatingIP, _, err := floatingips.Get(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -156,7 +150,7 @@ func TestListFloatingIPs(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips", @@ -166,8 +160,7 @@ func TestListFloatingIPs(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := floatingips.List(ctx, testEnv.Client, floatingips.ListOpts{}) + actual, _, err := floatingips.List(testEnv.Client, floatingips.ListOpts{}) if err != nil { t.Fatal(err) } @@ -192,7 +185,7 @@ func TestListFloatingIPsSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips", @@ -202,8 +195,7 @@ func TestListFloatingIPsSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := floatingips.List(ctx, testEnv.Client, floatingips.ListOpts{}) + actual, _, err := floatingips.List(testEnv.Client, floatingips.ListOpts{}) if err != nil { t.Fatal(err) } @@ -223,7 +215,7 @@ func TestListFloatingIPsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips", @@ -233,8 +225,7 @@ func TestListFloatingIPsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allFloatingIPs, httpResponse, err := floatingips.List(ctx, testEnv.Client, floatingips.ListOpts{}) + allFloatingIPs, httpResponse, err := floatingips.List(testEnv.Client, floatingips.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -253,12 +244,11 @@ func TestListFloatingIPsHTTPError(t *testing.T) { func TestListFloatingIPsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allFloatingIPs, _, err := floatingips.List(ctx, testEnv.Client, floatingips.ListOpts{}) + allFloatingIPs, _, err := floatingips.List(testEnv.Client, floatingips.ListOpts{}) if allFloatingIPs != nil { t.Fatal("expected no floating ips from the List method") @@ -273,7 +263,7 @@ func TestListFloatingIPsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips", @@ -283,8 +273,7 @@ func TestListFloatingIPsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allFloatingIPs, _, err := floatingips.List(ctx, testEnv.Client, floatingips.ListOpts{}) + allFloatingIPs, _, err := floatingips.List(testEnv.Client, floatingips.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -302,7 +291,7 @@ func TestCreateFloatingIPs(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/projects/49338ac045f448e294b25d013f890317", @@ -313,9 +302,8 @@ func TestCreateFloatingIPs(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateFloatingIPOpts - actualResponse, _, err := floatingips.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + actualResponse, _, err := floatingips.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if err != nil { t.Fatal(err) } @@ -335,7 +323,7 @@ func TestCreateFloatingIPsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/projects/49338ac045f448e294b25d013f890317", @@ -346,9 +334,8 @@ func TestCreateFloatingIPsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateFloatingIPOpts - floatingIPs, httpResponse, err := floatingips.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + floatingIPs, httpResponse, err := floatingips.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -367,13 +354,12 @@ func TestCreateFloatingIPsHTTPError(t *testing.T) { func TestCreateFloatingIPsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateFloatingIPOpts - floatingIPs, _, err := floatingips.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + floatingIPs, _, err := floatingips.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if floatingIPs != nil { t.Fatal("expected no floating ips from the Create method") @@ -388,7 +374,7 @@ func TestCreateFloatingIPsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/projects/49338ac045f448e294b25d013f890317", @@ -399,9 +385,8 @@ func TestCreateFloatingIPsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateFloatingIPOpts - floatingIPs, _, err := floatingips.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + floatingIPs, _, err := floatingips.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -419,17 +404,16 @@ func TestDeleteFloatingIP(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := floatingips.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + _, err := floatingips.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err != nil { t.Fatal(err) } @@ -443,7 +427,7 @@ func TestDeleteFloatingIPHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/floatingips/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -452,8 +436,7 @@ func TestDeleteFloatingIPHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := floatingips.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + httpResponse, err := floatingips.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -468,12 +451,11 @@ func TestDeleteFloatingIPHTTPError(t *testing.T) { func TestDeleteFloatingIPTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := floatingips.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + _, err := floatingips.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/keypairs/doc.go b/selvpcclient/resell/v2/keypairs/doc.go index ecbc1ac..002be3a 100644 --- a/selvpcclient/resell/v2/keypairs/doc.go +++ b/selvpcclient/resell/v2/keypairs/doc.go @@ -4,7 +4,7 @@ the Resell v2 API. Example of getting keypairs in the current domain - allKeypairs, _, err = keypairs.List(context, resellClient) + allKeypairs, _, err = keypairs.List(context, client) if err != nil { log.Fatal(err) } @@ -19,7 +19,7 @@ Example of creating keypairs in all regions with the same options PublicKey: "ssh-rsa public_key_part user0@example.org", UserID: "82a026cae2104e92b999dbe00cdb9435", } - newKeypairs, _, err := keypairs.Create(ctx, resellClient, newKeypairOptions) + newKeypairs, _, err := keypairs.Create(client, newKeypairOptions) if err != nil { log.Fatal(err) } @@ -31,7 +31,7 @@ Example of deleting a single keypair of a user keypairName := "my_keypair" userID := 82a026cae2104e92b999dbe00cdb9435"" - _, err = keypairs.Delete(ctx, resellClient, keypairName, userID) + _, err = keypairs.Delete(client, keypairName, userID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/keypairs/requests.go b/selvpcclient/resell/v2/keypairs/requests.go index ee4a17f..991d476 100644 --- a/selvpcclient/resell/v2/keypairs/requests.go +++ b/selvpcclient/resell/v2/keypairs/requests.go @@ -2,20 +2,29 @@ package keypairs import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "keypairs" // List gets a list of keypairs in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Keypair, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func List(client *selvpcclient.Client) ([]*Keypair, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,7 +45,7 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Keypair, } // Create requests a creation of the keypar with the specified options. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts KeypairOpts) ([]*Keypair, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, createOpts KeypairOpts) ([]*Keypair, *clientservices.ResponseResult, error) { // Nest create opts into additional body. type nestedCreateOpts struct { Keypair KeypairOpts `json:"keypair"` @@ -49,8 +58,16 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -71,9 +88,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts } // Delete deletes a single keypair by its name and user ID. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, name, userID string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, name, "users", userID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, name, userID string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, name, "users", userID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/keypairs/testing/fixtures.go b/selvpcclient/resell/v2/keypairs/testing/fixtures.go index c06fe0b..8593089 100644 --- a/selvpcclient/resell/v2/keypairs/testing/fixtures.go +++ b/selvpcclient/resell/v2/keypairs/testing/fixtures.go @@ -1,6 +1,6 @@ package testing -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/keypairs" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/keypairs" // TestListResponseRaw represents a raw response from List requests. const TestListResponseRaw = ` diff --git a/selvpcclient/resell/v2/keypairs/testing/requests_test.go b/selvpcclient/resell/v2/keypairs/testing/requests_test.go index 7a35eec..7847a08 100644 --- a/selvpcclient/resell/v2/keypairs/testing/requests_test.go +++ b/selvpcclient/resell/v2/keypairs/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/keypairs" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/keypairs" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestListKeypairs(t *testing.T) { @@ -15,7 +14,7 @@ func TestListKeypairs(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -25,8 +24,7 @@ func TestListKeypairs(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := keypairs.List(ctx, testEnv.Client) + actual, _, err := keypairs.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -47,7 +45,7 @@ func TestListKeypairsSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -57,8 +55,7 @@ func TestListKeypairsSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := keypairs.List(ctx, testEnv.Client) + actual, _, err := keypairs.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -76,7 +73,7 @@ func TestListKeypairsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -86,8 +83,7 @@ func TestListKeypairsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allKeypairs, httpResponse, err := keypairs.List(ctx, testEnv.Client) + allKeypairs, httpResponse, err := keypairs.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -106,12 +102,11 @@ func TestListKeypairsHTTPError(t *testing.T) { func TestListKeypairsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allKeypairs, _, err := keypairs.List(ctx, testEnv.Client) + allKeypairs, _, err := keypairs.List(testEnv.Client) if allKeypairs != nil { t.Fatal("expected no keypairs from the List method") @@ -126,7 +121,7 @@ func TestListKeypairsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -136,8 +131,7 @@ func TestListKeypairsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allKeypairs, _, err := keypairs.List(ctx, testEnv.Client) + allKeypairs, _, err := keypairs.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -155,7 +149,7 @@ func TestCreateKeypairs(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -166,9 +160,8 @@ func TestCreateKeypairs(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateKeypairOpts - actualResponse, _, err := keypairs.Create(ctx, testEnv.Client, createOpts) + actualResponse, _, err := keypairs.Create(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -188,7 +181,7 @@ func TestCreateKeypairsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -199,9 +192,8 @@ func TestCreateKeypairsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateKeypairOpts - l, httpResponse, err := keypairs.Create(ctx, testEnv.Client, createOpts) + l, httpResponse, err := keypairs.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -220,13 +212,12 @@ func TestCreateKeypairsHTTPError(t *testing.T) { func TestCreateKeypairsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateKeypairOpts - l, _, err := keypairs.Create(ctx, testEnv.Client, createOpts) + l, _, err := keypairs.Create(testEnv.Client, createOpts) if l != nil { t.Fatal("expected no keypairs from the Create method") @@ -241,7 +232,7 @@ func TestCreateKeypairsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs", @@ -252,9 +243,8 @@ func TestCreateKeypairsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateKeypairOpts - l, _, err := keypairs.Create(ctx, testEnv.Client, createOpts) + l, _, err := keypairs.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -272,17 +262,16 @@ func TestDeleteKeypair(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs/key1/users/82a026cae2104e92b999dbe00cdb9435", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := keypairs.Delete(ctx, testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") + _, err := keypairs.Delete(testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") if err != nil { t.Fatal(err) } @@ -296,7 +285,7 @@ func TestDeleteKeypairHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/keypairs/key1/users/82a026cae2104e92b999dbe00cdb9435", @@ -305,8 +294,7 @@ func TestDeleteKeypairHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := keypairs.Delete(ctx, testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") + httpResponse, err := keypairs.Delete(testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -321,12 +309,11 @@ func TestDeleteKeypairHTTPError(t *testing.T) { func TestDeleteKeypairTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := keypairs.Delete(ctx, testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") + _, err := keypairs.Delete(testEnv.Client, "key1", "82a026cae2104e92b999dbe00cdb9435") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/licenses/doc.go b/selvpcclient/resell/v2/licenses/doc.go index 4f4c8ed..1748ce9 100644 --- a/selvpcclient/resell/v2/licenses/doc.go +++ b/selvpcclient/resell/v2/licenses/doc.go @@ -4,7 +4,7 @@ the Resell v2 API. Example of getting a single license referenced by its id - license, _, err := licenses.Get(context, resellClient, licenseID) + license, _, err := licenses.Get(context, client, licenseID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single license referenced by its id Example of getting all licenses - allLicenses, _, err := licenses.List(ctx, resellClient, licenses.ListOpts{}) + allLicenses, _, err := licenses.List(client, licenses.ListOpts{}) if err != nil { log.Fatal(err) } @@ -32,7 +32,7 @@ Example of creating licenses in a project }, } projectID := "49338ac045f448e294b25d013f890317" - newLicenses, _, err := licenses.Create(ctx, resellClient, projectID, newLicensesOptions) + newLicenses, _, err := licenses.Create(client, projectID, newLicensesOptions) if err != nil { log.Fatal(err) } @@ -42,7 +42,7 @@ Example of creating licenses in a project Example of deleting a single license - _, err = licenses.Delete(ctx, resellClient, "5232d5f3-4950-454b-bd41-78c5295622cd") + _, err = licenses.Delete(client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/licenses/requests.go b/selvpcclient/resell/v2/licenses/requests.go index eb9a432..c719a77 100644 --- a/selvpcclient/resell/v2/licenses/requests.go +++ b/selvpcclient/resell/v2/licenses/requests.go @@ -2,20 +2,31 @@ package licenses import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/google/go-querystring/query" + + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "licenses" // Get returns a single license by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*License, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*License, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,18 +47,25 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*L } // List gets a list of licenses in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts) ([]*License, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") +func List(client *selvpcclient.Client, opts ListOpts) ([]*License, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } - queryParams, err := selvpcclient.BuildQueryParameters(opts) + url := strings.Join([]string{endpoint, resourceURL}, "/") + + queryParams, err := query.Values(opts) if err != nil { return nil, nil, err } - if queryParams != "" { - url = strings.Join([]string{url, queryParams}, "?") - } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url = strings.Join([]string{url, queryParams.Encode()}, "?") + + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -68,15 +86,23 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts } // Create requests a creation of the licenses in the specified project. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID string, createOpts LicenseOpts) ([]*License, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, projectID string, createOpts LicenseOpts) ([]*License, *clientservices.ResponseResult, error) { createLicenseOpts := &createOpts requestBody, err := json.Marshal(createLicenseOpts) if err != nil { return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", projectID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", projectID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -97,9 +123,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID s } // Delete deletes a single license by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/licenses/requests_opts.go b/selvpcclient/resell/v2/licenses/requests_opts.go index 9fa037a..df272da 100644 --- a/selvpcclient/resell/v2/licenses/requests_opts.go +++ b/selvpcclient/resell/v2/licenses/requests_opts.go @@ -20,5 +20,5 @@ type LicenseOpt struct { // ListOpts represents options for the licenses List request. type ListOpts struct { - Detailed bool `param:"detailed"` + Detailed bool `url:"detailed"` } diff --git a/selvpcclient/resell/v2/licenses/schemas.go b/selvpcclient/resell/v2/licenses/schemas.go index 8d9182d..31ff209 100644 --- a/selvpcclient/resell/v2/licenses/schemas.go +++ b/selvpcclient/resell/v2/licenses/schemas.go @@ -1,6 +1,6 @@ package licenses -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" // License represents a single Resell License. type License struct { diff --git a/selvpcclient/resell/v2/licenses/testing/fixtures.go b/selvpcclient/resell/v2/licenses/testing/fixtures.go index 1cb4e3a..4d439ee 100644 --- a/selvpcclient/resell/v2/licenses/testing/fixtures.go +++ b/selvpcclient/resell/v2/licenses/testing/fixtures.go @@ -3,8 +3,8 @@ package testing import ( "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/licenses" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/licenses" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" ) // TestGetLicenseResponseRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/licenses/testing/requests_test.go b/selvpcclient/resell/v2/licenses/testing/requests_test.go index c06b7b8..112b0f5 100644 --- a/selvpcclient/resell/v2/licenses/testing/requests_test.go +++ b/selvpcclient/resell/v2/licenses/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/licenses" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/licenses" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetLicense(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetLicense(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/123123", @@ -25,8 +24,7 @@ func TestGetLicense(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := licenses.Get(ctx, testEnv.Client, "123123") + actual, _, err := licenses.Get(testEnv.Client, "123123") if err != nil { t.Fatal(err) } @@ -46,7 +44,7 @@ func TestGetLicenseHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/123123", @@ -56,8 +54,7 @@ func TestGetLicenseHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - license, httpResponse, err := licenses.Get(ctx, testEnv.Client, "123123") + license, httpResponse, err := licenses.Get(testEnv.Client, "123123") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -76,12 +73,11 @@ func TestGetLicenseHTTPError(t *testing.T) { func TestGetLicenseTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - license, _, err := licenses.Get(ctx, testEnv.Client, "123123") + license, _, err := licenses.Get(testEnv.Client, "123123") if license != nil { t.Fatal("expected no license from the Get method") @@ -96,7 +92,7 @@ func TestGetLicenseUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/123123", @@ -106,8 +102,7 @@ func TestGetLicenseUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - license, _, err := licenses.Get(ctx, testEnv.Client, "123123") + license, _, err := licenses.Get(testEnv.Client, "123123") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -125,7 +120,7 @@ func TestListLicenses(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses", @@ -135,8 +130,7 @@ func TestListLicenses(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := licenses.List(ctx, testEnv.Client, licenses.ListOpts{}) + actual, _, err := licenses.List(testEnv.Client, licenses.ListOpts{}) if err != nil { t.Fatal(err) } @@ -161,7 +155,7 @@ func TestListLicensesSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses", @@ -171,8 +165,7 @@ func TestListLicensesSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := licenses.List(ctx, testEnv.Client, licenses.ListOpts{}) + actual, _, err := licenses.List(testEnv.Client, licenses.ListOpts{}) if err != nil { t.Fatal(err) } @@ -192,7 +185,7 @@ func TestListLicensesHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses", @@ -202,8 +195,7 @@ func TestListLicensesHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allLicenses, httpResponse, err := licenses.List(ctx, testEnv.Client, licenses.ListOpts{}) + allLicenses, httpResponse, err := licenses.List(testEnv.Client, licenses.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -222,12 +214,11 @@ func TestListLicensesHTTPError(t *testing.T) { func TestListLicensesTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allLicenses, _, err := licenses.List(ctx, testEnv.Client, licenses.ListOpts{}) + allLicenses, _, err := licenses.List(testEnv.Client, licenses.ListOpts{}) if allLicenses != nil { t.Fatal("expected no licenses from the List method") @@ -242,7 +233,7 @@ func TestListLicensesUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses", @@ -252,8 +243,7 @@ func TestListLicensesUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allLicenses, _, err := licenses.List(ctx, testEnv.Client, licenses.ListOpts{}) + allLicenses, _, err := licenses.List(testEnv.Client, licenses.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -271,7 +261,7 @@ func TestCreateLicenses(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/projects/49338ac045f448e294b25d013f890317", @@ -282,9 +272,8 @@ func TestCreateLicenses(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateLicenseOpts - actualResponse, _, err := licenses.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + actualResponse, _, err := licenses.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if err != nil { t.Fatal(err) } @@ -304,7 +293,7 @@ func TestCreateLicensesHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/projects/49338ac045f448e294b25d013f890317", @@ -315,9 +304,8 @@ func TestCreateLicensesHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateLicenseOpts - l, httpResponse, err := licenses.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + l, httpResponse, err := licenses.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -336,13 +324,12 @@ func TestCreateLicensesHTTPError(t *testing.T) { func TestCreateLicensesTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateLicenseOpts - l, _, err := licenses.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + l, _, err := licenses.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if l != nil { t.Fatal("expected no licenses from the Create method") @@ -357,7 +344,7 @@ func TestCreateLicensesUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/projects/49338ac045f448e294b25d013f890317", @@ -368,9 +355,8 @@ func TestCreateLicensesUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateLicenseOpts - l, _, err := licenses.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + l, _, err := licenses.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -388,17 +374,16 @@ func TestDeleteLicense(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/5232d5f3-4950-454b-bd41-78c5295622cd", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := licenses.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + _, err := licenses.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err != nil { t.Fatal(err) } @@ -412,7 +397,7 @@ func TestDeleteLicenseHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/licenses/5232d5f3-4950-454b-bd41-78c5295622cd", @@ -421,8 +406,7 @@ func TestDeleteLicenseHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := licenses.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + httpResponse, err := licenses.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -437,12 +421,11 @@ func TestDeleteLicenseHTTPError(t *testing.T) { func TestDeleteLicenseTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := licenses.Delete(ctx, testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") + _, err := licenses.Delete(testEnv.Client, "5232d5f3-4950-454b-bd41-78c5295622cd") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/projects/doc.go b/selvpcclient/resell/v2/projects/doc.go index 61014c6..f4e6c10 100644 --- a/selvpcclient/resell/v2/projects/doc.go +++ b/selvpcclient/resell/v2/projects/doc.go @@ -4,7 +4,7 @@ Resell v2 API. Example of getting a single project referenced by its id - project, _, err := projects.Get(context, resellClient, projectID) + project, _, err := projects.Get(context, client, projectID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single project referenced by its id Example of listing all projects in the domain - allProjects, _, err := projects.List(context, resellClient) + allProjects, _, err := projects.List(context, client) if err != nil { log.Fatal(err) } @@ -25,7 +25,7 @@ Example of creating a single project createOpts := projects.CreateOpts{ Name: "test000", } - newProject, _, err := projects.Create(context, resellClient, createOpts) + newProject, _, err := projects.Create(context, client, createOpts) if err != nil { log.Fatal(err) } @@ -44,7 +44,7 @@ Example of updating a single project Name: &name, Theme: &themeUpdateOpts, } - updatedProject, _, err := projects.Update(context, resellClient, newProject.ID, updateOpts) + updatedProject, _, err := projects.Update(context, client, newProject.ID, updateOpts) if err != nil { log.Fatal(err) } @@ -52,7 +52,7 @@ Example of updating a single project Example of deleting a single project - _, err = projects.Delete(context, resellClient, newProject.ID) + _, err = projects.Delete(context, client, newProject.ID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/projects/requests.go b/selvpcclient/resell/v2/projects/requests.go index 610f56d..0d940dc 100644 --- a/selvpcclient/resell/v2/projects/requests.go +++ b/selvpcclient/resell/v2/projects/requests.go @@ -2,20 +2,29 @@ package projects import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "projects" // Get returns a single project by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*Project, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*Project, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,9 +45,17 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*P } // List gets a list of projects in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Project, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func List(client *selvpcclient.Client) ([]*Project, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -59,7 +76,7 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Project, } // Create requests a creation of the project. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts CreateOpts) (*Project, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, createOpts CreateOpts) (*Project, *clientservices.ResponseResult, error) { // Nest create options into the parent "project" JSON structure. type createProject struct { Options CreateOpts `json:"project"` @@ -70,8 +87,16 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -92,7 +117,7 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts } // Update requests an update of the project referenced by its id. -func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, updateOpts UpdateOpts) (*Project, *selvpcclient.ResponseResult, error) { +func Update(client *selvpcclient.Client, id string, updateOpts UpdateOpts) (*Project, *clientservices.ResponseResult, error) { // Nest update options into the parent "project" JSON structure. type updateProject struct { Options UpdateOpts `json:"project"` @@ -103,8 +128,16 @@ func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPatch, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPatch, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -125,9 +158,17 @@ func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, } // Delete deletes a single project by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/projects/schemas.go b/selvpcclient/resell/v2/projects/schemas.go index 337f3d4..b2e1fb7 100644 --- a/selvpcclient/resell/v2/projects/schemas.go +++ b/selvpcclient/resell/v2/projects/schemas.go @@ -3,7 +3,7 @@ package projects import ( "encoding/json" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/quotas" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/quotas" ) // Project represents a single Identity service project. diff --git a/selvpcclient/resell/v2/projects/testing/fixtures.go b/selvpcclient/resell/v2/projects/testing/fixtures.go index 661bfe4..1e8c548 100644 --- a/selvpcclient/resell/v2/projects/testing/fixtures.go +++ b/selvpcclient/resell/v2/projects/testing/fixtures.go @@ -1,7 +1,7 @@ package testing import ( - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/projects" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/projects" ) // TestGetProjectResponseRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/projects/testing/requests_test.go b/selvpcclient/resell/v2/projects/testing/requests_test.go index 2555737..ab5a513 100644 --- a/selvpcclient/resell/v2/projects/testing/requests_test.go +++ b/selvpcclient/resell/v2/projects/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/projects" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/projects" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetProject(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetProject(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/49338ac045f448e294b25d013f890317", @@ -25,8 +24,7 @@ func TestGetProject(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := projects.Get(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + actual, _, err := projects.Get(testEnv.Client, "49338ac045f448e294b25d013f890317") if err != nil { t.Fatal(err) } @@ -44,7 +42,7 @@ func TestGetProjectSingleQuota(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/49338ac045f448e294b25d013f890317", @@ -54,8 +52,7 @@ func TestGetProjectSingleQuota(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := projects.Get(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + actual, _, err := projects.Get(testEnv.Client, "49338ac045f448e294b25d013f890317") if err != nil { t.Fatal(err) } @@ -75,7 +72,7 @@ func TestGetProjectHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/49338ac045f448e294b25d013f890317", @@ -85,8 +82,7 @@ func TestGetProjectHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - project, httpResponse, err := projects.Get(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + project, httpResponse, err := projects.Get(testEnv.Client, "49338ac045f448e294b25d013f890317") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -105,12 +101,11 @@ func TestGetProjectHTTPError(t *testing.T) { func TestGetProjectTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - project, _, err := projects.Get(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + project, _, err := projects.Get(testEnv.Client, "49338ac045f448e294b25d013f890317") if project != nil { t.Fatal("expected no project from the Get method") @@ -125,7 +120,7 @@ func TestGetProjectUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/49338ac045f448e294b25d013f890317", @@ -135,8 +130,7 @@ func TestGetProjectUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - project, _, err := projects.Get(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + project, _, err := projects.Get(testEnv.Client, "49338ac045f448e294b25d013f890317") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -154,7 +148,7 @@ func TestListProjects(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -164,8 +158,7 @@ func TestListProjects(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := projects.List(ctx, testEnv.Client) + actual, _, err := projects.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -186,7 +179,7 @@ func TestListProjectsSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -196,8 +189,7 @@ func TestListProjectsSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := projects.List(ctx, testEnv.Client) + actual, _, err := projects.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -217,7 +209,7 @@ func TestListProjectsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -227,8 +219,7 @@ func TestListProjectsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allProjects, httpResponse, err := projects.List(ctx, testEnv.Client) + allProjects, httpResponse, err := projects.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -247,12 +238,11 @@ func TestListProjectsHTTPError(t *testing.T) { func TestListProjectsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allProjects, _, err := projects.List(ctx, testEnv.Client) + allProjects, _, err := projects.List(testEnv.Client) if allProjects != nil { t.Fatal("expected no projects from the List method") @@ -267,7 +257,7 @@ func TestListProjectsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -277,8 +267,7 @@ func TestListProjectsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allProjects, _, err := projects.List(ctx, testEnv.Client) + allProjects, _, err := projects.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -296,7 +285,7 @@ func TestCreateProject(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -307,9 +296,8 @@ func TestCreateProject(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateProjectOpts - actualResponse, _, err := projects.Create(ctx, testEnv.Client, createOpts) + actualResponse, _, err := projects.Create(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -329,7 +317,7 @@ func TestCreateProjectsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -340,9 +328,8 @@ func TestCreateProjectsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateProjectOpts - project, httpResponse, err := projects.Create(ctx, testEnv.Client, createOpts) + project, httpResponse, err := projects.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -361,13 +348,12 @@ func TestCreateProjectsHTTPError(t *testing.T) { func TestCreateProjectsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateProjectOpts - project, _, err := projects.Create(ctx, testEnv.Client, createOpts) + project, _, err := projects.Create(testEnv.Client, createOpts) if project != nil { t.Fatal("expected no project from the Create method") @@ -382,7 +368,7 @@ func TestCreateProjectsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects", @@ -393,9 +379,8 @@ func TestCreateProjectsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateProjectOpts - project, _, err := projects.Create(ctx, testEnv.Client, createOpts) + project, _, err := projects.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -413,7 +398,7 @@ func TestUpdateProject(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/f9ede488e5f14bac8962d8c53d0af9f4", @@ -424,9 +409,8 @@ func TestUpdateProject(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateProjectOpts - actualResponse, _, err := projects.Update(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) + actualResponse, _, err := projects.Update(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) if err != nil { t.Fatal(err) } @@ -446,7 +430,7 @@ func TestUpdateProjectHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/f9ede488e5f14bac8962d8c53d0af9f4", @@ -456,9 +440,8 @@ func TestUpdateProjectHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateProjectOpts - project, httpResponse, err := projects.Update(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) + project, httpResponse, err := projects.Update(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -476,13 +459,12 @@ func TestUpdateProjectHTTPError(t *testing.T) { func TestUpdateProjectTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() updateOpts := TestUpdateProjectOpts - project, _, err := projects.Update(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) + project, _, err := projects.Update(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) if project != nil { t.Fatal("expected no project from the Update method") @@ -497,7 +479,7 @@ func TestUpdateProjectUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/f9ede488e5f14bac8962d8c53d0af9f4", @@ -508,9 +490,8 @@ func TestUpdateProjectUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateProjectOpts - project, _, err := projects.Update(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) + project, _, err := projects.Update(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4", updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -528,17 +509,16 @@ func TestDeleteProject(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/f9ede488e5f14bac8962d8c53d0af9f4", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := projects.Delete(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") + _, err := projects.Delete(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") if err != nil { t.Fatal(err) } @@ -552,7 +532,7 @@ func TestDeleteProjectHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/projects/f9ede488e5f14bac8962d8c53d0af9f4", @@ -561,8 +541,7 @@ func TestDeleteProjectHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := projects.Delete(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") + httpResponse, err := projects.Delete(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -577,12 +556,11 @@ func TestDeleteProjectHTTPError(t *testing.T) { func TestDeleteProjectTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := projects.Delete(ctx, testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") + _, err := projects.Delete(testEnv.Client, "f9ede488e5f14bac8962d8c53d0af9f4") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/roles/doc.go b/selvpcclient/resell/v2/roles/doc.go index 6f75da3..e0dc195 100644 --- a/selvpcclient/resell/v2/roles/doc.go +++ b/selvpcclient/resell/v2/roles/doc.go @@ -4,7 +4,7 @@ Resell v2 API. Example of getting roles in the current domain - allRoles, _, err = roles.List(context, resellClient) + allRoles, _, err = roles.List(context, client) if err != nil { log.Fatal(err) } @@ -14,7 +14,7 @@ Example of getting roles in the current domain Example of getting roles in the specified project - allRoles, _, err := roles.ListProject(context, resellClient, projectID) + allRoles, _, err := roles.ListProject(context, client, projectID) if err != nil { log.Fatal(err) } @@ -24,7 +24,7 @@ Example of getting roles in the specified project Example of getting roles for the specified user - allRoles, _, err := roles.ListUser(context, resellClient, userID) + allRoles, _, err := roles.ListUser(context, client, userID) if err != nil { log.Fatal(err) } @@ -38,7 +38,7 @@ Example of creating a single role ProjectID: "49338ac045f448e294b25d013f890317", UserID: "763eecfaeb0c8e9b76ab12a82eb4c11", } - role, _, err := roles.Create(ctx, resellClient, createOpts) + role, _, err := roles.Create(client, createOpts) if err != nil { log.Fatal(err) } @@ -58,7 +58,7 @@ Example of creating several roles }, }, } - allRoles, httpResponse, err := roles.CreateBulk(ctx, testEnv.Client, createOpts) + allRoles, httpResponse, err := roles.CreateBulk(testEnv.Client, createOpts) for _, myRole := range allRoles { fmt.Println(myRole) } @@ -69,7 +69,7 @@ Example of deleting a single role ProjectID: "49338ac045f448e294b25d013f890317", UserID: "763eecfaeb0c8e9b76ab12a82eb4c11", } - _, err := roles.Delete(ctx, resellClient, deleteOpts) + _, err := roles.Delete(client, deleteOpts) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/roles/requests.go b/selvpcclient/resell/v2/roles/requests.go index 7e9aca6..a438a12 100644 --- a/selvpcclient/resell/v2/roles/requests.go +++ b/selvpcclient/resell/v2/roles/requests.go @@ -2,20 +2,29 @@ package roles import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "roles" // List returns all roles in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Role, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func List(client *selvpcclient.Client) ([]*Role, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,9 +45,17 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Role, *se } // ListProject returns all roles in the specified project. -func ListProject(ctx context.Context, client *selvpcclient.ServiceClient, id string) ([]*Role, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func ListProject(client *selvpcclient.Client, id string) ([]*Role, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -59,9 +76,17 @@ func ListProject(ctx context.Context, client *selvpcclient.ServiceClient, id str } // ListUser returns all roles that are associated with the specified user. -func ListUser(ctx context.Context, client *selvpcclient.ServiceClient, id string) ([]*Role, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, "users", id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func ListUser(client *selvpcclient.Client, id string) ([]*Role, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "users", id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -82,9 +107,17 @@ func ListUser(ctx context.Context, client *selvpcclient.ServiceClient, id string } // Create requests a creation of the single role for the specified project and user. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts RoleOpt) (*Role, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", createOpts.ProjectID, "users", createOpts.UserID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, nil) +func Create(client *selvpcclient.Client, createOpts RoleOpt) (*Role, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", createOpts.ProjectID, "users", createOpts.UserID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -105,15 +138,23 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts } // CreateBulk requests a creation of several roles. -func CreateBulk(ctx context.Context, client *selvpcclient.ServiceClient, createOpts RoleOpts) ([]*Role, *selvpcclient.ResponseResult, error) { +func CreateBulk(client *selvpcclient.Client, createOpts RoleOpts) ([]*Role, *clientservices.ResponseResult, error) { createRolesOpts := &createOpts requestBody, err := json.Marshal(createRolesOpts) if err != nil { return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200, 208}, + }) if err != nil { return nil, nil, err } @@ -134,9 +175,17 @@ func CreateBulk(ctx context.Context, client *selvpcclient.ServiceClient, createO } // Delete requests a deletion of the single role for the specified project and user. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, deleteOpts RoleOpt) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", deleteOpts.ProjectID, "users", deleteOpts.UserID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, deleteOpts RoleOpt) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", deleteOpts.ProjectID, "users", deleteOpts.UserID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/roles/testing/fixtures.go b/selvpcclient/resell/v2/roles/testing/fixtures.go index 879eced..5b04bee 100644 --- a/selvpcclient/resell/v2/roles/testing/fixtures.go +++ b/selvpcclient/resell/v2/roles/testing/fixtures.go @@ -1,6 +1,6 @@ package testing -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/roles" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/roles" // TestListResponseRaw represents a raw response from List requests. const TestListResponseRaw = ` diff --git a/selvpcclient/resell/v2/roles/testing/requests_test.go b/selvpcclient/resell/v2/roles/testing/requests_test.go index b810bb6..cdb9d87 100644 --- a/selvpcclient/resell/v2/roles/testing/requests_test.go +++ b/selvpcclient/resell/v2/roles/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/roles" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/roles" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestListRoles(t *testing.T) { @@ -15,7 +14,7 @@ func TestListRoles(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -25,8 +24,7 @@ func TestListRoles(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.List(ctx, testEnv.Client) + actual, _, err := roles.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -47,7 +45,7 @@ func TestListRolesSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -57,8 +55,7 @@ func TestListRolesSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.List(ctx, testEnv.Client) + actual, _, err := roles.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -76,7 +73,7 @@ func TestListRolesHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -86,8 +83,7 @@ func TestListRolesHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, httpResponse, err := roles.List(ctx, testEnv.Client) + allRoles, httpResponse, err := roles.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -106,12 +102,11 @@ func TestListRolesHTTPError(t *testing.T) { func TestListRolesTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allRoles, _, err := roles.List(ctx, testEnv.Client) + allRoles, _, err := roles.List(testEnv.Client) if allRoles != nil { t.Fatal("expected no roles from the List method") @@ -126,7 +121,7 @@ func TestListRolesUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -136,8 +131,7 @@ func TestListRolesUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, _, err := roles.List(ctx, testEnv.Client) + allRoles, _, err := roles.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -155,7 +149,7 @@ func TestListRolesProject(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", @@ -165,8 +159,7 @@ func TestListRolesProject(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + actual, _, err := roles.ListProject(testEnv.Client, "49338ac045f448e294b25d013f890317") if err != nil { t.Fatal(err) } @@ -191,7 +184,7 @@ func TestListRolesProjectSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", @@ -201,8 +194,7 @@ func TestListRolesProjectSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + actual, _, err := roles.ListProject(testEnv.Client, "49338ac045f448e294b25d013f890317") if err != nil { t.Fatal(err) } @@ -222,7 +214,7 @@ func TestListRolesProjectHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", @@ -232,8 +224,7 @@ func TestListRolesProjectHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, httpResponse, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + allRoles, httpResponse, err := roles.ListProject(testEnv.Client, "49338ac045f448e294b25d013f890317") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -252,12 +243,11 @@ func TestListRolesProjectHTTPError(t *testing.T) { func TestListRolesProjectTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allRoles, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + allRoles, _, err := roles.ListProject(testEnv.Client, "49338ac045f448e294b25d013f890317") if allRoles != nil { t.Fatal("expected no roles from the List method") @@ -272,7 +262,7 @@ func TestListRolesProjectUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", @@ -282,8 +272,7 @@ func TestListRolesProjectUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + allRoles, _, err := roles.ListProject(testEnv.Client, "49338ac045f448e294b25d013f890317") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -301,7 +290,7 @@ func TestListRolesUser(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -311,8 +300,7 @@ func TestListRolesUser(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.ListUser(ctx, testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") + actual, _, err := roles.ListUser(testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") if err != nil { t.Fatal(err) } @@ -337,7 +325,7 @@ func TestListRolesUserSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -347,8 +335,7 @@ func TestListRolesUserSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := roles.ListUser(ctx, testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") + actual, _, err := roles.ListUser(testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") if err != nil { t.Fatal(err) } @@ -368,7 +355,7 @@ func TestListRolesUserHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -378,8 +365,7 @@ func TestListRolesUserHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, httpResponse, err := roles.ListUser(ctx, testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") + allRoles, httpResponse, err := roles.ListUser(testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -398,12 +384,11 @@ func TestListRolesUserHTTPError(t *testing.T) { func TestListRolesUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allRoles, _, err := roles.ListUser(ctx, testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") + allRoles, _, err := roles.ListUser(testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") if allRoles != nil { t.Fatal("expected no roles from the List method") @@ -418,7 +403,7 @@ func TestListRolesUserUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -428,8 +413,7 @@ func TestListRolesUserUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allRoles, _, err := roles.ListUser(ctx, testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") + allRoles, _, err := roles.ListUser(testEnv.Client, "763eecfaeb0c8e9b76ab12a82eb4c11") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -447,7 +431,7 @@ func TestCreateRole(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -457,9 +441,8 @@ func TestCreateRole(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestRoleOpt - actual, _, err := roles.Create(ctx, testEnv.Client, createOpts) + actual, _, err := roles.Create(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -479,7 +462,7 @@ func TestCreateRoleHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -489,9 +472,8 @@ func TestCreateRoleHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestRoleOpt - role, httpResponse, err := roles.Create(ctx, testEnv.Client, createOpts) + role, httpResponse, err := roles.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -510,13 +492,12 @@ func TestCreateRoleHTTPError(t *testing.T) { func TestCreateRoleTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestRoleOpt - role, _, err := roles.Create(ctx, testEnv.Client, createOpts) + role, _, err := roles.Create(testEnv.Client, createOpts) if role != nil { t.Fatal("expected no role from the Create method") @@ -531,7 +512,7 @@ func TestCreateRoleUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -541,9 +522,8 @@ func TestCreateRoleUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestRoleOpt - role, _, err := roles.Create(ctx, testEnv.Client, createOpts) + role, _, err := roles.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -561,7 +541,7 @@ func TestCreateRolesBulk(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -572,9 +552,8 @@ func TestCreateRolesBulk(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateRolesOpts - actual, _, err := roles.CreateBulk(ctx, testEnv.Client, createOpts) + actual, _, err := roles.CreateBulk(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -599,7 +578,7 @@ func TestCreateRolesBulkHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -610,9 +589,8 @@ func TestCreateRolesBulkHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateRolesOpts - allRoles, httpResponse, err := roles.CreateBulk(ctx, testEnv.Client, createOpts) + allRoles, httpResponse, err := roles.CreateBulk(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -631,13 +609,12 @@ func TestCreateRolesBulkHTTPError(t *testing.T) { func TestCreateRolesBulkTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateRolesOpts - allRoles, _, err := roles.CreateBulk(ctx, testEnv.Client, createOpts) + allRoles, _, err := roles.CreateBulk(testEnv.Client, createOpts) if allRoles != nil { t.Fatal("expected no role from the CreateBulk method") @@ -652,7 +629,7 @@ func TestCreateRolesBulkUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles", @@ -663,9 +640,8 @@ func TestCreateRolesBulkUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateRolesOpts - allRoles, _, err := roles.CreateBulk(ctx, testEnv.Client, createOpts) + allRoles, _, err := roles.CreateBulk(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -683,18 +659,17 @@ func TestDeleteRole(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317/users/763eecfaeb0c8e9b76ab12a82eb4c11", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() deleteOpts := TestRoleOpt - _, err := roles.Delete(ctx, testEnv.Client, deleteOpts) + _, err := roles.Delete(testEnv.Client, deleteOpts) if err != nil { t.Fatal(err) } @@ -708,7 +683,7 @@ func TestDeleteRoleHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317/users/763eecfaeb0c8e9b76ab12a82eb4c11", @@ -717,9 +692,8 @@ func TestDeleteRoleHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() deleteOpts := TestRoleOpt - httpResponse, err := roles.Delete(ctx, testEnv.Client, deleteOpts) + httpResponse, err := roles.Delete(testEnv.Client, deleteOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -734,13 +708,12 @@ func TestDeleteRoleHTTPError(t *testing.T) { func TestDeleteRoleTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() deleteOpts := TestRoleOpt - _, err := roles.Delete(ctx, testEnv.Client, deleteOpts) + _, err := roles.Delete(testEnv.Client, deleteOpts) if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/subnets/doc.go b/selvpcclient/resell/v2/subnets/doc.go index c283028..25693a3 100644 --- a/selvpcclient/resell/v2/subnets/doc.go +++ b/selvpcclient/resell/v2/subnets/doc.go @@ -4,7 +4,7 @@ the Resell v2 API. Example of getting a single subnet referenced by its id - subnet, _, err := subnets.Get(context, resellClient, subnetID) + subnet, _, err := subnets.Get(context, client, subnetID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single subnet referenced by its id Example of getting all subnets - allSubnets, _, err := subnets.List(ctx, resellClient, subnets.ListOpts{}) + allSubnets, _, err := subnets.List(client, subnets.ListOpts{}) if err != nil { log.Fatal(err) } @@ -32,7 +32,7 @@ Example of creating subnets }, }, } - newSubnets, _, err := subnets.Create(ctx, resellClient, projectID, createOpts) + newSubnets, _, err := subnets.Create(client, projectID, createOpts) if err != nil { log.Fatal(err) } @@ -42,7 +42,7 @@ Example of creating subnets Example of deleting a single subnet - _, err = subnets.Delete(ctx, resellClient, subnetID) + _, err = subnets.Delete(client, subnetID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/subnets/requests.go b/selvpcclient/resell/v2/subnets/requests.go index 552de41..3b16653 100644 --- a/selvpcclient/resell/v2/subnets/requests.go +++ b/selvpcclient/resell/v2/subnets/requests.go @@ -2,20 +2,31 @@ package subnets import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/google/go-querystring/query" + + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "subnets" // Get returns a single subnet by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*Subnet, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*Subnet, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,18 +47,25 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*S } // List gets a list of subnets in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts) ([]*Subnet, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") +func List(client *selvpcclient.Client, opts ListOpts) ([]*Subnet, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } - queryParams, err := selvpcclient.BuildQueryParameters(opts) + url := strings.Join([]string{endpoint, resourceURL}, "/") + + queryParams, err := query.Values(opts) if err != nil { return nil, nil, err } - if queryParams != "" { - url = strings.Join([]string{url, queryParams}, "?") - } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url = strings.Join([]string{url, queryParams.Encode()}, "?") + + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -68,15 +86,23 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts } // Create requests a creation of the subnets in the specified project. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID string, createOpts SubnetOpts) ([]*Subnet, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, projectID string, createOpts SubnetOpts) ([]*Subnet, *clientservices.ResponseResult, error) { createSubnetsOpts := &createOpts requestBody, err := json.Marshal(createSubnetsOpts) if err != nil { return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", projectID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", projectID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -97,9 +123,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID s } // Delete deletes a single subnet by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/subnets/requests_opts.go b/selvpcclient/resell/v2/subnets/requests_opts.go index 7e1928c..93c8489 100644 --- a/selvpcclient/resell/v2/subnets/requests_opts.go +++ b/selvpcclient/resell/v2/subnets/requests_opts.go @@ -1,6 +1,6 @@ package subnets -import "github.com/selectel/go-selvpcclient/v2/selvpcclient" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient" // SubnetOpts represents options for the subnets Create request. type SubnetOpts struct { @@ -25,5 +25,5 @@ type SubnetOpt struct { // ListOpts represents options for the licenses List request. type ListOpts struct { - Detailed bool `param:"detailed"` + Detailed bool `url:"detailed"` } diff --git a/selvpcclient/resell/v2/subnets/schemas.go b/selvpcclient/resell/v2/subnets/schemas.go index b533f44..8de11ac 100644 --- a/selvpcclient/resell/v2/subnets/schemas.go +++ b/selvpcclient/resell/v2/subnets/schemas.go @@ -1,6 +1,6 @@ package subnets -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" // Subnet represents a single Resell subnet. type Subnet struct { diff --git a/selvpcclient/resell/v2/subnets/testing/fixtures.go b/selvpcclient/resell/v2/subnets/testing/fixtures.go index 4ebea25..89c20a5 100644 --- a/selvpcclient/resell/v2/subnets/testing/fixtures.go +++ b/selvpcclient/resell/v2/subnets/testing/fixtures.go @@ -3,9 +3,9 @@ package testing import ( "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/subnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/subnets" ) // TestGetSubnetResponseRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/subnets/testing/requests_test.go b/selvpcclient/resell/v2/subnets/testing/requests_test.go index 5d50d3d..e056caa 100644 --- a/selvpcclient/resell/v2/subnets/testing/requests_test.go +++ b/selvpcclient/resell/v2/subnets/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/subnets" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/subnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetSubnet(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetSubnet(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/111122", @@ -25,8 +24,7 @@ func TestGetSubnet(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := subnets.Get(ctx, testEnv.Client, "111122") + actual, _, err := subnets.Get(testEnv.Client, "111122") if err != nil { t.Fatal(err) } @@ -46,7 +44,7 @@ func TestGetSubnetHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/111122", @@ -56,8 +54,7 @@ func TestGetSubnetHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - subnet, httpResponse, err := subnets.Get(ctx, testEnv.Client, "111122") + subnet, httpResponse, err := subnets.Get(testEnv.Client, "111122") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -76,12 +73,11 @@ func TestGetSubnetHTTPError(t *testing.T) { func TestGetSubnetTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - subnet, _, err := subnets.Get(ctx, testEnv.Client, "111122") + subnet, _, err := subnets.Get(testEnv.Client, "111122") if subnet != nil { t.Fatal("expected no subnet from the Get method") @@ -96,7 +92,7 @@ func TestGetSubnetUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/111122", @@ -106,8 +102,7 @@ func TestGetSubnetUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - subnet, _, err := subnets.Get(ctx, testEnv.Client, "111122") + subnet, _, err := subnets.Get(testEnv.Client, "111122") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -125,7 +120,7 @@ func TestListSubnets(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets", @@ -135,8 +130,7 @@ func TestListSubnets(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := subnets.List(ctx, testEnv.Client, subnets.ListOpts{}) + actual, _, err := subnets.List(testEnv.Client, subnets.ListOpts{}) if err != nil { t.Fatal(err) } @@ -161,7 +155,7 @@ func TestListSubnetsSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets", @@ -171,8 +165,7 @@ func TestListSubnetsSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := subnets.List(ctx, testEnv.Client, subnets.ListOpts{}) + actual, _, err := subnets.List(testEnv.Client, subnets.ListOpts{}) if err != nil { t.Fatal(err) } @@ -192,7 +185,7 @@ func TestListSubnetsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets", @@ -202,8 +195,7 @@ func TestListSubnetsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allSubnet, httpResponse, err := subnets.List(ctx, testEnv.Client, subnets.ListOpts{}) + allSubnet, httpResponse, err := subnets.List(testEnv.Client, subnets.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -222,12 +214,11 @@ func TestListSubnetsHTTPError(t *testing.T) { func TestListSubnetsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allSubnet, _, err := subnets.List(ctx, testEnv.Client, subnets.ListOpts{}) + allSubnet, _, err := subnets.List(testEnv.Client, subnets.ListOpts{}) if allSubnet != nil { t.Fatal("expected no subnets from the List method") @@ -242,7 +233,7 @@ func TestListSubnetsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets", @@ -252,8 +243,7 @@ func TestListSubnetsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allSubnet, _, err := subnets.List(ctx, testEnv.Client, subnets.ListOpts{}) + allSubnet, _, err := subnets.List(testEnv.Client, subnets.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -271,7 +261,7 @@ func TestCreateSubnets(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/projects/9c97bdc75295493096cf5edcb8c37933", @@ -282,9 +272,8 @@ func TestCreateSubnets(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateSubnetsOpts - actualResponse, _, err := subnets.Create(ctx, testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) + actualResponse, _, err := subnets.Create(testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) if err != nil { t.Fatal(err) } @@ -304,7 +293,7 @@ func TestCreateSubnetsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/projects/9c97bdc75295493096cf5edcb8c37933", @@ -315,9 +304,8 @@ func TestCreateSubnetsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateSubnetsOpts - subnet, httpResponse, err := subnets.Create(ctx, testEnv.Client, + subnet, httpResponse, err := subnets.Create(testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) if !endpointCalled { @@ -337,13 +325,12 @@ func TestCreateSubnetsHTTPError(t *testing.T) { func TestCreateSubnetsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateSubnetsOpts - subnet, _, err := subnets.Create(ctx, testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) + subnet, _, err := subnets.Create(testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) if subnet != nil { t.Fatal("expected no subnet from the Create method") @@ -358,7 +345,7 @@ func TestCreateSubnetsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/projects/9c97bdc75295493096cf5edcb8c37933", @@ -369,9 +356,8 @@ func TestCreateSubnetsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateSubnetsOpts - subnet, _, err := subnets.Create(ctx, testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) + subnet, _, err := subnets.Create(testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -389,17 +375,16 @@ func TestDeleteSubnet(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/112233", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := subnets.Delete(ctx, testEnv.Client, "112233") + _, err := subnets.Delete(testEnv.Client, "112233") if err != nil { t.Fatal(err) } @@ -414,7 +399,7 @@ func TestDeleteSubnetHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/subnets/112233", @@ -423,8 +408,7 @@ func TestDeleteSubnetHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := subnets.Delete(ctx, testEnv.Client, "112233") + httpResponse, err := subnets.Delete(testEnv.Client, "112233") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -439,12 +423,11 @@ func TestDeleteSubnetHTTPError(t *testing.T) { func TestDeleteSubnetTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := subnets.Delete(ctx, testEnv.Client, "112233") + _, err := subnets.Delete(testEnv.Client, "112233") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/tokens/doc.go b/selvpcclient/resell/v2/tokens/doc.go index 3d5c051..5ecb0ac 100644 --- a/selvpcclient/resell/v2/tokens/doc.go +++ b/selvpcclient/resell/v2/tokens/doc.go @@ -6,7 +6,7 @@ Example of creating a project-scoped token createOpts := tokens.TokenOpts{ ProjectID: "f628616b452f4052b191161c26abba91", } - token, err := tokens.Create(ctx, resellClient, createOpts) + token, err := tokens.Create(client, createOpts) if err != nil { log.Fatal(err) } @@ -17,7 +17,7 @@ Example of creating a domain-scoped token createOpts := tokens.TokenOpts{ AccountName: "1122334455", } - token, err := tokens.Create(ctx, resellClient, createOpts) + token, err := tokens.Create(client, createOpts) if err != nil { log.Fatal(err) } @@ -25,7 +25,7 @@ Example of creating a domain-scoped token Example of deleting a token - _, err = tokens.Delete(context, resellClient, token.ID) + _, err = tokens.Delete(context, client, token.ID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/tokens/requests.go b/selvpcclient/resell/v2/tokens/requests.go index a6f78fd..cd528ec 100644 --- a/selvpcclient/resell/v2/tokens/requests.go +++ b/selvpcclient/resell/v2/tokens/requests.go @@ -2,18 +2,19 @@ package tokens import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "tokens" // Create requests a creation of the Identity token. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts TokenOpts) (*Token, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, createOpts TokenOpts) (*Token, *clientservices.ResponseResult, error) { // Nest create options into the parent "token" JSON structure. type createToken struct { Options TokenOpts `json:"token"` @@ -24,8 +25,16 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -46,9 +55,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts } // Delete a user owned Identity token by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/tokens/testing/fixtures.go b/selvpcclient/resell/v2/tokens/testing/fixtures.go index 0cd3c2d..ef02a97 100644 --- a/selvpcclient/resell/v2/tokens/testing/fixtures.go +++ b/selvpcclient/resell/v2/tokens/testing/fixtures.go @@ -1,6 +1,6 @@ package testing -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/tokens" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/tokens" // TestCreateTokenOptsRaw represents marshalled options for the Create request. const TestCreateTokenOptsRaw = ` diff --git a/selvpcclient/resell/v2/tokens/testing/requests_test.go b/selvpcclient/resell/v2/tokens/testing/requests_test.go index ae27a80..6d25f37 100644 --- a/selvpcclient/resell/v2/tokens/testing/requests_test.go +++ b/selvpcclient/resell/v2/tokens/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/tokens" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/tokens" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestCreateToken(t *testing.T) { @@ -15,7 +14,7 @@ func TestCreateToken(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/tokens", @@ -26,9 +25,8 @@ func TestCreateToken(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateTokenOpts - actualResponse, _, err := tokens.Create(ctx, testEnv.Client, createOpts) + actualResponse, _, err := tokens.Create(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -48,7 +46,7 @@ func TestCreateTokenHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/tokens", @@ -59,9 +57,8 @@ func TestCreateTokenHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateTokenOpts - token, httpResponse, err := tokens.Create(ctx, testEnv.Client, createOpts) + token, httpResponse, err := tokens.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -80,13 +77,12 @@ func TestCreateTokenHTTPError(t *testing.T) { func TestCreateTokenTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateTokenOpts - token, _, err := tokens.Create(ctx, testEnv.Client, createOpts) + token, _, err := tokens.Create(testEnv.Client, createOpts) if token != nil { t.Fatal("expected no token from the Create method") @@ -101,7 +97,7 @@ func TestCreateTokenUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/tokens", @@ -112,9 +108,8 @@ func TestCreateTokenUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateTokenOpts - token, _, err := tokens.Create(ctx, testEnv.Client, createOpts) + token, _, err := tokens.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -132,7 +127,7 @@ func TestDeleteToken(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/tokens/dAFaSLSbK06iJ-iiq9x19A", @@ -141,8 +136,7 @@ func TestDeleteToken(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := tokens.Delete(ctx, testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") + _, err := tokens.Delete(testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") if err != nil { t.Fatal(err) } @@ -156,7 +150,7 @@ func TestDeleteNotOwnToken(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/tokens/dAFaSLSbK06iJ-iiq9x19A", @@ -165,8 +159,7 @@ func TestDeleteNotOwnToken(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := tokens.Delete(ctx, testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") + httpResponse, err := tokens.Delete(testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -181,12 +174,11 @@ func TestDeleteNotOwnToken(t *testing.T) { func TestDeleteUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := tokens.Delete(ctx, testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") + _, err := tokens.Delete(testEnv.Client, "dAFaSLSbK06iJ-iiq9x19A") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/traffic/doc.go b/selvpcclient/resell/v2/traffic/doc.go index 8ee18ff..3abbdd7 100644 --- a/selvpcclient/resell/v2/traffic/doc.go +++ b/selvpcclient/resell/v2/traffic/doc.go @@ -4,7 +4,7 @@ Resell v2 API. Example of getting domain traffic - domainTraffic, _, err := traffic.Get(ctx, resellClient) + domainTraffic, _, err := traffic.Get(client) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/traffic/requests.go b/selvpcclient/resell/v2/traffic/requests.go index 40e1a0f..accb28e 100644 --- a/selvpcclient/resell/v2/traffic/requests.go +++ b/selvpcclient/resell/v2/traffic/requests.go @@ -1,19 +1,28 @@ package traffic import ( - "context" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "traffic" // Get returns the domain traffic information. -func Get(ctx context.Context, client *selvpcclient.ServiceClient) (*DomainTraffic, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client) (*DomainTraffic, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } diff --git a/selvpcclient/resell/v2/traffic/schemas.go b/selvpcclient/resell/v2/traffic/schemas.go index 6f76fb8..9c7fb37 100644 --- a/selvpcclient/resell/v2/traffic/schemas.go +++ b/selvpcclient/resell/v2/traffic/schemas.go @@ -4,7 +4,7 @@ import ( "encoding/json" "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" ) // Traffic contains information about used and paid traffic. diff --git a/selvpcclient/resell/v2/traffic/testing/fixtures.go b/selvpcclient/resell/v2/traffic/testing/fixtures.go index c9aaaca..51b8102 100644 --- a/selvpcclient/resell/v2/traffic/testing/fixtures.go +++ b/selvpcclient/resell/v2/traffic/testing/fixtures.go @@ -3,8 +3,8 @@ package testing import ( "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/traffic" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/traffic" ) // TestGetTrafficRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/traffic/testing/requests_test.go b/selvpcclient/resell/v2/traffic/testing/requests_test.go index 24f3c41..cb07cb1 100644 --- a/selvpcclient/resell/v2/traffic/testing/requests_test.go +++ b/selvpcclient/resell/v2/traffic/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/traffic" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/traffic" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetDomainTraffic(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetDomainTraffic(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/traffic", @@ -25,8 +24,7 @@ func TestGetDomainTraffic(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - tr, _, err := traffic.Get(ctx, testEnv.Client) + tr, _, err := traffic.Get(testEnv.Client) if err != nil { t.Fatal(err) } @@ -51,7 +49,7 @@ func TestGetDomainTrafficUsed(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/traffic", @@ -61,8 +59,7 @@ func TestGetDomainTrafficUsed(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - tr, _, err := traffic.Get(ctx, testEnv.Client) + tr, _, err := traffic.Get(testEnv.Client) if err != nil { t.Fatal(err) } @@ -82,7 +79,7 @@ func TestGetDomainTrafficHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/traffic", @@ -92,8 +89,7 @@ func TestGetDomainTrafficHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - tr, httpResponse, err := traffic.Get(ctx, testEnv.Client) + tr, httpResponse, err := traffic.Get(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -112,12 +108,11 @@ func TestGetDomainTrafficHTTPError(t *testing.T) { func TestGetTrafficTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - tr, _, err := traffic.Get(ctx, testEnv.Client) + tr, _, err := traffic.Get(testEnv.Client) if tr != nil { t.Fatal("expected no traffic from the Get method") @@ -132,7 +127,7 @@ func TestGetTrafficInvalidTimestampsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/traffic", @@ -142,8 +137,7 @@ func TestGetTrafficInvalidTimestampsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - tr, _, err := traffic.Get(ctx, testEnv.Client) + tr, _, err := traffic.Get(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -161,7 +155,7 @@ func TestGetTrafficInvalidResponseUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/traffic", @@ -171,8 +165,7 @@ func TestGetTrafficInvalidResponseUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - tr, _, err := traffic.Get(ctx, testEnv.Client) + tr, _, err := traffic.Get(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") diff --git a/selvpcclient/resell/v2/users/doc.go b/selvpcclient/resell/v2/users/doc.go index 979e76d..164c16f 100644 --- a/selvpcclient/resell/v2/users/doc.go +++ b/selvpcclient/resell/v2/users/doc.go @@ -4,7 +4,7 @@ Resell v2 API. Example of getting a single user referenced by its id - user, _, err := users.Get(context, resellClient, userID) + user, _, err := users.Get(context, client, userID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single user referenced by its id Example of getting all users - allUsers, _, err := users.List(ctx, resellClient) + allUsers, _, err := users.List(client) if err != nil { log.Fatal(err) } @@ -26,7 +26,7 @@ Example of creating a single user Name: "user0", Password: "verysecret", } - createdUser, _, err := users.Create(ctx, resellClient, userCreateOpts) + createdUser, _, err := users.Create(client, userCreateOpts) if err != nil { log.Fatal(err) } @@ -40,7 +40,7 @@ Example of updating a single user Password: "moresecret", Enabled: &userEnabled, } - updatedUser, _, err := users.Update(ctx, resellClient, createdUser.ID, userUpdateOpts) + updatedUser, _, err := users.Update(client, createdUser.ID, userUpdateOpts) if err != nil { log.Fatal(err) } @@ -48,7 +48,7 @@ Example of updating a single user Example of deleting a single user - _, err = users.Delete(context, resellClient, createdUser.ID) + _, err = users.Delete(context, client, createdUser.ID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/users/requests.go b/selvpcclient/resell/v2/users/requests.go index 3fb5860..2062b76 100644 --- a/selvpcclient/resell/v2/users/requests.go +++ b/selvpcclient/resell/v2/users/requests.go @@ -2,20 +2,29 @@ package users import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "users" // Get returns a single user by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*User, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*User, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,9 +45,17 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*U } // List gets a list of users in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*User, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func List(client *selvpcclient.Client) ([]*User, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -59,7 +76,7 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*User, *se } // Create requests a creation of the user. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts UserOpts) (*User, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, createOpts UserOpts) (*User, *clientservices.ResponseResult, error) { // Nest create options into the parent "user" JSON structure. type createUser struct { Options UserOpts `json:"user"` @@ -70,8 +87,16 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -92,7 +117,7 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts } // Update requests an update of the user referenced by its id. -func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, updateOpts UserOpts) (*User, *selvpcclient.ResponseResult, error) { +func Update(client *selvpcclient.Client, id string, updateOpts UserOpts) (*User, *clientservices.ResponseResult, error) { // Nest update options into the parent "user" JSON structure. type updateUser struct { Options UserOpts `json:"user"` @@ -103,8 +128,16 @@ func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPatch, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPatch, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -125,9 +158,17 @@ func Update(ctx context.Context, client *selvpcclient.ServiceClient, id string, } // Delete deletes a single user by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/users/testing/fixtures.go b/selvpcclient/resell/v2/users/testing/fixtures.go index 821a32a..08ac6b9 100644 --- a/selvpcclient/resell/v2/users/testing/fixtures.go +++ b/selvpcclient/resell/v2/users/testing/fixtures.go @@ -1,6 +1,6 @@ package testing -import "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/users" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/users" // TestGetUsersResponseRaw represents a raw response from the Get request. const TestGetUsersResponseRaw = ` diff --git a/selvpcclient/resell/v2/users/testing/requests_test.go b/selvpcclient/resell/v2/users/testing/requests_test.go index 8331456..bf5be05 100644 --- a/selvpcclient/resell/v2/users/testing/requests_test.go +++ b/selvpcclient/resell/v2/users/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/users" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/users" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetUser(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetUser(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -25,8 +24,7 @@ func TestGetUser(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actualResponse, _, err := users.Get(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + actualResponse, _, err := users.Get(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if err != nil { t.Fatal(err) } @@ -45,7 +43,7 @@ func TestGetUserHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -55,8 +53,7 @@ func TestGetUserHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - user, httpResponse, err := users.Get(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + user, httpResponse, err := users.Get(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -74,12 +71,11 @@ func TestGetUserHTTPError(t *testing.T) { func TestGetUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, _, err := users.Get(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + _, _, err := users.Get(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if err == nil { t.Fatal("expected error from the Get method") @@ -91,7 +87,7 @@ func TestGetUsersUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -101,8 +97,7 @@ func TestGetUsersUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - user, _, err := users.Get(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + user, _, err := users.Get(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -120,7 +115,7 @@ func TestListUsers(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -130,8 +125,7 @@ func TestListUsers(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := users.List(ctx, testEnv.Client) + actual, _, err := users.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -156,7 +150,7 @@ func TestListUsersSingle(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -166,8 +160,7 @@ func TestListUsersSingle(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := users.List(ctx, testEnv.Client) + actual, _, err := users.List(testEnv.Client) if err != nil { t.Fatal(err) } @@ -187,7 +180,7 @@ func TestListUsersHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -197,8 +190,7 @@ func TestListUsersHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allUsers, httpResponse, err := users.List(ctx, testEnv.Client) + allUsers, httpResponse, err := users.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -217,12 +209,11 @@ func TestListUsersHTTPError(t *testing.T) { func TestListUsersTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allUsers, _, err := users.List(ctx, testEnv.Client) + allUsers, _, err := users.List(testEnv.Client) if allUsers != nil { t.Fatal("expected no users from the List method") @@ -237,7 +228,7 @@ func TestListUsersUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -247,8 +238,7 @@ func TestListUsersUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allUsers, _, err := users.List(ctx, testEnv.Client) + allUsers, _, err := users.List(testEnv.Client) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -266,7 +256,7 @@ func TestCreateUser(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -277,9 +267,8 @@ func TestCreateUser(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateUserOpts - actualResponse, _, err := users.Create(ctx, testEnv.Client, createOpts) + actualResponse, _, err := users.Create(testEnv.Client, createOpts) if err != nil { t.Fatal(err) } @@ -299,7 +288,7 @@ func TestCreateUserHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -309,9 +298,8 @@ func TestCreateUserHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateUserOpts - user, httpResponse, err := users.Create(ctx, testEnv.Client, createOpts) + user, httpResponse, err := users.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -329,13 +317,12 @@ func TestCreateUserHTTPError(t *testing.T) { func TestCreateUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateUserOpts - user, _, err := users.Create(ctx, testEnv.Client, createOpts) + user, _, err := users.Create(testEnv.Client, createOpts) if user != nil { t.Fatal("expected no users from the Create method") @@ -350,7 +337,7 @@ func TestCreateUserUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users", @@ -361,9 +348,8 @@ func TestCreateUserUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateUserOpts - user, _, err := users.Create(ctx, testEnv.Client, createOpts) + user, _, err := users.Create(testEnv.Client, createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -381,7 +367,7 @@ func TestUpdateUser(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -392,9 +378,8 @@ func TestUpdateUser(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateUserOpts - actualResponse, _, err := users.Update(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) + actualResponse, _, err := users.Update(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) if err != nil { t.Fatal(err) } @@ -414,7 +399,7 @@ func TestUpdateUserHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -424,9 +409,8 @@ func TestUpdateUserHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateUserOpts - user, httpResponse, err := users.Update(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) + user, httpResponse, err := users.Update(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -444,13 +428,12 @@ func TestUpdateUserHTTPError(t *testing.T) { func TestUpdateUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() updateOpts := TestUpdateUserOpts - user, _, err := users.Update(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) + user, _, err := users.Update(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) if user != nil { t.Fatal("expected no users from the Update method") @@ -465,7 +448,7 @@ func TestUpdateUserUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -476,9 +459,8 @@ func TestUpdateUserUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() updateOpts := TestUpdateUserOpts - user, _, err := users.Update(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) + user, _, err := users.Update(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f", updateOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -496,17 +478,16 @@ func TestDeleteUser(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := users.Delete(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + _, err := users.Delete(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if err != nil { t.Fatal(err) } @@ -520,7 +501,7 @@ func TestDeleteUserHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/users/4b2e452ed4c940bd87a88499eaf14c4f", @@ -529,8 +510,7 @@ func TestDeleteUserHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := users.Delete(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + httpResponse, err := users.Delete(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -545,12 +525,11 @@ func TestDeleteUserHTTPError(t *testing.T) { func TestDeleteUserTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := users.Delete(ctx, testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") + _, err := users.Delete(testEnv.Client, "4b2e452ed4c940bd87a88499eaf14c4f") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/resell/v2/vrrpsubnets/doc.go b/selvpcclient/resell/v2/vrrpsubnets/doc.go index 22274d9..f3e7bac 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/doc.go +++ b/selvpcclient/resell/v2/vrrpsubnets/doc.go @@ -4,7 +4,7 @@ through the Resell v2 API. Example of getting a single VRRP subnet referenced by its id - vrrpsubnet, _, err := vrrpsubnets.Get(context, resellClient, vrrpSubnetID) + vrrpsubnet, _, err := vrrpsubnets.Get(context, client, vrrpSubnetID) if err != nil { log.Fatal(err) } @@ -12,7 +12,7 @@ Example of getting a single VRRP subnet referenced by its id Example of getting all VRRP subnets - allVRRPSubnets, _, err := vrrpsubnets.List(ctx, resellClient, vrrpsubnets.ListOpts{}) + allVRRPSubnets, _, err := vrrpsubnets.List(client, vrrpsubnets.ListOpts{}) if err != nil { log.Fatal(err) } @@ -35,7 +35,7 @@ Example of creating VRRP subnets }, }, } - newVRRPSubnets, _, err := vrrpsubnets.Create(ctx, resellClient, projectID, createOpts) + newVRRPSubnets, _, err := vrrpsubnets.Create(client, projectID, createOpts) if err != nil { log.Fatal(err) } @@ -45,7 +45,7 @@ Example of creating VRRP subnets Example of deleting a single VRRP subnet - _, err = vrrpsubnets.Delete(ctx, resellClient, subnetID) + _, err = vrrpsubnets.Delete(client, subnetID) if err != nil { log.Fatal(err) } diff --git a/selvpcclient/resell/v2/vrrpsubnets/requests.go b/selvpcclient/resell/v2/vrrpsubnets/requests.go index e63a585..065caa0 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/requests.go +++ b/selvpcclient/resell/v2/vrrpsubnets/requests.go @@ -2,20 +2,31 @@ package vrrpsubnets import ( "bytes" - "context" "encoding/json" + "fmt" "net/http" "strings" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" + "github.com/google/go-querystring/query" + + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) const resourceURL = "vrrp_subnets" // Get returns a single VRRP subnet by its id. -func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*VRRPSubnet, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) +func Get(client *selvpcclient.Client, id string) (*VRRPSubnet, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -36,18 +47,25 @@ func Get(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*V } // List gets a list of VRRP subnets in the current domain. -func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts) ([]*VRRPSubnet, *selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL}, "/") +func List(client *selvpcclient.Client, opts ListOpts) ([]*VRRPSubnet, *clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } - queryParams, err := selvpcclient.BuildQueryParameters(opts) + url := strings.Join([]string{endpoint, resourceURL}, "/") + + queryParams, err := query.Values(opts) if err != nil { return nil, nil, err } - if queryParams != "" { - url = strings.Join([]string{url, queryParams}, "?") - } - responseResult, err := client.DoRequest(ctx, http.MethodGet, url, nil) + url = strings.Join([]string{url, queryParams.Encode()}, "?") + + responseResult, err := client.Resell.Requests.Do(http.MethodGet, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -68,15 +86,23 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient, opts ListOpts } // Create requests a creation of the VRRP subnets in the specified project. -func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID string, createOpts VRRPSubnetOpts) ([]*VRRPSubnet, *selvpcclient.ResponseResult, error) { +func Create(client *selvpcclient.Client, projectID string, createOpts VRRPSubnetOpts) ([]*VRRPSubnet, *clientservices.ResponseResult, error) { createVRRPSubnetsOpts := &createOpts requestBody, err := json.Marshal(createVRRPSubnetsOpts) if err != nil { return nil, nil, err } - url := strings.Join([]string{client.Endpoint, resourceURL, "projects", projectID}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody)) + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, "projects", projectID}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodPost, url, &clientservices.RequestOptions{ + Body: bytes.NewReader(requestBody), + OkCodes: []int{200}, + }) if err != nil { return nil, nil, err } @@ -97,9 +123,17 @@ func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID s } // Delete deletes a single VRRP subnet by its id. -func Delete(ctx context.Context, client *selvpcclient.ServiceClient, id string) (*selvpcclient.ResponseResult, error) { - url := strings.Join([]string{client.Endpoint, resourceURL, id}, "/") - responseResult, err := client.DoRequest(ctx, http.MethodDelete, url, nil) +func Delete(client *selvpcclient.Client, id string) (*clientservices.ResponseResult, error) { + endpoint, err := client.Resell.GetEndpoint() + if err != nil { + return nil, fmt.Errorf("failed to get endpoint, err: %w", err) + } + + url := strings.Join([]string{endpoint, resourceURL, id}, "/") + responseResult, err := client.Resell.Requests.Do(http.MethodDelete, url, &clientservices.RequestOptions{ + Body: nil, + OkCodes: []int{204}, + }) if err != nil { return nil, err } diff --git a/selvpcclient/resell/v2/vrrpsubnets/requests_opts.go b/selvpcclient/resell/v2/vrrpsubnets/requests_opts.go index 4e08056..c432bc2 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/requests_opts.go +++ b/selvpcclient/resell/v2/vrrpsubnets/requests_opts.go @@ -1,6 +1,6 @@ package vrrpsubnets -import "github.com/selectel/go-selvpcclient/v2/selvpcclient" +import "github.com/selectel/go-selvpcclient/v3/selvpcclient" // VRRPSubnetOpts represents options for the VRRP subnets Create request. type VRRPSubnetOpts struct { @@ -34,5 +34,5 @@ type VRRPRegionOpt struct { // ListOpts represents options for the VRRP subnets List request. type ListOpts struct { - Detailed bool `param:"detailed"` + Detailed bool `url:"detailed"` } diff --git a/selvpcclient/resell/v2/vrrpsubnets/schemas.go b/selvpcclient/resell/v2/vrrpsubnets/schemas.go index a68a370..dcad0dd 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/schemas.go +++ b/selvpcclient/resell/v2/vrrpsubnets/schemas.go @@ -1,8 +1,8 @@ package vrrpsubnets import ( - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/subnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/subnets" ) // VRRPSubnet represents a single Resell VRRP subnet. diff --git a/selvpcclient/resell/v2/vrrpsubnets/testing/fixtures.go b/selvpcclient/resell/v2/vrrpsubnets/testing/fixtures.go index ec37a3b..3f0205a 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/testing/fixtures.go +++ b/selvpcclient/resell/v2/vrrpsubnets/testing/fixtures.go @@ -3,10 +3,10 @@ package testing import ( "time" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/servers" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/subnets" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/vrrpsubnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/servers" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/subnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/vrrpsubnets" ) // TestGetVRRPSubnetResponseRaw represents a raw response from the Get request. diff --git a/selvpcclient/resell/v2/vrrpsubnets/testing/requests_test.go b/selvpcclient/resell/v2/vrrpsubnets/testing/requests_test.go index 307deab..1d03cee 100644 --- a/selvpcclient/resell/v2/vrrpsubnets/testing/requests_test.go +++ b/selvpcclient/resell/v2/vrrpsubnets/testing/requests_test.go @@ -1,13 +1,12 @@ package testing import ( - "context" "net/http" "reflect" "testing" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell/v2/vrrpsubnets" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/vrrpsubnets" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/testutils" ) func TestGetVRRPSubnet(t *testing.T) { @@ -15,7 +14,7 @@ func TestGetVRRPSubnet(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/186", @@ -25,8 +24,7 @@ func TestGetVRRPSubnet(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := vrrpsubnets.Get(ctx, testEnv.Client, "186") + actual, _, err := vrrpsubnets.Get(testEnv.Client, "186") if err != nil { t.Fatal(err) } @@ -46,7 +44,7 @@ func TestGetVRRPSubnetHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/186", @@ -56,8 +54,7 @@ func TestGetVRRPSubnetHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - subnet, httpResponse, err := vrrpsubnets.Get(ctx, testEnv.Client, "186") + subnet, httpResponse, err := vrrpsubnets.Get(testEnv.Client, "186") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -76,12 +73,11 @@ func TestGetVRRPSubnetHTTPError(t *testing.T) { func TestGetVRRPSubnetTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - subnet, _, err := vrrpsubnets.Get(ctx, testEnv.Client, "111122") + subnet, _, err := vrrpsubnets.Get(testEnv.Client, "111122") if subnet != nil { t.Fatal("expected no VRRP subnet from the Get method") @@ -96,7 +92,7 @@ func TestGetVRRPSubnetUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/186", @@ -106,8 +102,7 @@ func TestGetVRRPSubnetUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - vrpsubnet, _, err := vrrpsubnets.Get(ctx, testEnv.Client, "186") + vrpsubnet, _, err := vrrpsubnets.Get(testEnv.Client, "186") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -125,7 +120,7 @@ func TestListVRRPSubnets(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets", @@ -135,8 +130,7 @@ func TestListVRRPSubnets(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - actual, _, err := vrrpsubnets.List(ctx, testEnv.Client, vrrpsubnets.ListOpts{}) + actual, _, err := vrrpsubnets.List(testEnv.Client, vrrpsubnets.ListOpts{}) if err != nil { t.Fatal(err) } @@ -156,7 +150,7 @@ func TestListVRRPSubnetsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets", @@ -166,8 +160,7 @@ func TestListVRRPSubnetsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allVRRPSubnets, httpResponse, err := vrrpsubnets.List(ctx, testEnv.Client, vrrpsubnets.ListOpts{}) + allVRRPSubnets, httpResponse, err := vrrpsubnets.List(testEnv.Client, vrrpsubnets.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -186,12 +179,11 @@ func TestListVRRPSubnetsHTTPError(t *testing.T) { func TestListVRRPSubnetsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - allVRRPSubnets, _, err := vrrpsubnets.List(ctx, testEnv.Client, vrrpsubnets.ListOpts{}) + allVRRPSubnets, _, err := vrrpsubnets.List(testEnv.Client, vrrpsubnets.ListOpts{}) if allVRRPSubnets != nil { t.Fatal("expected no VRRP subnets from the List method") @@ -206,7 +198,7 @@ func TestListVRRPSubnetsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets", @@ -216,8 +208,7 @@ func TestListVRRPSubnetsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - allVRRPSubnets, _, err := vrrpsubnets.List(ctx, testEnv.Client, vrrpsubnets.ListOpts{}) + allVRRPSubnets, _, err := vrrpsubnets.List(testEnv.Client, vrrpsubnets.ListOpts{}) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -235,7 +226,7 @@ func TestCreateVRRPSubnets(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/projects/49338ac045f448e294b25d013f890317", @@ -246,9 +237,8 @@ func TestCreateVRRPSubnets(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateVRRPSubnetsOpts - actualResponse, _, err := vrrpsubnets.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + actualResponse, _, err := vrrpsubnets.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if err != nil { t.Fatal(err) } @@ -268,7 +258,7 @@ func TestCreateVRRPSubnetsHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/projects/49338ac045f448e294b25d013f890317", @@ -279,9 +269,8 @@ func TestCreateVRRPSubnetsHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateVRRPSubnetsOpts - vrrpSubnet, httpResponse, err := vrrpsubnets.Create(ctx, testEnv.Client, + vrrpSubnet, httpResponse, err := vrrpsubnets.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { @@ -301,13 +290,12 @@ func TestCreateVRRPSubnetsHTTPError(t *testing.T) { func TestCreateVRRPSubnetsTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() createOpts := TestCreateVRRPSubnetsOpts - vrrpSubnet, _, err := vrrpsubnets.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + vrrpSubnet, _, err := vrrpsubnets.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if vrrpSubnet != nil { t.Fatal("expected no VRRP subnet from the Create method") @@ -322,7 +310,7 @@ func TestCreateVRRPSubnetsUnmarshalError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/projects/49338ac045f448e294b25d013f890317", @@ -333,9 +321,8 @@ func TestCreateVRRPSubnetsUnmarshalError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() createOpts := TestCreateVRRPSubnetsOpts - vrrpSubnet, _, err := vrrpsubnets.Create(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) + vrrpSubnet, _, err := vrrpsubnets.Create(testEnv.Client, "49338ac045f448e294b25d013f890317", createOpts) if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -353,17 +340,16 @@ func TestDeleteVRRPSubnet(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/112233", Method: http.MethodDelete, - Status: http.StatusOK, + Status: http.StatusNoContent, CallFlag: &endpointCalled, }) - ctx := context.Background() - _, err := vrrpsubnets.Delete(ctx, testEnv.Client, "112233") + _, err := vrrpsubnets.Delete(testEnv.Client, "112233") if err != nil { t.Fatal(err) } @@ -378,7 +364,7 @@ func TestDeleteVRRPSubnetHTTPError(t *testing.T) { testEnv := testutils.SetupTestEnv() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() testutils.HandleReqWithoutBody(t, &testutils.HandleReqOpts{ Mux: testEnv.Mux, URL: "/resell/v2/vrrp_subnets/112233", @@ -387,8 +373,7 @@ func TestDeleteVRRPSubnetHTTPError(t *testing.T) { CallFlag: &endpointCalled, }) - ctx := context.Background() - httpResponse, err := vrrpsubnets.Delete(ctx, testEnv.Client, "112233") + httpResponse, err := vrrpsubnets.Delete(testEnv.Client, "112233") if !endpointCalled { t.Fatal("endpoint wasn't called") @@ -403,12 +388,11 @@ func TestDeleteVRRPSubnetHTTPError(t *testing.T) { func TestDeleteVRRPSubnetTimeoutError(t *testing.T) { testEnv := testutils.SetupTestEnv() - testEnv.Server.Close() defer testEnv.TearDownTestEnv() - testEnv.NewTestResellV2Client() + testEnv.NewSelVPCClient() + testEnv.Server.Close() - ctx := context.Background() - _, err := vrrpsubnets.Delete(ctx, testEnv.Client, "112233") + _, err := vrrpsubnets.Delete(testEnv.Client, "112233") if err == nil { t.Fatal("expected error from the Delete method") diff --git a/selvpcclient/selvpc.go b/selvpcclient/selvpc.go index 7e981e5..c359437 100644 --- a/selvpcclient/selvpc.go +++ b/selvpcclient/selvpc.go @@ -4,190 +4,101 @@ import ( "bytes" "context" "encoding/json" - "errors" "fmt" - "io" - "io/ioutil" //nolint:staticcheck - "net" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" "time" - "unicode" -) - -const ( - // AppVersion is a version of the application. - AppVersion = "2.0.0" - // AppName is a global application name. - AppName = "go-selvpcclient" + "github.com/gophercloud/gophercloud" - // DefaultEndpoint contains basic endpoint for queries. - DefaultEndpoint = "https://api.selectel.ru/vpc" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" +) - DefaultOpenstackIdentityEndpoint = "https://api.selvpc.ru/identity/v3/" +const ( + AppName = "go-selvpcclient" + AppVersion = "3.0.0" +) - // DefaultUserAgent contains basic user agent that will be used in queries. - DefaultUserAgent = AppName + "/" + AppVersion +type Client struct { + // Resell - client for Cloud Management API. + Resell *clients.ResellClient - // defaultHTTPTimeout represents the default timeout (in seconds) for HTTP - // requests. - defaultHTTPTimeout = 120 + // QuotaManager - client for Cloud Quota Management API. + QuotaManager *clients.QuotaManagerClient - // defaultDialTimeout represents the default timeout (in seconds) for HTTP - // connection establishments. - defaultDialTimeout = 60 + // Catalog - service for simplified resolve regional endpoints from Keystone catalog. + Catalog *clientservices.CatalogService - // defaultKeepalive represents the default keep-alive period for an active - // network connection. - defaultKeepaliveTimeout = 60 + serviceClient *gophercloud.ServiceClient +} - // defaultMaxIdleConns represents the maximum number of idle (keep-alive) - // connections. - defaultMaxIdleConns = 100 +type ClientOptions struct { + Context context.Context - // defaultIdleConnTimeout represents the maximum amount of time an idle - // (keep-alive) connection will remain idle before closing itself. - defaultIdleConnTimeout = 100 + // Your Account ID, for example: 234567. + DomainName string - // defaultTLSHandshakeTimeout represents the default timeout (in seconds) - // for TLS handshake. - defaultTLSHandshakeTimeout = 60 + // Credentials of your service user. + // Documentation: https://docs.selectel.ru/control-panel-actions/users-and-roles/ + Username string + Password string - // defaultExpectContinueTimeout represents the default amount of time to - // wait for a server's first response headers. - defaultExpectContinueTimeout = 1 -) + // Optional field, that is used for authentication with project scope. + // If you created service user with admin role of project, then this field is for you. + ProjectID string -var ( - errOptsIsNotStruct = errors.New("provided options is not a structure") - errServiceResponse = errors.New("status code from the server") -) + // Optional field to specify a non-default Identity endpoint. + AuthURL string -// NewHTTPClient returns a reference to an initialized configured HTTP client. -func NewHTTPClient() *http.Client { - return &http.Client{ - Timeout: time.Second * defaultHTTPTimeout, - Transport: newHTTPTransport(), - } + // Optional field to specify the domain name where the user is located. + // Used in private clouds to issue a token not from owned domain. + // If this field is not set, then it will be equal to the value of DomainName. + UserDomainName string } -// newHTTPTransport returns a reference to an initialized configured HTTP -// transport. -func newHTTPTransport() *http.Transport { - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: defaultDialTimeout * time.Second, - KeepAlive: defaultKeepaliveTimeout * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: defaultMaxIdleConns, - IdleConnTimeout: defaultIdleConnTimeout * time.Second, - TLSHandshakeTimeout: defaultTLSHandshakeTimeout * time.Second, - ExpectContinueTimeout: defaultExpectContinueTimeout * time.Second, +func NewClient(options *ClientOptions) (*Client, error) { + serviceClientOptions := clientservices.ServiceClientOptions{ + DomainName: options.DomainName, + Username: options.Username, + Password: options.Password, + ProjectID: options.ProjectID, + UserDomainName: options.UserDomainName, + AuthURL: options.AuthURL, + UserAgent: fmt.Sprintf("%s/%s", AppName, AppVersion), } -} - -// ServiceClient stores details that are needed to work with different Selectel VPC APIs. -type ServiceClient struct { - // HTTPClient represents an initialized HTTP client that will be used to do requests. - HTTPClient *http.Client - // Endpoint represents an endpoint that will be used in all requests. - Endpoint string - - // TokenID is a client authentication token. - TokenID string - - // UserAgent contains user agent that will be used in all requests. - UserAgent string -} - -// ResponseResult represents a result of a HTTP request. -// It embeddes standard http.Response and adds a custom error description. -type ResponseResult struct { - *http.Response - - // Err contains error that can be provided to a caller. - Err error -} - -// ExtractResult allows to provide an object into which ResponseResult body will be extracted. -func (result *ResponseResult) ExtractResult(to interface{}) error { - body, err := ioutil.ReadAll(result.Body) - defer result.Body.Close() + serviceClient, err := clientservices.NewServiceClient(&serviceClientOptions) if err != nil { - return err + return nil, fmt.Errorf("failed to create service client, err: %w", err) } - err = json.Unmarshal(body, to) - return err -} + serviceClient.ProviderClient.Context = options.Context -// ExtractErr build a string without whitespaces from the error body. -// We don't unmarshal it into some struct because there are no strict error definition in the API. -func (result *ResponseResult) ExtractErr() (string, error) { - body, err := ioutil.ReadAll(result.Body) - defer result.Body.Close() + catalogService, err := clientservices.NewCatalogService(serviceClient) if err != nil { - return "", err + return nil, fmt.Errorf("failed to initialize endpoints catalog service, err: %w", err) } - resp := string(body) + requestService := clientservices.NewRequestService(serviceClient) - var builder strings.Builder - builder.Grow(len(resp)) - for _, ch := range resp { - if !unicode.IsSpace(ch) { - builder.WriteRune(ch) - } + client := Client{ + Resell: clients.NewResellClient(requestService, catalogService), + QuotaManager: clients.NewQuotaManagerClient(requestService, catalogService), + Catalog: catalogService, + serviceClient: serviceClient, } - return builder.String(), nil + return &client, nil } -// DoRequest performs the HTTP request with the current ServiceClient's HTTPClient. -// Authentication and optional headers will be added automatically. -func (client *ServiceClient) DoRequest(ctx context.Context, method, path string, body io.Reader) (*ResponseResult, error) { - // Prepare a HTTP request with the provided context. - request, err := http.NewRequest(method, path, body) - if err != nil { - return nil, err - } - request.Header.Set("User-Agent", client.UserAgent) - request.Header.Set("X-token", client.TokenID) - if body != nil { - request.Header.Set("Content-Type", "application/json") - } - request = request.WithContext(ctx) - - // Send HTTP request and populate the ResponseResult. - response, err := client.HTTPClient.Do(request) - if err != nil { - return nil, err - } - responseResult := &ResponseResult{ - response, - nil, - } - - // Check status code and populate extended error message if it's possible. - if response.StatusCode >= 400 && response.StatusCode <= 599 { - extendedError, err := responseResult.ExtractErr() - if err != nil { - responseResult.Err = fmt.Errorf("selvpcclient: got the %d %w", response.StatusCode, errServiceResponse) - } else { - responseResult.Err = fmt.Errorf("selvpcclient: got the %d %w: %s", response.StatusCode, errServiceResponse, extendedError) - } - } - - return responseResult, nil +// GetXAuthToken - returns X-Auth-Token from Service Provider. This method doesn't guarantee that the token is valid. +// It returns the last used token from the service provider. Usually the lifetime of the token is 24h. If you use +// this token, then you should handle 401 error. +func (selvpc *Client) GetXAuthToken() string { + return selvpc.serviceClient.Token() } +// --------------------------------------------------------------------------------------------------------------------- + // RFC3339NoZ describes a timestamp format used by some SelVPC responses. const RFC3339NoZ = "2006-01-02T15:04:05" @@ -224,52 +135,3 @@ const ( // IPVersion represents a type for the IP versions of the different Selectel VPC APIs. type IPVersion string - -// BuildQueryParameters converts provided options struct to the string of URL parameters. -func BuildQueryParameters(opts interface{}) (string, error) { - optsValue := reflect.ValueOf(opts) - if optsValue.Kind() != reflect.Struct { - return "", errOptsIsNotStruct - } - optsType := reflect.TypeOf(opts) - - params := url.Values{} - - for i := 0; i < optsValue.NumField(); i++ { - fieldValue := optsValue.Field(i) - fieldType := optsType.Field(i) - - queryTag := fieldType.Tag.Get("param") - if queryTag != "" { - if isZero(fieldValue) { - continue - } - - tags := strings.Split(queryTag, ",") - loop: - switch fieldValue.Kind() { - case reflect.Ptr: - fieldValue = fieldValue.Elem() - goto loop - case reflect.String: - params.Add(tags[0], fieldValue.String()) - case reflect.Int: - params.Add(tags[0], strconv.FormatInt(fieldValue.Int(), 10)) - case reflect.Bool: - params.Add(tags[0], strconv.FormatBool(fieldValue.Bool())) - } - } - } - - return params.Encode(), nil -} - -// isZero checks if provided value is zero. -func isZero(v reflect.Value) bool { - if v.Kind() == reflect.Ptr { - return v.IsNil() - } - z := reflect.Zero(v.Type()) - - return v.Interface() == z.Interface() -} diff --git a/selvpcclient/testing/client_test.go b/selvpcclient/testing/client_test.go deleted file mode 100644 index af14360..0000000 --- a/selvpcclient/testing/client_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package testing - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" //nolint:staticcheck - "log" - "net/http" - "testing" - - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/testutils" -) - -func TestDoGetRequest(t *testing.T) { - testEnv := testutils.SetupTestEnv() - defer testEnv.TearDownTestEnv() - testEnv.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Content-Type", "application/json") - fmt.Fprint(w, "response") - - if r.Method != http.MethodGet { - t.Errorf("got %s method, want GET", r.Method) - } - }) - - endpoint := testEnv.Server.URL + "/" - client := &selvpcclient.ServiceClient{ - HTTPClient: &http.Client{}, - Endpoint: endpoint, - TokenID: "token", - UserAgent: "agent", - } - - ctx := context.Background() - response, err := client.DoRequest(ctx, http.MethodGet, endpoint, nil) - if err != nil { - log.Fatalf("unexpected error: %v", err) //nolint:gocritic - } - if response.Body == nil { - log.Fatal("response body is empty") - } - if response.StatusCode != 200 { - log.Fatalf("got %d response status, want 200", response.StatusCode) - } -} - -func TestDoPostRequest(t *testing.T) { - testEnv := testutils.SetupTestEnv() - defer testEnv.TearDownTestEnv() - testEnv.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Content-Type", "application/json") - fmt.Fprint(w, "response") - - if r.Method != http.MethodPost { - t.Errorf("got %s method, want POST", r.Method) - } - - _, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("unable to read the request body: %v", err) - } - }) - - endpoint := testEnv.Server.URL + "/" - client := &selvpcclient.ServiceClient{ - HTTPClient: &http.Client{}, - Endpoint: endpoint, - TokenID: "token", - UserAgent: "agent", - } - - requestBody, err := json.Marshal(&struct { - ID string `json:"id"` - }{ - ID: "uuid", - }) - if err != nil { - log.Fatalf("can't marshal JSON: %v", err) //nolint:gocritic - } - - ctx := context.Background() - response, err := client.DoRequest(ctx, http.MethodPost, endpoint, bytes.NewReader(requestBody)) - if err != nil { - log.Fatalf("unexpected error: %v", err) - } - if response.Body == nil { - log.Fatal("response body is empty") - } - if response.StatusCode != 200 { - log.Fatalf("got %d response status, want 200", response.StatusCode) - } -} diff --git a/selvpcclient/testutils/clients.go b/selvpcclient/testutils/clients.go index 23e1a19..a7c959c 100644 --- a/selvpcclient/testutils/clients.go +++ b/selvpcclient/testutils/clients.go @@ -1,56 +1,32 @@ package testutils import ( - "net/http" - "testing" + "log" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/resell" + "github.com/gophercloud/gophercloud" + + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients" + clientservices "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients/services" ) -// NewTestResellV2Client prepares a client for the Resell V2 API tests. -func (testEnv *TestEnv) NewTestResellV2Client() { - apiVersion := "v2" - resellClient := &selvpcclient.ServiceClient{ - HTTPClient: &http.Client{}, - Endpoint: testEnv.Server.URL + "/resell/" + apiVersion, - TokenID: FakeTokenID, - UserAgent: resell.UserAgent, +func (testEnv *TestEnv) NewSelVPCClient() { + serviceClient := &gophercloud.ServiceClient{ + ProviderClient: &gophercloud.ProviderClient{TokenID: FakeTokenID}, + Endpoint: testEnv.Server.URL + "/", // gophercloud endpoints doesn't start with / } - testEnv.Client = resellClient -} - -type TestIdentityMgr struct { - ServerURL string -} -func (mgr TestIdentityMgr) GetToken() (string, error) { - return "some_token", nil -} + serviceClient.ProviderClient.Context = testEnv.Context -func (mgr TestIdentityMgr) GetEndpointForRegion(region string) (string, error) { - return mgr.ServerURL, nil -} - -// NewTestRegionalClient prepares a client for the quota V1 API tests. -func (testEnv *TestQuotasEnv) NewTestRegionalClient() { - identity := TestIdentityMgr{ - ServerURL: testEnv.Server.URL, + catalogService, err := clientservices.NewCatalogService(serviceClient) + if err != nil { + log.Fatalf("failed to initialize endpoints catalog service, err: %v", err) } - regionalClient := quotamanager.NewQuotaRegionalClient(&http.Client{}, identity) - testEnv.Client = regionalClient -} -// CompareClients compares two ServiceClients. -func CompareClients(t *testing.T, expected, actual *selvpcclient.ServiceClient) { - if expected.Endpoint != actual.Endpoint { - t.Errorf("expected Endpoint %s, but got %s", expected.Endpoint, actual.Endpoint) - } - if expected.TokenID != actual.TokenID { - t.Errorf("expected TokenID %s, but got %s", expected.TokenID, actual.TokenID) - } - if expected.UserAgent != actual.UserAgent { - t.Errorf("expected UserAgent %s, but got %s", expected.UserAgent, actual.UserAgent) + requestService := clientservices.NewRequestService(serviceClient) + + testEnv.Client = &selvpcclient.Client{ + Resell: clients.NewResellClient(requestService, catalogService), + QuotaManager: clients.NewQuotaManagerClient(requestService, catalogService), } } diff --git a/selvpcclient/testutils/environment.go b/selvpcclient/testutils/environment.go index 21f9dc3..e8b4785 100644 --- a/selvpcclient/testutils/environment.go +++ b/selvpcclient/testutils/environment.go @@ -1,61 +1,72 @@ package testutils import ( + "context" + "fmt" + "html/template" + "log" "net/http" "net/http/httptest" - "github.com/selectel/go-selvpcclient/v2/selvpcclient" - "github.com/selectel/go-selvpcclient/v2/selvpcclient/quotamanager" + "github.com/selectel/go-selvpcclient/v3/selvpcclient" + "github.com/selectel/go-selvpcclient/v3/selvpcclient/clients" ) // TestEnv represents a testing environment for all resources. type TestEnv struct { - Mux *http.ServeMux - Server *httptest.Server - Client *selvpcclient.ServiceClient + Mux *http.ServeMux + Server *httptest.Server + Client *selvpcclient.Client + Context context.Context } // SetupTestEnv prepares the new testing environment. func SetupTestEnv() *TestEnv { + ctx := context.Background() mux := http.NewServeMux() server := httptest.NewServer(mux) + testEnv := &TestEnv{ - Mux: mux, - Server: server, + Mux: mux, + Server: server, + Context: ctx, } - return testEnv -} + err := testEnv.TokenMock() + if err != nil { + log.Fatalf("failed to create mock for token info request, err: %v", err) + } -// TearDownTestEnv releases the testing environment. -func (testEnv *TestEnv) TearDownTestEnv() { - testEnv.Server.Close() - testEnv.Server = nil - testEnv.Mux = nil - testEnv.Client = nil + return testEnv } -// TestQuotasEnv represents a testing environment for quotas. -type TestQuotasEnv struct { - Mux *http.ServeMux - Server *httptest.Server - Client *quotamanager.QuotaRegionalClient -} +// TokenMock - mock for /auth/token. This is mock is required to resolve endpoint of service from Keystone catalog. +func (testEnv *TestEnv) TokenMock() error { + tmpl, err := template.New("token").Parse(TokenInfo) + if err != nil { + log.Fatalf("failed to parse token tamplate /auth/token mock, err: %v", err) + } -// SetupTestQuotasEnv prepares the new quotas testing environment. -func SetupTestQuotasEnv() *TestQuotasEnv { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - testEnv := &TestQuotasEnv{ - Mux: mux, - Server: server, + data := TokenInfoTemplate{ + QuotaManagerEndpoint: testEnv.Server.URL, + ResellEndpoint: fmt.Sprintf("%s/%s", testEnv.Server.URL, clients.ResellServiceType), } - return testEnv + testEnv.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + err = tmpl.Execute(w, data) + if err != nil { + log.Fatalf("failed to execute template for /auth/token mock, err: %v", err) + } + }) + + return nil } // TearDownTestEnv releases the testing environment. -func (testEnv *TestQuotasEnv) TearDownTestEnv() { +func (testEnv *TestEnv) TearDownTestEnv() { testEnv.Server.Close() testEnv.Server = nil testEnv.Mux = nil diff --git a/selvpcclient/testutils/fakes.go b/selvpcclient/testutils/fakes.go index c76f893..4f000a7 100644 --- a/selvpcclient/testutils/fakes.go +++ b/selvpcclient/testutils/fakes.go @@ -2,3 +2,66 @@ package testutils // FakeTokenID is a fake token for the Selectel VPC API. const FakeTokenID = "fakeUUID" + +const TokenInfo = ` +{ + "token": { + "catalog": [ + { + "endpoints": [ + { + "id": "8daa99650cff4502874f30bafa6fc8a8", + "interface": "public", + "region_id": "ru-1", + "url": "{{ .QuotaManagerEndpoint}}", + "region": "ru-1" + }, + { + "id": "5040e0815ace4a7e9eeac3a1706ad899", + "interface": "public", + "region_id": "ru-3", + "url": "https://api.selvpc/quota-manager/v1", + "region": "ru-3" + }, + { + "id": "95a24577049349309bb949a5f8bcc253", + "interface": "admin", + "region_id": "ru-1", + "url": "http://ru-1.openstack:63079", + "region": "ru-1" + } + ], + "id": "73bbae11073b4e34b7c8fcf7dfc27ef1", + "type": "quota-manager", + "name": "bizeff" + }, + { + "endpoints": [ + { + "id":"8a2bd27225434e098068f49af7cd6f79", + "interface":"public", + "region_id":"ru-1", + "url":"{{ .ResellEndpoint}}", + "region":"ru-1" + }, + { + "id":"2934bf5234e54bd3bfef8544893a5e71", + "interface":"public", + "region_id":"ru-2", + "url":"{{ .ResellEndpoint}}", + "region":"ru-2" + } + ], + "id":"5549d38ff47b4dbfb406d5b459023090", + "type":"resell", + "name":"hong" + } + ] + } +} +` + +type TokenInfoTemplate struct { + QuotaManagerEndpoint string + ResellEndpoint string +} diff --git a/selvpcclient/testutils/handlers.go b/selvpcclient/testutils/handlers.go index 4a75284..6c07508 100644 --- a/selvpcclient/testutils/handlers.go +++ b/selvpcclient/testutils/handlers.go @@ -3,7 +3,7 @@ package testutils import ( "encoding/json" "fmt" - "io/ioutil" //nolint:staticcheck + "io" "net/http" "reflect" "testing" @@ -58,7 +58,7 @@ func HandleReqWithBody(t *testing.T, opts *HandleReqOpts) { t.Fatalf("expected %s method but got %s", opts.Method, r.Method) } - b, err := ioutil.ReadAll(r.Body) + b, err := io.ReadAll(r.Body) if err != nil { t.Errorf("unable to read the request body: %v", err) }