Skip to content

Commit

Permalink
Merge 8ecfb67 into 647897b
Browse files Browse the repository at this point in the history
  • Loading branch information
T-Sh committed Nov 25, 2022
2 parents 647897b + 8ecfb67 commit 98f7e44
Show file tree
Hide file tree
Showing 30 changed files with 1,499 additions and 1,944 deletions.
4 changes: 2 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ linters:
- dogsled
- errcheck
- exportloopref
- gci
# - gci
- gocognit
- goconst
- gocritic
Expand All @@ -32,7 +32,7 @@ linters:
- misspell
- nakedret
- noctx
- nolintlint
# - nolintlint
- prealloc
- rowserrcheck
- scopelint
Expand Down
126 changes: 108 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ You can use this library to work with the following objects of the Selectel VPC
* [keypairs](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/keypairs)
* [licenses](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/licenses)
* [projects](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/projects)
* [quotas](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/quotas)
* [quotas](https://godoc.org/github.com/selectel/go-selvpcclient/quotamanager/quotas)
* [roles](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/roles)
* [subnets](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/subnets)
* [tokens](https://godoc.org/github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/tokens)
Expand Down Expand Up @@ -56,29 +56,119 @@ To work with the Selectel VPC API you first need to:
package main

import (
"context"
"fmt"
"log"
"context"
"fmt"
"log"

resell "github.com/selectel/go-selvpcclient/selvpcclient/resell/v2"
"github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/projects"
resell "github.com/selectel/go-selvpcclient/selvpcclient/resell/v2"
"github.com/selectel/go-selvpcclient/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)
}
// 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/selvpcclient"
"github.com/selectel/go-selvpcclient/selvpcclient/quotamanager"
"github.com/selectel/go-selvpcclient/selvpcclient/quotamanager/quotas"
resell "github.com/selectel/go-selvpcclient/selvpcclient/resell/v2"
reselTokens "github.com/selectel/go-selvpcclient/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
)

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 <projectID> in region <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)
}

// Get quotas for project <projectID> in region <region>.
quotasData, _, err := quotas.GetProjectQuotas(ctx, quotaMgr, projectID, region)
if err != nil {
log.Fatal(err)
}

for _, quota := range quotasData {
fmt.Println(quota.Name, quota.ResourceQuotasEntities)
}

// Update quotas for project <projectID> in region <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)
if err != nil {
log.Fatal(err)
}

for _, quota := range updatedQuotasData {
fmt.Println(quota.Name, quota.ResourceQuotasEntities)
}
}
```
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/selectel/go-selvpcclient

go 1.14

require github.com/gophercloud/gophercloud v1.0.0
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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=
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=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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=
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=
130 changes: 130 additions & 0 deletions selvpcclient/quotamanager/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package quotamanager

import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil" //nolint:staticcheck
"net/http"
"strings"
"unicode"

"github.com/selectel/go-selvpcclient/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
}
17 changes: 17 additions & 0 deletions selvpcclient/quotamanager/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
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

0 comments on commit 98f7e44

Please sign in to comment.