From a105c7cce29595441d5faa28b8a7569a30dfb9c0 Mon Sep 17 00:00:00 2001 From: Ryan SVIHLA Date: Wed, 31 Mar 2021 14:20:23 +0200 Subject: [PATCH] Error message cleanup (#12) * additional testing * increased linting, bumped sdk for better errors * updated golang ci version --- .golangci.yml | 36 +++++++++ README.md | 2 +- cmd/db.go | 2 +- cmd/db/create.go | 5 +- cmd/db/create_test.go | 8 +- cmd/db/delete.go | 4 +- cmd/db/delete_test.go | 4 +- cmd/db/get.go | 10 +-- cmd/db/get_test.go | 22 ++++-- cmd/db/list.go | 14 ++-- cmd/db/list_test.go | 26 +++++-- cmd/db/park.go | 23 +++--- cmd/db/park_test.go | 15 +++- cmd/db/resize.go | 14 ++-- cmd/db/resize_test.go | 14 ++-- cmd/db/secBundle.go | 8 +- cmd/db/secBundle_test.go | 68 ++++++++++++++++- cmd/db/tiers.go | 104 ++++++++++++++----------- cmd/db/tiers_test.go | 144 ++++++++++++++++++++++++++++++++++- cmd/db/unpark.go | 4 +- cmd/db/unpark_test.go | 6 +- cmd/db_test.go | 2 +- cmd/login.go | 26 ++++--- cmd/login_test.go | 2 +- cmd/root.go | 4 +- cmd/root_test.go | 2 +- go.mod | 2 +- go.sum | 5 +- pkg/conf.go | 8 +- pkg/conf_test.go | 8 +- pkg/const.go | 23 ++++++ pkg/env/env.go | 4 +- pkg/errors.go | 14 ++-- pkg/errors_test.go | 2 +- pkg/httputils/client.go | 29 ++++--- pkg/httputils/client_test.go | 2 +- pkg/login.go | 13 ++-- pkg/login_test.go | 2 +- pkg/strfmt.go | 4 +- pkg/strfmt_test.go | 2 +- pkg/tests/client.go | 31 ++++---- pkg/tests/client_test.go | 14 ++-- script/bootstrap | 2 +- 43 files changed, 523 insertions(+), 211 deletions(-) create mode 100644 pkg/const.go diff --git a/.golangci.yml b/.golangci.yml index 76be012..bcab67c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,39 @@ issues: exclude: SA1019 +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dogsled + - dupl + - errcheck + - exhaustive + - funlen + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - golint + - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - misspell + - nakedret + - nolintlint + - rowserrcheck + - scopelint + - staticcheck + - structcheck + - typecheck + - unconvert + - unparam + - unused + - varcheck + - whitespace diff --git a/README.md b/README.md index c4b57fb..568e60c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Apache 2.0 licensed Astra Cloud Management CLI ## status -- Alpha +Ready for production ## How to install - Homebrew for Mac and Linux diff --git a/cmd/db.go b/cmd/db.go index 1d26d2e..41dbdae 100644 --- a/cmd/db.go +++ b/cmd/db.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd contains all fo the commands for the cli +// Package cmd contains all fo the commands for the cli package cmd import ( diff --git a/cmd/db/create.go b/cmd/db/create.go index 2b738ec..c222ed4 100644 --- a/cmd/db/create.go +++ b/cmd/db/create.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -42,10 +42,9 @@ func init() { CreateCmd.Flags().StringVarP(&createDbTier, "tier", "t", "serverless", "tier to give to the Astra Database") CreateCmd.Flags().IntVarP(&createDbCapacityUnit, "capacityUnit", "c", 1, "capacityUnit flag to give to the Astra Database") CreateCmd.Flags().StringVarP(&createDbCloudProvider, "cloudProvider", "l", "GCP", "cloud provider flag to give to the Astra Database") - } -//CreateCmd creates a database in Astra +// CreateCmd creates a database in Astra var CreateCmd = &cobra.Command{ Use: "create", Short: "creates a database by id", diff --git a/cmd/db/create_test.go b/cmd/db/create_test.go index 7b169d7..c4a5a39 100644 --- a/cmd/db/create_test.go +++ b/cmd/db/create_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -26,7 +26,7 @@ import ( func TestCreateGetsId(t *testing.T) { expectedID := "abcd" - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{ Databases: []astraops.Database{ { @@ -46,7 +46,7 @@ func TestCreateGetsId(t *testing.T) { } } func TestCreateLoginFails(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{} err := executeCreate(func() (pkg.Client, error) { return mockClient, fmt.Errorf("service down") @@ -65,7 +65,7 @@ func TestCreateLoginFails(t *testing.T) { } func TestCreateFails(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{ ErrorQueue: []error{fmt.Errorf("service down")}, } diff --git a/cmd/db/delete.go b/cmd/db/delete.go index c02b38f..af047c0 100644 --- a/cmd/db/delete.go +++ b/cmd/db/delete.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db provides the sub-commands for the db command +// Package db provides the sub-commands for the db command package db import ( @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" ) -//DeleteCmd provides the delete database command +// DeleteCmd provides the delete database command var DeleteCmd = &cobra.Command{ Use: "delete ", Short: "delete database by databaseID", diff --git a/cmd/db/delete_test.go b/cmd/db/delete_test.go index 1a706cf..a641064 100644 --- a/cmd/db/delete_test.go +++ b/cmd/db/delete_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -62,7 +62,7 @@ func TestDeleteLoginError(t *testing.T) { } if "" != msg { - t.Errorf("expected emtpy but was '%v'", msg) + t.Errorf("expected empty but was '%v'", msg) } } diff --git a/cmd/db/get.go b/cmd/db/get.go index b64ecb5..77bfa48 100644 --- a/cmd/db/get.go +++ b/cmd/db/get.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db provides the sub-commands for the db command +// Package db provides the sub-commands for the db command package db import ( @@ -32,7 +32,7 @@ func init() { GetCmd.Flags().StringVarP(&getFmt, "output", "o", "text", "Output format for report default is text") } -//GetCmd provides the get database command +// GetCmd provides the get database command var GetCmd = &cobra.Command{ Use: "get ", Short: "get database by databaseID", @@ -60,7 +60,7 @@ func executeGet(args []string, login func() (pkg.Client, error)) (string, error) return "", fmt.Errorf("unable to get '%s' with error %v", id, err) } switch getFmt { - case "text": + case pkg.TextFormat: var rows [][]string rows = append(rows, []string{"name", "id", "status"}) rows = append(rows, []string{db.Info.Name, db.ID, string(db.Status)}) @@ -70,13 +70,13 @@ func executeGet(args []string, login func() (pkg.Client, error)) (string, error) return "", fmt.Errorf("unexpected error writing out text %v", err) } return buf.String(), nil - case "json": + case pkg.JSONFormat: b, err := json.MarshalIndent(db, "", " ") if err != nil { return "", fmt.Errorf("unexpected error marshaling to json: '%v', Try -output text instead", err) } return string(b), nil default: - return "", fmt.Errorf("-output %q is not valid option", getFmt) + return "", fmt.Errorf("-o %q is not valid option", getFmt) } } diff --git a/cmd/db/get_test.go b/cmd/db/get_test.go index 584b130..318ce75 100644 --- a/cmd/db/get_test.go +++ b/cmd/db/get_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -26,7 +26,7 @@ import ( ) func TestGet(t *testing.T) { - getFmt = "json" + getFmt = pkg.JSONFormat dbs := []astraops.Database{ {ID: "1"}, {ID: "2"}, @@ -35,7 +35,6 @@ func TestGet(t *testing.T) { return &tests.MockClient{ Databases: dbs, }, nil - }) if err != nil { t.Fatalf("unexpected error %v", err) @@ -51,7 +50,7 @@ func TestGet(t *testing.T) { } func TestGetText(t *testing.T) { - getFmt = "text" + getFmt = pkg.TextFormat dbs := []astraops.Database{ { ID: "1", @@ -72,7 +71,6 @@ func TestGetText(t *testing.T) { return &tests.MockClient{ Databases: dbs, }, nil - }) if err != nil { t.Fatalf("unexpected error %v", err) @@ -86,3 +84,17 @@ func TestGetText(t *testing.T) { t.Errorf("expected '%v' but was '%v'", expected, txt) } } + +func TestGetInvalidFmt(t *testing.T) { + getFmt = "badham" + _, err := executeGet([]string{"abc"}, func() (pkg.Client, error) { + return &tests.MockClient{}, nil + }) + if err == nil { + t.Fatalf("unexpected error %v", err) + } + expected := "-o \"badham\" is not valid option" + if err.Error() != expected { + t.Errorf("expected '%v' but was '%v'", expected, err.Error()) + } +} diff --git a/cmd/db/list.go b/cmd/db/list.go index 2340ab3..d39a3ac 100644 --- a/cmd/db/list.go +++ b/cmd/db/list.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db provides the sub-commands for the db command +// Package db provides the sub-commands for the db command package db import ( @@ -40,14 +40,14 @@ func init() { ListCmd.Flags().StringVarP(&listFmt, "output", "o", "text", "Output format for report default is json") } -//ListCmd provides the list databases command +// ListCmd provides the list databases command var ListCmd = &cobra.Command{ Use: "list", Short: "lists all databases", Long: `lists all databases in your Astra account`, Run: func(cmd *cobra.Command, args []string) { creds := &pkg.Creds{} - msg, err := executeList(args, creds.Login) + msg, err := executeList(creds.Login) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) @@ -56,7 +56,7 @@ var ListCmd = &cobra.Command{ }, } -func executeList(args []string, login func() (pkg.Client, error)) (string, error) { +func executeList(login func() (pkg.Client, error)) (string, error) { client, err := login() if err != nil { return "", fmt.Errorf("unable to login with error '%v'", err) @@ -66,7 +66,7 @@ func executeList(args []string, login func() (pkg.Client, error)) (string, error return "", fmt.Errorf("unable to get list of dbs with error '%v'", err) } switch listFmt { - case "text": + case pkg.TextFormat: var rows [][]string rows = append(rows, []string{"name", "id", "status"}) for _, db := range dbs { @@ -78,13 +78,13 @@ func executeList(args []string, login func() (pkg.Client, error)) (string, error return "", fmt.Errorf("unexpected error writing text output '%v'", err) } return out.String(), nil - case "json": + case pkg.JSONFormat: b, err := json.MarshalIndent(dbs, "", " ") if err != nil { return "", fmt.Errorf("unexpected error marshaling to json: '%v', Try -output text instead", err) } return string(b), nil default: - return "", fmt.Errorf("-output %q is not valid option", getFmt) + return "", fmt.Errorf("-o %q is not valid option", listFmt) } } diff --git a/cmd/db/list_test.go b/cmd/db/list_test.go index 42b6f88..d85852f 100644 --- a/cmd/db/list_test.go +++ b/cmd/db/list_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -26,16 +26,15 @@ import ( ) func TestList(t *testing.T) { - listFmt = "json" + listFmt = pkg.JSONFormat dbs := []astraops.Database{ {ID: "1"}, {ID: "2"}, } - jsonTxt, err := executeList([]string{"", "", "", "10"}, func() (pkg.Client, error) { + jsonTxt, err := executeList(func() (pkg.Client, error) { return &tests.MockClient{ Databases: dbs, }, nil - }) if err != nil { t.Fatalf("unexpected error %v", err) @@ -57,7 +56,7 @@ func TestList(t *testing.T) { } func TestListText(t *testing.T) { - listFmt = "text" + listFmt = pkg.TextFormat dbs := []astraops.Database{ { ID: "1", @@ -74,11 +73,10 @@ func TestListText(t *testing.T) { Status: astraops.TERMINATING, }, } - txt, err := executeList([]string{"", "", "", "10"}, func() (pkg.Client, error) { + txt, err := executeList(func() (pkg.Client, error) { return &tests.MockClient{ Databases: dbs, }, nil - }) if err != nil { t.Fatalf("unexpected error %v", err) @@ -93,3 +91,17 @@ func TestListText(t *testing.T) { t.Errorf("expected '%v' but was '%v'", expected, txt) } } + +func TestListInvalidFmt(t *testing.T) { + listFmt = "listham" + _, err := executeList(func() (pkg.Client, error) { + return &tests.MockClient{}, nil + }) + if err == nil { + t.Fatalf("unexpected error %v", err) + } + expected := "-o \"listham\" is not valid option" + if err.Error() != expected { + t.Errorf("expected '%v' but was '%v'", expected, err.Error()) + } +} diff --git a/cmd/db/park.go b/cmd/db/park.go index 4fc0f45..5baceda 100644 --- a/cmd/db/park.go +++ b/cmd/db/park.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" ) -//ParkCmd provides parking support for classic database tiers in Astra +// ParkCmd provides parking support for classic database tiers in Astra var ParkCmd = &cobra.Command{ Use: "park ", Short: "parks the database specified, does not work with serverless", @@ -31,27 +31,26 @@ var ParkCmd = &cobra.Command{ Args: cobra.ExactArgs(1), Run: func(cobraCmd *cobra.Command, args []string) { creds := &pkg.Creds{} - client, err := creds.Login() - if err != nil { - fmt.Fprintf(os.Stderr, "unable to login with error %v\n", err) - os.Exit(1) - } - err = executePark(args, client) + msg, err := executePark(args, creds.Login) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } + fmt.Println(msg) }, } // executePark parks the database with the specified ID. If no ID is provided // the command will error out -func executePark(args []string, client pkg.Client) error { +func executePark(args []string, makeClient func() (pkg.Client, error)) (string, error) { + client, err := makeClient() + if err != nil { + return "", fmt.Errorf("unable to login with error %v", err) + } id := args[0] fmt.Printf("starting to park database %v\n", id) if err := client.Park(id); err != nil { - return fmt.Errorf("unable to park '%s' with error %v", id, err) + return "", fmt.Errorf("unable to park '%s' with error %v", id, err) } - fmt.Printf("database %v parked\n", id) - return nil + return fmt.Sprintf("database %v parked", id), nil } diff --git a/cmd/db/park_test.go b/cmd/db/park_test.go index a0d2b87..a27f360 100644 --- a/cmd/db/park_test.go +++ b/cmd/db/park_test.go @@ -12,20 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( "testing" + "github.com/rsds143/astra-cli/pkg" tests "github.com/rsds143/astra-cli/pkg/tests" ) func TestPark(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{} - id := "qdfkjoj" - err := executePark([]string{id}, mockClient) + id := "abcd" + msg, err := executePark([]string{id}, func() (pkg.Client, error) { + return mockClient, nil + }) if err != nil { t.Fatalf("unexpected error '%v'", err) } @@ -36,4 +39,8 @@ func TestPark(t *testing.T) { if id != mockClient.Call(0) { t.Errorf("expected '%v' but was '%v'", id, mockClient.Call(0)) } + expected := "database abcd parked" + if msg != expected { + t.Errorf("expected '%v' but was '%v'", expected, msg) + } } diff --git a/cmd/db/resize.go b/cmd/db/resize.go index 69e9e62..5387ef4 100644 --- a/cmd/db/resize.go +++ b/cmd/db/resize.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -24,12 +24,14 @@ import ( "github.com/spf13/cobra" ) -//ResizeCmd provides the resize database command +const noRequiredArgs = 2 + +// ResizeCmd provides the resize database command var ResizeCmd = &cobra.Command{ Use: "resize ", Short: "Resizes a database by id with the specified capacity unit", Long: "Resizes a database by id with the specified capacity unit. Note does not work on serverless.", - Args: cobra.ExactArgs(2), + Args: cobra.ExactArgs(noRequiredArgs), Run: func(cobraCmd *cobra.Command, args []string) { creds := &pkg.Creds{} client, err := creds.Login() @@ -45,12 +47,12 @@ var ResizeCmd = &cobra.Command{ }, } -//executeResize resizes the database with the specified ID with the specified size. If no ID is provided +// executeResize resizes the database with the specified ID with the specified size. If no ID is provided // the command will error out func executeResize(args []string, client pkg.Client) error { id := args[0] capacityUnitRaw := args[1] - capacityUnit, err := strconv.Atoi(capacityUnitRaw) + capacityUnit, err := strconv.ParseInt(capacityUnitRaw, 10, 32) if err != nil { return &pkg.ParseError{ Args: args, @@ -58,7 +60,7 @@ func executeResize(args []string, client pkg.Client) error { } } if err := client.Resize(id, int32(capacityUnit)); err != nil { - return fmt.Errorf("unable to unpark '%s' with error %v", id, err) + return fmt.Errorf("unable to resize '%s' with error %v", id, err) } fmt.Printf("resize database %v submitted with size %v\n", id, capacityUnit) return nil diff --git a/cmd/db/resize_test.go b/cmd/db/resize_test.go index b1718f2..1296fce 100644 --- a/cmd/db/resize_test.go +++ b/cmd/db/resize_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -22,9 +22,9 @@ import ( ) func TestResize(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{} - id := "qdfkjoj" + id := "resizeId1" size := "100" err := executeResize([]string{id, size}, mockClient) if err != nil { @@ -45,15 +45,15 @@ func TestResize(t *testing.T) { } func TestResizeParseError(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{} - id := "qdfkjoj" - size := "abcd" + id := "resizeparseId" + size := "poppaoute" err := executeResize([]string{id, size}, mockClient) if err == nil { t.Fatal("expected error") } - expectedError := "Unable to parse command line with args: qdfkjoj, abcd. Nested error was 'unable to parse capacity unit 'abcd' with error strconv.Atoi: parsing \"abcd\": invalid syntax'" + expectedError := "Unable to parse command line with args: resizeparseId, poppaoute. Nested error was 'unable to parse capacity unit 'poppaoute' with error strconv.ParseInt: parsing \"poppaoute\": invalid syntax'" if err.Error() != expectedError { t.Errorf("expected '%v' but was '%v'", expectedError, err.Error()) } diff --git a/cmd/db/secBundle.go b/cmd/db/secBundle.go index 6d5fe2d..5b4142e 100644 --- a/cmd/db/secBundle.go +++ b/cmd/db/secBundle.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db provides the sub-commands for the db command +// Package db provides the sub-commands for the db command package db import ( @@ -34,7 +34,7 @@ func init() { SecBundleCmd.Flags().StringVarP(&secBundleLoc, "location", "l", "secureBundle.zip", "location of bundle to download to if using zip format. ignore if using json") } -//SecBundleCmd provides the secBundle database command +// SecBundleCmd provides the secBundle database command var SecBundleCmd = &cobra.Command{ Use: "secBundle ", Short: "get secure bundle by databaseID", @@ -68,13 +68,13 @@ func executeSecBundle(args []string, login func() (pkg.Client, error)) (string, return "", fmt.Errorf("error outputing zip format '%v'", err) } return fmt.Sprintf("file %v saved %v bytes written", secBundleLoc, bytesWritten), nil - case "json": + case pkg.JSONFormat: b, err := json.MarshalIndent(secBundle, "", " ") if err != nil { return "", fmt.Errorf("unexpected error marshaling to json: '%v', Try -output text instead", err) } return string(b), nil default: - return "", fmt.Errorf("-output %q is not valid option", secBundleFmt) + return "", fmt.Errorf("-o %q is not valid option", secBundleFmt) } } diff --git a/cmd/db/secBundle_test.go b/cmd/db/secBundle_test.go index 631953b..fb1fbfb 100644 --- a/cmd/db/secBundle_test.go +++ b/cmd/db/secBundle_test.go @@ -12,11 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path" "testing" "github.com/rsds143/astra-cli/pkg" @@ -25,7 +30,7 @@ import ( ) func TestSecBundle(t *testing.T) { - id := "abc" + id := "secId123" secBundleLoc = "my_loc" secBundleFmt = "json" bundle := astraops.SecureBundle{ @@ -51,3 +56,62 @@ func TestSecBundle(t *testing.T) { t.Errorf("expected '%v' but was '%v'", bundle, fromServer) } } + +func TestSecBundleZip(t *testing.T) { + zipContent := "zip file content" + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, zipContent) + })) + defer ts.Close() + tmpDir := t.TempDir() + zipFile := path.Join(tmpDir, "bundle.zip") + defer func() { + if err := os.Remove(zipFile); err != nil { + t.Logf("unable to remove '%v' in test due to error '%v'", zipFile, err) + } + }() + id := "abc" + secBundleLoc = zipFile + secBundleFmt = "zip" + bundle := astraops.SecureBundle{ + DownloadURL: ts.URL, + DownloadURLInternal: "wyz", + DownloadURLMigrationProxy: "opu", + DownloadURLMigrationProxyInternal: "zert", + } + msg, err := executeSecBundle([]string{id}, func() (pkg.Client, error) { + return &tests.MockClient{ + Bundle: bundle, + }, nil + }) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + expected := fmt.Sprintf("file %v saved 17 bytes written", zipFile) + if msg != expected { + t.Errorf("expected '%v' but was '%v'", expected, msg) + } +} + +func TestSecBundleInvalidFmt(t *testing.T) { + id := "abc" + secBundleFmt = "ham" + bundle := astraops.SecureBundle{ + DownloadURL: "url", + DownloadURLInternal: "wyz", + DownloadURLMigrationProxy: "opu", + DownloadURLMigrationProxyInternal: "zert", + } + _, err := executeSecBundle([]string{id}, func() (pkg.Client, error) { + return &tests.MockClient{ + Bundle: bundle, + }, nil + }) + if err == nil { + t.Fatalf("unexpected error %v", err) + } + expected := "-o \"ham\" is not valid option" + if err.Error() != expected { + t.Errorf("expected '%v' but was '%v'", expected, err.Error()) + } +} diff --git a/cmd/db/tiers.go b/cmd/db/tiers.go index 6bd7591..2343089 100644 --- a/cmd/db/tiers.go +++ b/cmd/db/tiers.go @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db provides the sub-commands for the db command +// Package db provides the sub-commands for the db command package db import ( + "bytes" "encoding/json" "fmt" "os" @@ -31,62 +32,73 @@ func init() { TiersCmd.Flags().StringVarP(&tiersFmt, "output", "o", "text", "Output format for report default is json") } -//TiersCmd is the command to list availability data in Astra +// TiersCmd is the command to list availability data in Astra var TiersCmd = &cobra.Command{ Use: "tiers", Short: "List all available tiers on the Astra DevOps API", Long: `List all available tiers on the Astra DevOps API. Each tier is a combination of costs, size, region, and name`, Run: func(cmd *cobra.Command, args []string) { - var tiers []astraops.TierInfo creds := &pkg.Creds{} - client, err := creds.Login() + msg, err := executeTiers(creds.Login) if err != nil { - fmt.Fprintf(os.Stderr, "unable to login with error %v\n", err) + fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } - if tiers, err = client.GetTierInfo(); err != nil { - fmt.Fprintf(os.Stderr, "unable to get tiers with error %v\n", err) - os.Exit(1) - } - switch tiersFmt { - case "text": - var rows [][]string - rows = append(rows, []string{"name", "cloud", "region", "db (used)/(limit)", "cap (used)/(limit)", "cost per month", "cost per minute"}) - for _, tier := range tiers { - costMonthRaw := tier.Cost.CostPerMonthCents - var costMonth float64 - if costMonthRaw > 0 { - costMonth = costMonthRaw / 100.0 - } - costMinRaw := tier.Cost.CostPerMinCents - var costMin float64 - if costMinRaw > 0 { - costMin = costMinRaw / 100.0 - } - rows = append(rows, []string{ - tier.Tier, - tier.CloudProvider, - tier.Region, - fmt.Sprintf("%v/%v", tier.DatabaseCountUsed, tier.DatabaseCountLimit), - fmt.Sprintf("%v/%v", tier.CapacityUnitsUsed, tier.CapacityUnitsLimit), - fmt.Sprintf("$%.2f", costMonth), - fmt.Sprintf("$%.2f", costMin)}) + fmt.Println(msg) + }, +} + +func executeTiers(login func() (pkg.Client, error)) (string, error) { + var tiers []astraops.TierInfo + client, err := login() + if err != nil { + return "", fmt.Errorf("unable to login with error %v", err) + } + if tiers, err = client.GetTierInfo(); err != nil { + return "", fmt.Errorf("unable to get tiers with error %v", err) + } + switch tiersFmt { + case pkg.TextFormat: + var rows [][]string + rows = append(rows, []string{"name", "cloud", "region", "db (used)/(limit)", "cap (used)/(limit)", "cost per month", "cost per minute"}) + for _, tier := range tiers { + var costMonthRaw float64 + var costMinRaw float64 + if tier.Cost != nil { + costMonthRaw = tier.Cost.CostPerMonthCents + costMinRaw = tier.Cost.CostPerMinCents } - err = pkg.WriteRows(os.Stdout, rows) - if err != nil { - fmt.Fprintf(os.Stderr, "unexpected error writing text output %v", err) - os.Exit(1) + divisor := 100.0 + var costMonth float64 + if costMonthRaw > 0.0 { + costMonth = costMonthRaw / divisor } - case "json": - b, err := json.MarshalIndent(tiers, "", " ") - if err != nil { - fmt.Fprintf(os.Stderr, "unexpected error marshaling to json: '%v', Try -format text instead\n", err) - os.Exit(1) + var costMin float64 + if costMinRaw > 0.0 { + costMin = costMinRaw / divisor } - fmt.Println(string(b)) - default: - fmt.Fprintf(os.Stderr, "-o %q is not valid option.\n", tiersFmt) - os.Exit(1) + rows = append(rows, []string{ + tier.Tier, + tier.CloudProvider, + tier.Region, + fmt.Sprintf("%v/%v", tier.DatabaseCountUsed, tier.DatabaseCountLimit), + fmt.Sprintf("%v/%v", tier.CapacityUnitsUsed, tier.CapacityUnitsLimit), + fmt.Sprintf("$%.2f", costMonth), + fmt.Sprintf("$%.2f", costMin)}) } - }, + var buf bytes.Buffer + err = pkg.WriteRows(&buf, rows) + if err != nil { + return "", fmt.Errorf("unexpected error writing text output %v", err) + } + return buf.String(), nil + case pkg.JSONFormat: + b, err := json.MarshalIndent(tiers, "", " ") + if err != nil { + return "", fmt.Errorf("unexpected error marshaling to json: '%v', Try -format text instead", err) + } + return string(b), nil + default: + return "", fmt.Errorf("-o %q is not valid option", tiersFmt) + } } diff --git a/cmd/db/tiers_test.go b/cmd/db/tiers_test.go index 3e69149..dd32e2b 100644 --- a/cmd/db/tiers_test.go +++ b/cmd/db/tiers_test.go @@ -12,11 +12,149 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db -import "testing" +import ( + "encoding/json" + "reflect" + "strings" + "testing" + + "github.com/rsds143/astra-cli/pkg" + tests "github.com/rsds143/astra-cli/pkg/tests" + "github.com/rsds143/astra-devops-sdk-go/astraops" +) func TestTiers(t *testing.T) { - t.Skip("ignore") + tiersFmt = "json" + tier1 := astraops.TierInfo{ + Tier: "abd", + } + tier2 := astraops.TierInfo{ + Tier: "xyz", + } + jsonTxt, err := executeTiers(func() (pkg.Client, error) { + return &tests.MockClient{ + Tiers: []astraops.TierInfo{ + tier1, + tier2, + }, + }, nil + }) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + var fromServer []astraops.TierInfo + err = json.Unmarshal([]byte(jsonTxt), &fromServer) + if err != nil { + t.Fatalf("unexpected error with json %v", err) + } + expected := []astraops.TierInfo{ + tier1, + tier2, + } + if !reflect.DeepEqual(fromServer, expected) { + t.Errorf("expected '%v' but was '%v'", expected, fromServer) + } +} + +func TestTiersText(t *testing.T) { + tiersFmt = "text" + tier1 := astraops.TierInfo{ + Tier: "tier1", + CloudProvider: "cloud1", + Region: "region1", + DatabaseCountUsed: 1, + DatabaseCountLimit: 1, + Cost: &astraops.Costs{ + CostPerMonthCents: 10, + CostPerMinCents: 1, + }, + CapacityUnitsUsed: 1, + CapacityUnitsLimit: 1, + } + tier2 := astraops.TierInfo{ + Tier: "tier2", + CloudProvider: "cloud2", + Region: "region2", + Cost: &astraops.Costs{ + CostPerMonthCents: 20, + CostPerMinCents: 2, + }, + CapacityUnitsUsed: 2, + CapacityUnitsLimit: 2, + } + msg, err := executeTiers(func() (pkg.Client, error) { + return &tests.MockClient{ + Tiers: []astraops.TierInfo{ + tier1, + tier2, + }, + }, nil + }) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + expected := strings.Join([]string{ + "name cloud region db (used)/(limit) cap (used)/(limit) cost per month cost per minute", + "tier1 cloud1 region1 1/1 1/1 $0.10 $0.01", + "tier2 cloud2 region2 0/0 2/2 $0.20 $0.02", + }, "\n") + if msg != expected { + t.Errorf("expected '%v' but was '%v'", expected, msg) + } +} + +func TestTiersTextWithNoCost(t *testing.T) { + tiersFmt = "text" + tier1 := astraops.TierInfo{ + Tier: "tier1", + CloudProvider: "cloud1", + Region: "region1", + DatabaseCountUsed: 1, + DatabaseCountLimit: 1, + CapacityUnitsUsed: 1, + CapacityUnitsLimit: 1, + } + tier2 := astraops.TierInfo{ + Tier: "tier2", + CloudProvider: "cloud2", + Region: "region2", + CapacityUnitsUsed: 2, + CapacityUnitsLimit: 2, + } + msg, err := executeTiers(func() (pkg.Client, error) { + return &tests.MockClient{ + Tiers: []astraops.TierInfo{ + tier1, + tier2, + }, + }, nil + }) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + expected := strings.Join([]string{ + "name cloud region db (used)/(limit) cap (used)/(limit) cost per month cost per minute", + "tier1 cloud1 region1 1/1 1/1 $0.00 $0.00", + "tier2 cloud2 region2 0/0 2/2 $0.00 $0.00", + }, "\n") + if msg != expected { + t.Errorf("expected '%v' but was '%v'", expected, msg) + } +} + +func TestTiersnvalidFmt(t *testing.T) { + tiersFmt = "ham" + _, err := executeTiers(func() (pkg.Client, error) { + return &tests.MockClient{}, nil + }) + if err == nil { + t.Fatalf("expected error") + } + expected := "-o \"ham\" is not valid option" + if err.Error() != expected { + t.Errorf("expected '%v' but was '%v'", expected, err.Error()) + } } diff --git a/cmd/db/unpark.go b/cmd/db/unpark.go index 83c2a15..cd090a9 100644 --- a/cmd/db/unpark.go +++ b/cmd/db/unpark.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" ) -//UnparkCmd provides unparking support for classic database tiers in Astra +// UnparkCmd provides unparking support for classic database tiers in Astra var UnparkCmd = &cobra.Command{ Use: "unpark ", Short: "parks the database specified, does not work with serverless", diff --git a/cmd/db/unpark_test.go b/cmd/db/unpark_test.go index 99bb45f..123adee 100644 --- a/cmd/db/unpark_test.go +++ b/cmd/db/unpark_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package db is where the Astra DB commands are +// Package db is where the Astra DB commands are package db import ( @@ -22,9 +22,9 @@ import ( ) func TestUnpark(t *testing.T) { - //setting package variables by hand, there be dragons + // setting package variables by hand, there be dragons mockClient := &tests.MockClient{} - id := "qdfkjoj" + id := "unparkID123" err := executeUnpark([]string{id}, mockClient) if err != nil { t.Fatalf("unexpected error '%v'", err) diff --git a/cmd/db_test.go b/cmd/db_test.go index 491da6e..9ec4dfc 100644 --- a/cmd/db_test.go +++ b/cmd/db_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd contains all fo the commands for the cli +// Package cmd contains all fo the commands for the cli package cmd import ( diff --git a/cmd/login.go b/cmd/login.go index b24e509..0b6bfdd 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd is the entry point for all of the commands +// Package cmd is the entry point for all of the commands package cmd import ( @@ -40,6 +40,12 @@ func init() { loginCmd.Flags().StringVarP(&clientID, "id", "i", "", "clientId from service account. Ignored if -json flag is used.") } +const ( + WriteError = 2 + CannotFindHome = 3 + JSONError = 4 +) + var loginCmd = &cobra.Command{ Use: "login", Short: "Stores credentials for the cli to use in other commands to operate on the Astra DevOps API", @@ -48,12 +54,12 @@ var loginCmd = &cobra.Command{ confDir, confFiles, err := pkg.GetHome(os.UserHomeDir) if err != nil { fmt.Printf("%v\n", err) - os.Exit(3) + os.Exit(CannotFindHome) } if authToken != "" { if err := makeConf(confDir, confFiles.TokenPath, authToken); err != nil { fmt.Printf("%v\n", err) - os.Exit(1) + os.Exit(WriteError) } return } else if clientJSON != "" { @@ -61,39 +67,39 @@ var loginCmd = &cobra.Command{ err := json.Unmarshal([]byte(clientJSON), &clientInfo) if err != nil { fmt.Fprintln(os.Stderr, fmt.Errorf("unable to serialize the json into a valid login due to error %s", err)) - os.Exit(1) + os.Exit(JSONError) } if len(clientInfo.ClientName) == 0 { fmt.Fprintln(os.Stderr, pkg.ParseError{ Args: args, Err: fmt.Errorf("clientName missing"), }) - os.Exit(1) + os.Exit(JSONError) } if len(clientInfo.ClientID) == 0 { fmt.Fprintln(os.Stderr, pkg.ParseError{ Args: args, Err: fmt.Errorf("clientId missing"), }) - os.Exit(1) + os.Exit(JSONError) } if len(clientInfo.ClientSecret) == 0 { fmt.Fprintln(os.Stderr, pkg.ParseError{ Args: args, Err: fmt.Errorf("clientSecret missing"), }) - os.Exit(1) + os.Exit(JSONError) } if err := makeConf(confDir, confFiles.SaPath, clientJSON); err != nil { fmt.Printf("%v\n", err) - os.Exit(1) + os.Exit(WriteError) } return } else { clientJSON = fmt.Sprintf("{\"clientId\":\"%v\",\"clientName\":\"%v\",\"clientSecret\":\"%v:\"}", clientID, clientName, clientSecret) if err := makeConf(confDir, confFiles.SaPath, clientJSON); err != nil { fmt.Printf("%v\n", err) - os.Exit(1) + os.Exit(JSONError) } return } @@ -114,7 +120,7 @@ func makeConf(confDir, confFile, content string) error { } }() writer := bufio.NewWriter(f) - //safe to write after validation + // safe to write after validation _, err = writer.Write([]byte(content)) if err != nil { return fmt.Errorf("error writing file") diff --git a/cmd/login_test.go b/cmd/login_test.go index 9f4f746..efaf5f5 100644 --- a/cmd/login_test.go +++ b/cmd/login_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd contains all fo the commands for the cli +// Package cmd contains all fo the commands for the cli package cmd import "testing" diff --git a/cmd/root.go b/cmd/root.go index 15d1f65..bb06aea 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd contains all fo the commands for the cli +// Package cmd contains all fo the commands for the cli package cmd import ( @@ -29,7 +29,7 @@ func init() { RootCmd.AddCommand(dbCmd) } -//RootCmd is the entry point for the whole app +// RootCmd is the entry point for the whole app var RootCmd = &cobra.Command{ Use: "astra-cli", Short: "An easy to use client for automating DataStax Astra", diff --git a/cmd/root_test.go b/cmd/root_test.go index 1687271..93e7c2f 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cmd contains all fo the commands for the cli +// Package cmd contains all fo the commands for the cli package cmd import ( diff --git a/go.mod b/go.mod index da4c6fe..efef9bb 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/rsds143/astra-cli go 1.16 require ( - github.com/rsds143/astra-devops-sdk-go v0.3.0 + github.com/rsds143/astra-devops-sdk-go v0.3.1 github.com/spf13/cobra v1.1.3 ) diff --git a/go.sum b/go.sum index 802215f..1a49666 100644 --- a/go.sum +++ b/go.sum @@ -24,7 +24,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -137,8 +136,8 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rsds143/astra-devops-sdk-go v0.3.0 h1:ymkYLcf5AfM1zYbyEmiETHzR34HcItp4n9b4GKGVj+Q= -github.com/rsds143/astra-devops-sdk-go v0.3.0/go.mod h1:LQaUwm75Ydy/z71nl466Xv0yw8ib5b9L6laTFXbvtHU= +github.com/rsds143/astra-devops-sdk-go v0.3.1 h1:Bx/EAWwlfAakX8/APEez7CXl7nfm7oGiVShHecnHacs= +github.com/rsds143/astra-devops-sdk-go v0.3.1/go.mod h1:LQaUwm75Ydy/z71nl466Xv0yw8ib5b9L6laTFXbvtHU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= diff --git a/pkg/conf.go b/pkg/conf.go index b0fb17b..ed721ae 100644 --- a/pkg/conf.go +++ b/pkg/conf.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( @@ -26,13 +26,13 @@ import ( "github.com/rsds143/astra-devops-sdk-go/astraops" ) -//ConfFiles supports both formats of credentials and will say if the token one is present +// ConfFiles supports both formats of credentials and will say if the token one is present type ConfFiles struct { TokenPath string SaPath string } -//HasServiceAccount returns true if there is a service account file present and accessible +// HasServiceAccount returns true if there is a service account file present and accessible func (c ConfFiles) HasServiceAccount() (bool, error) { if _, err := os.Stat(c.SaPath); err != nil { if os.IsNotExist(err) { @@ -43,7 +43,7 @@ func (c ConfFiles) HasServiceAccount() (bool, error) { return true, nil } -//HasToken returns true if there is a token file present and accessible +// HasToken returns true if there is a token file present and accessible func (c ConfFiles) HasToken() (bool, error) { if _, err := os.Stat(c.TokenPath); err != nil { if os.IsNotExist(err) { diff --git a/pkg/conf_test.go b/pkg/conf_test.go index 26326a7..915a1e5 100644 --- a/pkg/conf_test.go +++ b/pkg/conf_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( @@ -33,9 +33,9 @@ func TestReadLogin(t *testing.T) { if c.ClientID != id { t.Errorf("expected %v but was %v", id, c.ClientID) } - secret := "6ae15bff-1435-430f-975b-9b3d9914b698" - if c.ClientSecret != secret { - t.Errorf("expected %v but was %v", secret, c.ClientSecret) + testClientSec := "6ae15bff-1435-430f-975b-9b3d9914b698" + if c.ClientSecret != testClientSec { + t.Errorf("expected %v but was %v", testClientSec, c.ClientSecret) } } diff --git a/pkg/const.go b/pkg/const.go new file mode 100644 index 0000000..0aa546c --- /dev/null +++ b/pkg/const.go @@ -0,0 +1,23 @@ +// Copyright 2021 Ryan Svihla +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package pkg is the top level package for shared libraries +package pkg + +const ( + // JSONFormat is for the command line flag -o + JSONFormat = "json" + // TextFormat is for the command line flag -o + TextFormat = "text" +) diff --git a/pkg/env/env.go b/pkg/env/env.go index 4715b7d..e979166 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package env is the package where global environment configuration goes +// Package env is the package where global environment configuration goes package env -//Verbose sets the verbose mode for the command +// Verbose sets the verbose mode for the command var Verbose bool diff --git a/pkg/errors.go b/pkg/errors.go index af608cf..40d2355 100644 --- a/pkg/errors.go +++ b/pkg/errors.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( @@ -20,13 +20,13 @@ import ( "strings" ) -//ParseError is used to indicate there is an error in the command line args +// ParseError is used to indicate there is an error in the command line args type ParseError struct { Args []string Err error } -//Error outpus the error with the args provided, if there are no args that becomes the error +// Error outpus the error with the args provided, if there are no args that becomes the error func (p *ParseError) Error() string { if len(p.Args) == 0 { return "no args provided" @@ -34,24 +34,24 @@ func (p *ParseError) Error() string { return fmt.Sprintf("Unable to parse command line with args: %v. Nested error was '%v'", strings.Join(p.Args, ", "), p.Err) } -//JSONParseError when unable to read JSON +// JSONParseError when unable to read JSON type JSONParseError struct { Original string Err error } -//Error returns the error string +// Error returns the error string func (j *JSONParseError) Error() string { return fmt.Sprintf("JSON parsing error for json '%v' with error '%v'", j.Original, j.Err) } -//FileNotFoundError when unable to read file +// FileNotFoundError when unable to read file type FileNotFoundError struct { Path string Err error } -//Error returns the error string +// Error returns the error string func (j *FileNotFoundError) Error() string { return fmt.Sprintf("Unable to find file '%v' with error: '%s'", j.Path, j.Err) } diff --git a/pkg/errors_test.go b/pkg/errors_test.go index 64abfb8..04e22c4 100644 --- a/pkg/errors_test.go +++ b/pkg/errors_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( diff --git a/pkg/httputils/client.go b/pkg/httputils/client.go index fb5e195..fabad40 100644 --- a/pkg/httputils/client.go +++ b/pkg/httputils/client.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package httputils provides common http functions and utilities +// Package httputils provides common http functions and utilities package httputils import ( @@ -24,26 +24,31 @@ import ( "time" ) -//NewHTTPClient fires up client with 'better' defaults +const connections = 10 +const standardTimeOut = 5 * time.Second +const dialTimeout = 10 * time.Second +const expectContinueResponse = 1 * time.Second + +// NewHTTPClient fires up client with 'better' defaults func NewHTTPClient() *http.Client { return &http.Client{ - Timeout: 5 * time.Second, + Timeout: standardTimeOut, Transport: &http.Transport{ - MaxIdleConns: 10, - MaxConnsPerHost: 10, - MaxIdleConnsPerHost: 10, + MaxIdleConns: connections, + MaxConnsPerHost: connections, + MaxIdleConnsPerHost: connections, Dial: (&net.Dialer{ - Timeout: 10 * time.Second, - KeepAlive: 10 * time.Second, + Timeout: dialTimeout, + KeepAlive: dialTimeout, }).Dial, - TLSHandshakeTimeout: 5 * time.Second, - ResponseHeaderTimeout: 5 * time.Second, - ExpectContinueTimeout: 1 * time.Second, + TLSHandshakeTimeout: standardTimeOut, + ResponseHeaderTimeout: standardTimeOut, + ExpectContinueTimeout: expectContinueResponse, }, } } -//DownloadZip pulls down the URL listed and saves it to the specified location +// DownloadZip pulls down the URL listed and saves it to the specified location func DownloadZip(downloadURL string, secBundleLoc string) (int64, error) { httpClient := NewHTTPClient() res, err := httpClient.Get(downloadURL) diff --git a/pkg/httputils/client_test.go b/pkg/httputils/client_test.go index feed46f..49c814a 100644 --- a/pkg/httputils/client_test.go +++ b/pkg/httputils/client_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package httputils provides common http functions and utilities +// Package httputils provides common http functions and utilities package httputils import ( diff --git a/pkg/login.go b/pkg/login.go index b134594..ec38683 100644 --- a/pkg/login.go +++ b/pkg/login.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( @@ -23,12 +23,12 @@ import ( "github.com/rsds143/astra-devops-sdk-go/astraops" ) -//LoginService provides interface to implement logins and produce an Client +// LoginService provides interface to implement logins and produce an Client type LoginService interface { Login() (Client, error) } -//Client is the abstraction for client interactions. Allows alternative db management clients +// Client is the abstraction for client interactions. Allows alternative db management clients type Client interface { CreateDb(astraops.CreateDb) (astraops.Database, error) Terminate(string, bool) error @@ -41,12 +41,12 @@ type Client interface { GetTierInfo() ([]astraops.TierInfo, error) } -//Creds knows how handle and store credentials +// Creds knows how handle and store credentials type Creds struct { - GetHomeFunc func() (string, error) //optional. If not specified os.UserHomeDir is used for log base directory to find creds + GetHomeFunc func() (string, error) // optional. If not specified os.UserHomeDir is used for log base directory to find creds } -//Login logs into the Astra DevOps API using the local configuration provided by the 'astra-cli login' command +// Login logs into the Astra DevOps API using the local configuration provided by the 'astra-cli login' command func (c *Creds) Login() (Client, error) { getHome := c.GetHomeFunc if getHome == nil { @@ -84,5 +84,4 @@ func (c *Creds) Login() (Client, error) { return &astraops.AuthenticatedClient{}, fmt.Errorf("authenticate failed with error %v", err) } return client, nil - } diff --git a/pkg/login_test.go b/pkg/login_test.go index e1b1d10..c1fedd7 100644 --- a/pkg/login_test.go +++ b/pkg/login_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( diff --git a/pkg/strfmt.go b/pkg/strfmt.go index 96d1d97..c2906ec 100644 --- a/pkg/strfmt.go +++ b/pkg/strfmt.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( @@ -22,7 +22,7 @@ import ( "text/tabwriter" ) -//WriteRows outputs a flexiable right aligned tabwriter +// WriteRows outputs a flexiable right aligned tabwriter func WriteRows(w io.Writer, rows [][]string) error { tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) for i, row := range rows { diff --git a/pkg/strfmt_test.go b/pkg/strfmt_test.go index e10958b..57beff0 100644 --- a/pkg/strfmt_test.go +++ b/pkg/strfmt_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package pkg is the top level package for shared libraries +// Package pkg is the top level package for shared libraries package pkg import ( diff --git a/pkg/tests/client.go b/pkg/tests/client.go index 0d592e7..60ac134 100644 --- a/pkg/tests/client.go +++ b/pkg/tests/client.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package test is for test utilies and mocks +// Package test is for test utilies and mocks package test import "github.com/rsds143/astra-devops-sdk-go/astraops" -//MockClient is used for testing +// MockClient is used for testing type MockClient struct { ErrorQueue []error calls []interface{} @@ -26,7 +26,7 @@ type MockClient struct { Bundle astraops.SecureBundle } -//getError pops the next error stored off the stack +// getError pops the next error stored off the stack func (c *MockClient) getError() error { var err error if len(c.ErrorQueue) > 0 { @@ -37,7 +37,7 @@ func (c *MockClient) getError() error { return err } -//getError pops the next db object stored off the stack +// getError pops the next db object stored off the stack func (c *MockClient) getDb() astraops.Database { var db astraops.Database if len(c.Databases) > 0 { @@ -47,37 +47,36 @@ func (c *MockClient) getDb() astraops.Database { return db } -//Call returns a call at the specified index +// Call returns a call at the specified index func (c *MockClient) Call(index int) interface{} { return c.calls[index] } -//Calls returns all calls made in order +// Calls returns all calls made in order func (c *MockClient) Calls() []interface{} { return c.calls } -//CreateDb returns the next error and the next db created +// CreateDb returns the next error and the next db created func (c *MockClient) CreateDb(db astraops.CreateDb) (astraops.Database, error) { c.calls = append(c.calls, db) return c.getDb(), c.getError() } -//Terminate returns the next error and stores the id used, internal is ignored +// Terminate returns the next error and stores the id used, internal is ignored func (c *MockClient) Terminate(id string, internal bool) error { c.calls = append(c.calls, id) return c.getError() } -//FindDb returns the next database and next error, the id call is stored +// FindDb returns the next database and next error, the id call is stored func (c *MockClient) FindDb(id string) (astraops.Database, error) { c.calls = append(c.calls, id) return c.getDb(), c.getError() } -//ListDb returns all databases and stores the arguments as an interface array +// ListDb returns all databases and stores the arguments as an interface array func (c *MockClient) ListDb(include string, provider string, startingAfter string, limit int32) ([]astraops.Database, error) { - c.calls = append(c.calls, []interface{}{ include, provider, @@ -87,31 +86,31 @@ func (c *MockClient) ListDb(include string, provider string, startingAfter strin return c.Databases, c.getError() } -//Unpark returns the next error, the id call is stored +// Unpark returns the next error, the id call is stored func (c *MockClient) Unpark(id string) error { c.calls = append(c.calls, id) return c.getError() } -//Park returns the next error, the id call is stored +// Park returns the next error, the id call is stored func (c *MockClient) Park(id string) error { c.calls = append(c.calls, id) return c.getError() } -//Resize returns the next error, the id call and size is stored +// Resize returns the next error, the id call and size is stored func (c *MockClient) Resize(id string, size int32) error { c.calls = append(c.calls, []interface{}{id, size}) return c.getError() } -//GetSecureBundle returns the next error, the secured bundle stored, and the id call is stored +// GetSecureBundle returns the next error, the secured bundle stored, and the id call is stored func (c *MockClient) GetSecureBundle(id string) (astraops.SecureBundle, error) { c.calls = append(c.calls, id) return c.Bundle, c.getError() } -//GetTierInfo returns the next error, and the tierinfo objects stored +// GetTierInfo returns the next error, and the tierinfo objects stored func (c *MockClient) GetTierInfo() ([]astraops.TierInfo, error) { return c.Tiers, c.getError() } diff --git a/pkg/tests/client_test.go b/pkg/tests/client_test.go index 0c80ff6..25404aa 100644 --- a/pkg/tests/client_test.go +++ b/pkg/tests/client_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package test is for test utilies and mocks +// Package test is for test utilies and mocks package test import ( @@ -76,7 +76,7 @@ func TestGetDB(t *testing.T) { func TestPark(t *testing.T) { client := &MockClient{} - id := "DSQ" + id := "123" err := client.Park(id) if err != nil { t.Fatal("unexpected error") @@ -91,7 +91,7 @@ func TestPark(t *testing.T) { func TestUnpark(t *testing.T) { client := &MockClient{} - id := "DSQ" + id := "parkid" err := client.Unpark(id) if err != nil { t.Fatal("unexpected error") @@ -106,7 +106,7 @@ func TestUnpark(t *testing.T) { func TestTerminate(t *testing.T) { client := &MockClient{} - id := "DSQ" + id := "termid" err := client.Terminate(id, false) if err != nil { t.Fatal("unexpected error") @@ -126,7 +126,7 @@ func TestGetSecurteBundleId(t *testing.T) { DownloadURL: url, }, } - id := "DSQ" + id := "secid" bundle, err := client.GetSecureBundle(id) if err != nil { t.Fatal("unexpected error") @@ -194,9 +194,9 @@ func TestCreateDb(t *testing.T) { func TestResize(t *testing.T) { client := &MockClient{} - id := "DSQ" + id := "987" var size int32 = 10 - err := client.Resize(id, int32(size)) + err := client.Resize(id, size) if err != nil { t.Fatal("unexpected error") } diff --git a/script/bootstrap b/script/bootstrap index 3618a07..3ec026c 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -50,7 +50,7 @@ fi if ! command -v golangci-lint &> /dev/null then - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.26.0 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.36.0 else echo "golangci-lint installed skipping" fi