Skip to content

Commit

Permalink
better error handling of missing flags during login
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Svihla committed Apr 1, 2021
1 parent f2baa1e commit 99cdaec
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 33 deletions.
67 changes: 49 additions & 18 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func init() {
}

const (
CriticalError = 1
WriteError = 2
CannotFindHome = 3
JSONError = 4
Expand All @@ -53,15 +54,23 @@ var loginCmd = &cobra.Command{
Run: func(cobraCmd *cobra.Command, args []string) {
exitCode, err := executeLogin(args, func() (string, pkg.ConfFiles, error) {
return pkg.GetHome(os.UserHomeDir)
})
}, cobraCmd.Usage)
if err != nil {
fmt.Printf("%v\n", err)
}
os.Exit(exitCode)
if exitCode != 0 {
os.Exit(exitCode)
}
},
}

func executeLogin(args []string, getHome func() (string, pkg.ConfFiles, error)) (int, error) {
func executeLogin(args []string, getHome func() (string, pkg.ConfFiles, error), usageFunc func() error) (int, error) {
if len(args) == 0 {
if err := usageFunc(); err != nil {
return CriticalError, fmt.Errorf("cannot show usage %v", err)
}
return 0, nil
}
confDir, confFiles, err := getHome()
if err != nil {
return CannotFindHome, err
Expand All @@ -73,34 +82,26 @@ func executeLogin(args []string, getHome func() (string, pkg.ConfFiles, error))
}
return 0, nil
case clientJSON != "":
var clientInfo astraops.ClientInfo
err := json.Unmarshal([]byte(clientJSON), &clientInfo)
if err != nil {
return JSONError, fmt.Errorf("unable to serialize the json into a valid login due to error %s", err)
}
if len(clientInfo.ClientName) == 0 {
return executeLoginJSON(args, confDir, confFiles)
default:
if clientID == "" {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientName missing"),
Err: fmt.Errorf("clientId missing"),
}
}
if len(clientInfo.ClientID) == 0 {
if clientName == "" {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientId missing"),
Err: fmt.Errorf("clientName missing"),
}
}
if len(clientInfo.ClientSecret) == 0 {
if clientSecret == "" {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientSecret missing"),
}
}
if err := makeConf(confDir, confFiles.SaPath, clientJSON); err != nil {
return WriteError, err
}
return 0, nil
default:
clientJSON = fmt.Sprintf("{\"clientId\":\"%v\",\"clientName\":\"%v\",\"clientSecret\":\"%v\"}", clientID, clientName, clientSecret)
if err := makeConf(confDir, confFiles.SaPath, clientJSON); err != nil {
return WriteError, err
Expand All @@ -109,6 +110,36 @@ func executeLogin(args []string, getHome func() (string, pkg.ConfFiles, error))
}
}

func executeLoginJSON(args []string, confDir string, confFiles pkg.ConfFiles) (int, error) {
var clientInfo astraops.ClientInfo
err := json.Unmarshal([]byte(clientJSON), &clientInfo)
if err != nil {
return JSONError, fmt.Errorf("unable to serialize the json into a valid login due to error %s", err)
}
if len(clientInfo.ClientName) == 0 {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientName missing"),
}
}
if len(clientInfo.ClientID) == 0 {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientId missing"),
}
}
if len(clientInfo.ClientSecret) == 0 {
return JSONError, &pkg.ParseError{
Args: args,
Err: fmt.Errorf("clientSecret missing"),
}
}
if err := makeConf(confDir, confFiles.SaPath, clientJSON); err != nil {
return WriteError, err
}
return 0, nil
}

func makeConf(confDir, confFile, content string) error {
if err := os.MkdirAll(confDir, 0700); err != nil {
return fmt.Errorf("unable to get make config directory with error %s", err)
Expand Down
160 changes: 145 additions & 15 deletions cmd/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
package cmd

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"testing"
Expand All @@ -26,19 +28,25 @@ import (
)

const testJSON = `{"clientId":"deeb55bd-2a55-4988-a345-d8fdddd0e0c9","clientName":"[email protected]","clientSecret":"6ae15bff-1435-430f-975b-9b3d9914b698"}`
const testSecret = "jljlajef"
const testName = "[email protected]"
const testID = "abd278332"

func usageFunc() error {
return nil
}
func TestLoginCmdJson(t *testing.T) {
clientJSON = testJSON
defer func() {
clientJSON = ""
}()
dir := path.Join(t.TempDir(), "config")
f := path.Join(dir, "mytempFile")
exitCode, err := executeLogin([]string{}, func() (string, pkg.ConfFiles, error) {
exitCode, err := executeLogin([]string{"--json", clientJSON}, func() (string, pkg.ConfFiles, error) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err != nil {
t.Fatalf("unexpected error %v", err)
Expand Down Expand Up @@ -83,7 +91,7 @@ func TestLoginCmdJsonInvalidPerms(t *testing.T) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Error("expected error")
Expand All @@ -109,11 +117,11 @@ func TestArgs(t *testing.T) {

dir := path.Join(t.TempDir(), "config")
f := path.Join(dir, "mytempFile")
exitCode, err := executeLogin([]string{}, func() (string, pkg.ConfFiles, error) {
exitCode, err := executeLogin([]string{"--clientId", clientID, "--clientName", clientName, "--clientSecret", clientSecret}, func() (string, pkg.ConfFiles, error) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err != nil {
t.Fatalf("unexpected error %v", err)
Expand Down Expand Up @@ -157,11 +165,11 @@ func TestArgsWithNoPermission(t *testing.T) {
}
defer os.RemoveAll(inaccessible)
f := path.Join(inaccessible, "mytempFile")
exitCode, err := executeLogin([]string{}, func() (string, pkg.ConfFiles, error) {
exitCode, err := executeLogin([]string{"--clientId", clientID, "--clientName", clientName, "--clientSecret", clientSecret}, func() (string, pkg.ConfFiles, error) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Error("expected error")
Expand All @@ -175,10 +183,85 @@ func TestArgsWithNoPermission(t *testing.T) {
}
}

func TestLoginArgsMissingId(t *testing.T) {
clientJSON = ""
authToken = ""
clientName = testName
clientSecret = testSecret
clientID = ""
defer func() {
clientSecret = ""
clientName = ""
}()
exitCode, err := executeLogin([]string{"--clientId", clientID, "--clientName", clientName, "--clientSecret", clientSecret}, func() (string, pkg.ConfFiles, error) {
return "", pkg.ConfFiles{}, nil
}, usageFunc)
if err == nil {
t.Error("expected error")
}
expected := `Unable to parse command line with args: --clientId, , --clientName, [email protected], --clientSecret, jljlajef. Nested error was 'clientId missing'`
if err.Error() != expected {
t.Errorf("expected '%v' but was '%v'", expected, err.Error())
}
if exitCode != JSONError {
t.Errorf("unexpected exit code %v", exitCode)
}
}

func TestLoginArgsMissingName(t *testing.T) {
clientJSON = ""
authToken = ""
clientName = ""
clientSecret = testSecret
clientID = testID
defer func() {
clientSecret = ""
clientID = ""
}()
exitCode, err := executeLogin([]string{"--clientId", clientID, "--clientName", clientName, "--clientSecret", clientSecret}, func() (string, pkg.ConfFiles, error) {
return "", pkg.ConfFiles{}, nil
}, usageFunc)
if err == nil {
t.Errorf("expected error")
}
expected := `Unable to parse command line with args: --clientId, abd278332, --clientName, , --clientSecret, jljlajef. Nested error was 'clientName missing'`
if err.Error() != expected {
t.Errorf("expected '%v' but was '%v'", expected, err.Error())
}
if exitCode != JSONError {
t.Errorf("unexpected exit code %v", exitCode)
}
}

func TestLoginArgsMissingSecret(t *testing.T) {
clientJSON = ""
authToken = ""
clientName = testName
clientSecret = ""
clientID = testID
defer func() {
clientName = ""
clientID = ""
}()
exitCode, err := executeLogin([]string{"--clientId", clientID, "--clientName", clientName, "--clientSecret", clientSecret}, func() (string, pkg.ConfFiles, error) {
return "", pkg.ConfFiles{}, nil
}, usageFunc)
if err == nil {
t.Error("expected error")
}
expected := `Unable to parse command line with args: --clientId, abd278332, --clientName, [email protected], --clientSecret, . Nested error was 'clientSecret missing'`
if err.Error() != expected {
t.Errorf("expected '%v' but was '%v'", expected, err.Error())
}
if exitCode != JSONError {
t.Errorf("unexpected exit code %v", exitCode)
}
}

func TestLoginHomeError(t *testing.T) {
exitCode, err := executeLogin([]string{"--json", clientJSON}, func() (string, pkg.ConfFiles, error) {
return "", pkg.ConfFiles{}, fmt.Errorf("big error")
})
}, usageFunc)
if err == nil {
t.Error("expected error")
}
Expand All @@ -191,6 +274,24 @@ func TestLoginHomeError(t *testing.T) {
}
}

func TestLoginUsageError(t *testing.T) {
exitCode, err := executeLogin([]string{}, func() (string, pkg.ConfFiles, error) {
return "", pkg.ConfFiles{}, fmt.Errorf("big error")
}, func() error {
return fmt.Errorf("no terminal")
})
if err == nil {
t.Error("expected error")
}
expected := "cannot show usage no terminal"
if err.Error() != expected {
t.Errorf("expected '%v' but was '%v'", expected, err.Error())
}
if exitCode != CriticalError {
t.Errorf("unexpected exit code %v", exitCode)
}
}

func TestLoginCmdJsonMissignId(t *testing.T) {
clientJSON = `{"clientId":"","clientName":"[email protected]","clientSecret":"6ae15bff-1435-430f-975b-9b3d9914b698"}`
defer func() {
Expand All @@ -202,7 +303,7 @@ func TestLoginCmdJsonMissignId(t *testing.T) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Error("expected error")
Expand All @@ -227,7 +328,7 @@ func TestLoginCmdJsonMissignName(t *testing.T) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Errorf("expected error")
Expand All @@ -252,7 +353,7 @@ func TestLoginCmdJsonMissignSecret(t *testing.T) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Error("expected error")
Expand All @@ -273,11 +374,11 @@ func TestLoginCmdJsonInvalid(t *testing.T) {
}()
dir := path.Join(t.TempDir(), "config")
f := path.Join(dir, "mytempFile")
exitCode, err := executeLogin([]string{}, func() (string, pkg.ConfFiles, error) {
exitCode, err := executeLogin([]string{"--json", clientJSON}, func() (string, pkg.ConfFiles, error) {
return dir, pkg.ConfFiles{
SaPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Errorf("expected error")
Expand All @@ -298,7 +399,7 @@ func TestLoginToken(t *testing.T) {
return dir, pkg.ConfFiles{
TokenPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err != nil {
t.Fatalf("unexpected error %v", err)
Expand Down Expand Up @@ -339,7 +440,7 @@ func TestLoginTokenInvalidPerms(t *testing.T) {
return dir, pkg.ConfFiles{
TokenPath: f,
}, nil
})
}, usageFunc)
defer os.RemoveAll(dir)
if err == nil {
t.Error("expected error")
Expand Down Expand Up @@ -413,3 +514,32 @@ func TestMakeConfWithNonMakeableDir(t *testing.T) {
t.Errorf("expected '%v' but was '%v'", expected, err.Error())
}
}

func TestLoginShowHelp(t *testing.T) {
clientJSON = ""
authToken = ""
clientName = ""
clientSecret = ""
clientID = ""
originalOut := RootCmd.OutOrStderr()
defer func() {
RootCmd.SetOut(originalOut)
RootCmd.SetArgs([]string{})
}()
b := bytes.NewBufferString("")
RootCmd.SetOut(b)
RootCmd.SetArgs([]string{"login"})
err := RootCmd.Execute()
if err != nil {
t.Errorf("unexpected error '%v'", err)
}
out, err := ioutil.ReadAll(b)
if err != nil {
t.Fatal(err)
}
expected := loginCmd.UsageString()

if string(out) != expected {
t.Errorf("expected\n'%q'\nbut was\n'%q'", expected, string(out))
}
}
Loading

0 comments on commit 99cdaec

Please sign in to comment.