diff --git a/.github/workflows/golang-build.yaml b/.github/workflows/golang-build.yaml new file mode 100644 index 0000000..0d7980b --- /dev/null +++ b/.github/workflows/golang-build.yaml @@ -0,0 +1,24 @@ +name: Golang Build + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + go-version: ["1.18", "1.19", "1.20"] + + steps: + - uses: actions/checkout@v3 + - name: Setup Go ${{ matrix.go-version }} + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + - name: Building + run: go build -v ./... + - name: Running golangci-lint + uses: golangci/golangci-lint-action@v3 + - name: Testing + run: go test -v ./... diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 871ab85..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -language: go - -cache: - directories: - - $GOPATH/pkg/mod - -jobs: - fast_finish: true - include: - - go: 1.12.x - - go: 1.13.x - - go: 1.14.x - - go: 1.x - - go: tip - allow_failures: - - go: tip - -before_install: - - export GO111MODULE=off - - go get github.com/axw/gocov/gocov - - go get github.com/mattn/goveralls - - go get golang.org/x/lint/golint - - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi - - GO111MODULE=on - -install: - - go mod tidy - - git diff --exit-code go.mod - - git diff --exit-code go.sum - - go mod download - -script: - # Test Code quality - - go vet ./... - - ${GOPATH}/bin/golint ./... - - go test -covermode=count -coverprofile=profile.cov ./... - - # Test buildable on most common platforms, beyond Linux - - GOOS=darwin go build ./... - - GOOS=windows go build ./... - - # Best effort: notify coveralls. It's too unstable, ignore errors. - - $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci || exit 0 diff --git a/README.md b/README.md index 67fcfb2..4293db8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ go-ovh Lightweight Go wrapper around OVH's APIs. Handles all the hard work including credential creation and requests signing. [![GoDoc](https://godoc.org/github.com/ovh/go-ovh/go-ovh?status.svg)](http://godoc.org/github.com/ovh/go-ovh/ovh) -[![Build Status](https://travis-ci.org/ovh/go-ovh.svg?branch=master)](https://travis-ci.org/ovh/go-ovh) +[![Build Status](https://github.com/ovh/go-ovh/actions/workflows/golang-build.yaml/badge.svg?branch=master)](https://github.com/ovh/go-ovh/actions?query=workflow:golang-build) [![Coverage Status](https://coveralls.io/repos/github/ovh/go-ovh/badge.svg?branch=master)](https://coveralls.io/github/ovh/go-ovh?branch=master) [![Go Report Card](https://goreportcard.com/badge/ovh/go-ovh)](http://goreportcard.com/report/ovh/go-ovh) @@ -40,7 +40,7 @@ func main() { ## Installation -The Golang wrapper has been tested with Golang 1.5+. It may worker with older versions although it has not been tested. +The Golang wrapper has been tested with Golang 1.18+. It may worker with older versions although it has not been tested. To use it, just include it to your ``import`` and run ``go get``: diff --git a/go.mod b/go.mod index 1b281ee..7ee6f86 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,7 @@ module github.com/ovh/go-ovh -go 1.12 +go 1.18 -require ( - // required by gopkg.in/ini.v1 unit tests... - github.com/smartystreets/goconvey v1.6.4 // indirect - gopkg.in/ini.v1 v1.57.0 -) +require gopkg.in/ini.v1 v1.67.0 + +require github.com/stretchr/testify v1.8.2 // indirect diff --git a/go.sum b/go.sum index 51611ab..5c407e4 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,18 @@ -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= -gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ovh/configuration.go b/ovh/configuration.go index 4cc624d..51713bb 100644 --- a/ovh/configuration.go +++ b/ovh/configuration.go @@ -19,18 +19,16 @@ var ( // currentUserHome attempts to get current user's home directory func currentUserHome() (string, error) { - userHome := "" usr, err := user.Current() if err != nil { // Fallback by trying to read $HOME - userHome = os.Getenv("HOME") - if userHome != "" { - err = nil + if userHome := os.Getenv("HOME"); userHome != "" { + return userHome, nil } - } else { - userHome = usr.HomeDir + return "", err } - return userHome, nil + + return usr.HomeDir, nil } // appendConfigurationFile only if it exists. We need to do this because @@ -38,8 +36,8 @@ func currentUserHome() (string, error) { // file is missing. This is racy, but better than always failing. func appendConfigurationFile(cfg *ini.File, path string) { if file, err := os.Open(path); err == nil { - file.Close() - cfg.Append(path) + defer file.Close() + _ = cfg.Append(path) } } @@ -57,7 +55,6 @@ func appendConfigurationFile(cfg *ini.File, path string) { // - ./ovh.conf // - $HOME/.ovh.conf // - /etc/ovh.conf -// func (c *Client) loadConfig(endpointName string) error { // Load configuration files by order of increasing priority. All configuration // files are optional. Only load file from user home if home could be resolve @@ -107,7 +104,7 @@ func (c *Client) loadConfig(endpointName string) error { return nil } -// getConfigValue returns the value of OVH_ or ``name`` value from ``section``. If +// getConfigValue returns the value of OVH_ or "name" value from "section". If // the value could not be read from either env or any configuration files, return 'def' func getConfigValue(cfg *ini.File, section, name, def string) string { // Attempt to load from environment diff --git a/ovh/configuration_test.go b/ovh/configuration_test.go index c07057c..76840ea 100644 --- a/ovh/configuration_test.go +++ b/ovh/configuration_test.go @@ -34,28 +34,30 @@ func TestConfigFromFiles(t *testing.T) { // This is a simple way to test precedence // Prepare - ioutil.WriteFile(systemConfigPath, []byte(` + _ = ioutil.WriteFile(systemConfigPath, []byte(` [ovh-eu] application_key=system application_secret=system consumer_key=system `), 0660) - ioutil.WriteFile(home+userConfigPath, []byte(` + _ = ioutil.WriteFile(home+userConfigPath, []byte(` [ovh-eu] application_secret=user consumer_key=user `), 0660) - ioutil.WriteFile(localConfigPath, []byte(` + _ = ioutil.WriteFile(localConfigPath, []byte(` [ovh-eu] consumer_key=local `), 0660) // Clear - defer ioutil.WriteFile(systemConfigPath, []byte(``), 0660) - defer ioutil.WriteFile(home+userConfigPath, []byte(``), 0660) - defer ioutil.WriteFile(localConfigPath, []byte(``), 0660) + t.Cleanup(func() { + _ = ioutil.WriteFile(systemConfigPath, []byte(``), 0660) + _ = ioutil.WriteFile(home+userConfigPath, []byte(``), 0660) + _ = ioutil.WriteFile(localConfigPath, []byte(``), 0660) + }) // Test client := Client{} @@ -82,7 +84,7 @@ func TestConfigFromOnlyOneFile(t *testing.T) { // Prepare os.Remove(systemConfigPath) - ioutil.WriteFile(home+userConfigPath, []byte(` + _ = ioutil.WriteFile(home+userConfigPath, []byte(` [ovh-eu] application_key=user application_secret=user @@ -90,7 +92,9 @@ consumer_key=user `), 0660) // Clear - defer ioutil.WriteFile(home+userConfigPath, []byte(``), 0660) + t.Cleanup(func() { + _ = ioutil.WriteFile(home+userConfigPath, []byte(``), 0660) + }) // Test client := Client{} @@ -113,24 +117,21 @@ consumer_key=user func TestConfigFromEnv(t *testing.T) { // Prepare - ioutil.WriteFile(systemConfigPath, []byte(` + _ = ioutil.WriteFile(systemConfigPath, []byte(` [ovh-eu] application_key=fail application_secret=fail consumer_key=fail `), 0660) - defer ioutil.WriteFile(systemConfigPath, []byte(``), 0660) - os.Setenv("OVH_ENDPOINT", "ovh-eu") - os.Setenv("OVH_APPLICATION_KEY", "env") - os.Setenv("OVH_APPLICATION_SECRET", "env") - os.Setenv("OVH_CONSUMER_KEY", "env") + t.Cleanup(func() { + _ = ioutil.WriteFile(systemConfigPath, []byte(``), 0660) + }) - // Clear - defer os.Unsetenv("OVH_ENDPOINT") - defer os.Unsetenv("OVH_APPLICATION_KEY") - defer os.Unsetenv("OVH_APPLICATION_SECRET") - defer os.Unsetenv("OVH_CONSUMER_KEY") + t.Setenv("OVH_ENDPOINT", "ovh-eu") + t.Setenv("OVH_APPLICATION_KEY", "env") + t.Setenv("OVH_APPLICATION_SECRET", "env") + t.Setenv("OVH_CONSUMER_KEY", "env") // Test client := Client{} @@ -183,7 +184,7 @@ func TestConfigFromArgs(t *testing.T) { func TestEndpoint(t *testing.T) { // Prepare - ioutil.WriteFile(systemConfigPath, []byte(` + _ = ioutil.WriteFile(systemConfigPath, []byte(` [ovh-eu] application_key=ovh application_secret=ovh @@ -196,7 +197,9 @@ consumer_key=example.com `), 0660) // Clear - defer ioutil.WriteFile(systemConfigPath, []byte(``), 0660) + t.Cleanup(func() { + _ = ioutil.WriteFile(systemConfigPath, []byte(``), 0660) + }) // Test: by name client := Client{} diff --git a/ovh/ovh.go b/ovh/ovh.go index d06991a..0b78ada 100644 --- a/ovh/ovh.go +++ b/ovh/ovh.go @@ -86,7 +86,7 @@ func NewClient(endpoint, appKey, appSecret, consumerKey string) (*Client, error) AppSecret: appSecret, ConsumerKey: consumerKey, Client: &http.Client{}, - Timeout: time.Duration(DefaultTimeout), + Timeout: DefaultTimeout, } // Get and check the configuration @@ -369,7 +369,7 @@ func (c *Client) CallAPI(method, path string, reqBody, resType interface{}, need // - full serialized request body // - server current time (takes time delta into account) // -// Context is used by http.Client to handle context cancelation +// Context is used by http.Client to handle context cancelation. // // Call will automatically assemble the target url from the endpoint // configured in the client instance and the path argument. If the reqBody diff --git a/ovh/ovh_test.go b/ovh/ovh_test.go index 1b8e2c5..93549f6 100644 --- a/ovh/ovh_test.go +++ b/ovh/ovh_test.go @@ -186,7 +186,7 @@ func APIMethodTester(t *testing.T, HTTPmethod string, body interface{}, expected sleep := time.Duration(0) var failureExpected bool if cancel || contextTimeout { - sleep = time.Duration(2) * time.Second + sleep = 300 * time.Millisecond failureExpected = true } ts, client := initMockServer(&InputRequest, 200, `"success"`, &InputRequestBody, sleep) @@ -341,7 +341,7 @@ func TestGetResponse(t *testing.T) { Body: ioutil.NopCloser(strings.NewReader(``)), }, nil) if err != nil { - t.Fatalf("UnmarshalResponse should not return an error when reponse is empty or target type is nil. Got %v", err) + t.Fatalf("UnmarshalResponse should not return an error when response is empty or target type is nil. Got %v", err) } // Error