Skip to content

Add verbose #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.20'
go-version: '1.22'
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.53
version: v1.63

2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.20.x, 1.21.x]
go-version: [1.21.x, 1.22.x]
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand Down
14 changes: 9 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
module github.com/serverscom/serverscom-go-client

go 1.18
go 1.22.0

require github.com/onsi/gomega v1.5.0
require (
github.com/go-resty/resty/v2 v2.16.2
github.com/onsi/gomega v1.36.2
)

require (
golang.org/x/net v0.23.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
50 changes: 26 additions & 24 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3 changes: 2 additions & 1 deletion pkg/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ func (col *CollectionHandler[K]) Refresh(ctx context.Context) error {
func (col *CollectionHandler[K]) fireHTTPRequest(ctx context.Context) error {
var accumulatedCollectionElements []K

//nolint:govet
initialURL := col.client.buildURL(col.path)
url := col.client.applyParams(
initialURL,
Expand All @@ -252,7 +253,7 @@ func (col *CollectionHandler[K]) fireHTTPRequest(ctx context.Context) error {

col.clean = false
col.collection = accumulatedCollectionElements
col.rels = hyperHeaderParser(response.Header)
col.rels = hyperHeaderParser(response.Header())

return nil
}
Expand Down
81 changes: 33 additions & 48 deletions pkg/serverscom.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package serverscom

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"

"github.com/go-resty/resty/v2"
)

const defaultAPIEndpoint string = "https://api.servers.com/v1"
Expand Down Expand Up @@ -40,9 +40,7 @@ type Client struct {

KubernetesClusters KubernetesClustersService

token string

client *http.Client
client *resty.Client
}

// NewClient builds a new client with token
Expand All @@ -56,13 +54,15 @@ func NewClientWithEndpoint(token, baseURL string) *Client {
Proxy: http.ProxyFromEnvironment,
}

client := &http.Client{Transport: tr}
rClient := resty.NewWithClient(&http.Client{Transport: tr})

rClient.SetAuthToken(token)
rClient.SetHeader("Content-Type", "application/json")
rClient.SetHeader("User-Agent", "go-serverscom-client")

scClient := &Client{
baseURL: baseURL,
UserAgent: "go-serverscom-client",
token: token,
client: client,
baseURL: baseURL,
client: rClient,
}

scClient.configureResources()
Expand All @@ -75,6 +75,11 @@ func (cli *Client) SetupUserAgent(userAgent string) {
cli.UserAgent = userAgent
}

// SetVerbose sets debug mode for client
func (cli *Client) SetVerbose(verbose bool) {
cli.client.SetDebug(verbose)
}

func (cli *Client) configureResources() {
cli.CloudComputingInstances = &CloudComputingInstancesHandler{cli}
cli.Hosts = &HostsHandler{cli}
Expand Down Expand Up @@ -122,51 +127,31 @@ func (cli *Client) applyParams(endpointURL string, params map[string]string) str
)
}

func (cli *Client) buildAndExecRequestWithResponse(ctx context.Context, method, endpointURL string, body []byte) (*http.Response, []byte, error) {
var req *http.Request
var err error
func (cli *Client) buildAndExecRequestWithResponse(ctx context.Context, method, endpointURL string, body []byte) (*resty.Response, []byte, error) {
request := cli.client.R().SetContext(ctx)

if body != nil {
reader := bytes.NewReader(body)
req, err = http.NewRequest(method, endpointURL, reader)
} else {
req, err = http.NewRequest(method, endpointURL, nil)
}

if err != nil {
return nil, nil, err
request.SetBody(body)
}

req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", cli.token))
req.Header.Add("Content-Type", "application/json")
req.Header.Set("User-Agent", cli.UserAgent)

resp, err := cli.client.Do(req.WithContext(ctx))

resp, err := request.Execute(method, endpointURL)
if err != nil {
return nil, nil, fmt.Errorf("Client request error: %q", err)
}

defer resp.Body.Close()

contents, err := ioutil.ReadAll(resp.Body)
contents := resp.Body()

if err != nil {
return nil, nil, fmt.Errorf("Client can't read body: %q", err)
}

if resp.StatusCode < 400 {
if resp.StatusCode() < 400 {
return resp, contents, nil
}

contentType := resp.Header.Get("Content-Type")

var responseError = responseErrorWrapper{}
contentType := resp.Header().Get("Content-Type")
var responseError responseErrorWrapper

if strings.HasPrefix(contentType, "application/json") {
if err := json.Unmarshal(contents, &responseError); err != nil {
return nil, nil, newParsingError(
resp.StatusCode,
resp.StatusCode(),
string(contents),
err,
)
Expand All @@ -176,23 +161,23 @@ func (cli *Client) buildAndExecRequestWithResponse(ctx context.Context, method,
responseError.Message = string(contents)
}

switch resp.StatusCode {
switch resp.StatusCode() {
case 400:
return nil, nil, newBadRequestError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newBadRequestError(resp.StatusCode(), responseError.Code, responseError.Message)
case 401:
return nil, nil, newUnauthorizedError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newUnauthorizedError(resp.StatusCode(), responseError.Code, responseError.Message)
case 403:
return nil, nil, newForbiddenError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newForbiddenError(resp.StatusCode(), responseError.Code, responseError.Message)
case 404:
return nil, nil, newNotFoundError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newNotFoundError(resp.StatusCode(), responseError.Code, responseError.Message)
case 409:
return nil, nil, newConflictError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newConflictError(resp.StatusCode(), responseError.Code, responseError.Message)
case 422:
return nil, nil, newUnprocessableEntityError(resp.StatusCode, responseError.Code, responseError.Message, responseError.Errors)
return nil, nil, newUnprocessableEntityError(resp.StatusCode(), responseError.Code, responseError.Message, responseError.Errors)
case 500:
return nil, nil, newInternalServerError(resp.StatusCode, responseError.Code, responseError.Message)
return nil, nil, newInternalServerError(resp.StatusCode(), responseError.Code, responseError.Message)
default:
return nil, nil, fmt.Errorf("Unexpected response code: %d, with body: %s", resp.StatusCode, string(contents))
return nil, nil, fmt.Errorf("Unexpected response code: %d, with body: %s", resp.StatusCode(), string(contents))
}
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package serverscom
import (
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
Expand Down Expand Up @@ -103,7 +103,7 @@ func (fs *fakeServer) WithResponseBodyStub(filename string) *fakeServer {
_, currentFile, _, _ := runtime.Caller(1)
stubFilePath := path.Join(path.Dir(currentFile), "..", filename)

stub, err := ioutil.ReadFile(stubFilePath)
stub, err := os.ReadFile(stubFilePath)
if err != nil {
panic(fmt.Sprintf("Stub error: %q", err))
}
Expand All @@ -127,7 +127,7 @@ func (fs *fakeServer) WithResponseBodyStubFile(filePath string) *fakeServer {

defer f.Close()

b, err := ioutil.ReadAll(f)
b, err := io.ReadAll(f)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -179,7 +179,7 @@ func (fs *fakeServer) Build() (*fakeServer, *Client) {
}

if currentRequest.RequestBody != "" {
b, err := ioutil.ReadAll(r.Body)
b, err := io.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
Expand Down
2 changes: 1 addition & 1 deletion pkg/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ type SSHKeyCreateInput struct {

// SSHKeyUpdateInput represents ssh key update input
type SSHKeyUpdateInput struct {
Name string `json:"name"`
Name string `json:"name,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}

Expand Down
Loading