Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Migrate to cobra #86

Merged
merged 10 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fix all erorr handling to use errors
  • Loading branch information
cmoog committed Aug 7, 2020
commit 5f7d2053e4fbfda580c5b5b225edd047daade125
2 changes: 1 addition & 1 deletion ci/integration/users_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestUsers(t *testing.T) {

c, err := tcli.NewContainerRunner(ctx, &tcli.ContainerConfig{
Image: "codercom/enterprise-dev",
Name: "coder-cli-tests",
Name: "users-cli-tests",
BindMounts: map[string]string{
binpath: "/bin/coder",
},
Expand Down
10 changes: 10 additions & 0 deletions cmd/coder/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (

"cdr.dev/coder-cli/internal/config"
"cdr.dev/coder-cli/internal/entclient"

"go.coder.com/flog"
)

// requireAuth exits the process with a nonzero exit code if the user is not authenticated to make requests
func requireAuth() *entclient.Client {
sessionToken, err := config.Session.Read()
requireSuccess(err, "read session: %v (did you run coder login?)", err)
Expand All @@ -22,3 +25,10 @@ func requireAuth() *entclient.Client {
Token: sessionToken,
}
}

// requireSuccess prints the given message and format args as a fatal error if err != nil
func requireSuccess(err error, msg string, args ...interface{}) {
if err != nil {
flog.Fatal(msg, args...)
}
}
35 changes: 22 additions & 13 deletions cmd/coder/ceapi.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import (
"golang.org/x/xerrors"

"go.coder.com/flog"

"cdr.dev/coder-cli/internal/entclient"
Expand All @@ -25,43 +27,50 @@ outer:
}

// getEnvs returns all environments for the user.
func getEnvs(client *entclient.Client) []entclient.Environment {
func getEnvs(client *entclient.Client) ([]entclient.Environment, error) {
me, err := client.Me()
requireSuccess(err, "get self: %+v", err)
if err != nil {
return nil, xerrors.Errorf("get self: %+v", err)
}

orgs, err := client.Orgs()
requireSuccess(err, "get orgs: %+v", err)
if err != nil {
return nil, xerrors.Errorf("get orgs: %+v", err)
}

orgs = userOrgs(me, orgs)

var allEnvs []entclient.Environment

for _, org := range orgs {
envs, err := client.Envs(me, org)
requireSuccess(err, "get envs for %v: %+v", org.Name, err)
if err != nil {
return nil, xerrors.Errorf("get envs for %v: %+v", org.Name, err)
}

for _, env := range envs {
allEnvs = append(allEnvs, env)
}
}

return allEnvs
return allEnvs, nil
}

// findEnv returns a single environment by name (if it exists.)
func findEnv(client *entclient.Client, name string) entclient.Environment {
envs := getEnvs(client)
func findEnv(client *entclient.Client, name string) (*entclient.Environment, error) {
envs, err := getEnvs(client)
if err != nil {
return nil, xerrors.Errorf("failed to get environments: %w", err)
}

var found []string

for _, env := range envs {
found = append(found, env.Name)
if env.Name == name {
return env
return &env, nil
}
}

flog.Info("found %q", found)
flog.Fatal("environment %q not found", name)
panic("unreachable")
flog.Error("found %q", found)
flog.Error("%q not found", name)
return nil, xerrors.New("environment not found")
}
33 changes: 18 additions & 15 deletions cmd/coder/configssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import (
"cdr.dev/coder-cli/internal/config"
"cdr.dev/coder-cli/internal/entclient"
"github.com/urfave/cli"

"go.coder.com/flog"
"golang.org/x/xerrors"
)

func makeConfigSSHCmd() cli.Command {
Expand Down Expand Up @@ -46,7 +45,7 @@ func makeConfigSSHCmd() cli.Command {
}
}

func configSSH(filepath *string, remove *bool) func(c *cli.Context) {
func configSSH(filepath *string, remove *bool) func(c *cli.Context) error {
startToken := "# ------------START-CODER-ENTERPRISE-----------"
startMessage := `# The following has been auto-generated by "coder config-ssh"
# to make accessing your Coder Enterprise environments easier.
Expand All @@ -58,7 +57,7 @@ func configSSH(filepath *string, remove *bool) func(c *cli.Context) {
# You should not hand-edit this section, unless you are deleting it.`
endToken := "# ------------END-CODER-ENTERPRISE------------"

return func(c *cli.Context) {
return func(c *cli.Context) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

Expand All @@ -67,45 +66,48 @@ func configSSH(filepath *string, remove *bool) func(c *cli.Context) {
// SSH configs are not always already there.
currentConfig = ""
} else if err != nil {
flog.Fatal("failed to read ssh config file %q: %v", filepath, err)
return xerrors.Errorf("failed to read ssh config file %q: %w", filepath, err)
}

startIndex := strings.Index(currentConfig, startToken)
endIndex := strings.Index(currentConfig, endToken)

if *remove {
if startIndex == -1 || endIndex == -1 {
flog.Fatal("the Coder Enterprise ssh configuration section could not be safely deleted or does not exist")
return xerrors.Errorf("the Coder Enterprise ssh configuration section could not be safely deleted or does not exist")
}
currentConfig = currentConfig[:startIndex-1] + currentConfig[endIndex+len(endToken)+1:]

err = writeStr(*filepath, currentConfig)
if err != nil {
flog.Fatal("failed to write to ssh config file %q: %v", *filepath, err)
return xerrors.Errorf("failed to write to ssh config file %q: %v", *filepath, err)
}

return
return nil
}

entClient := requireAuth()

sshAvailable := isSSHAvailable(ctx)
if !sshAvailable {
flog.Fatal("SSH is disabled or not available for your Coder Enterprise deployment.")
return xerrors.New("SSH is disabled or not available for your Coder Enterprise deployment.")
}

me, err := entClient.Me()
if err != nil {
flog.Fatal("failed to fetch username: %v", err)
return xerrors.Errorf("failed to fetch username: %w", err)
}

envs := getEnvs(entClient)
envs, err := getEnvs(entClient)
if err != nil {
return err
}
if len(envs) < 1 {
flog.Fatal("no environments found")
return xerrors.New("no environments found")
}
newConfig, err := makeNewConfigs(me.Username, envs, startToken, startMessage, endToken)
if err != nil {
flog.Fatal("failed to make new ssh configurations: %v", err)
return xerrors.Errorf("failed to make new ssh configurations: %w", err)
}

// if we find the old config, remove those chars from the string
Expand All @@ -115,17 +117,18 @@ func configSSH(filepath *string, remove *bool) func(c *cli.Context) {

err = writeStr(*filepath, currentConfig+newConfig)
if err != nil {
flog.Fatal("failed to write new configurations to ssh config file %q: %v", filepath, err)
return xerrors.Errorf("failed to write new configurations to ssh config file %q: %w", filepath, err)
}
err = writeSSHKey(ctx, entClient)
if err != nil {
flog.Fatal("failed to fetch and write ssh key: %v", err)
return xerrors.Errorf("failed to fetch and write ssh key: %w", err)
}

fmt.Printf("An auto-generated ssh config was written to %q\n", *filepath)
fmt.Printf("Your private ssh key was written to %q\n", privateKeyFilepath)
fmt.Println("You should now be able to ssh into your environment")
fmt.Printf("For example, try running\n\n\t$ ssh coder.%s\n\n", envs[0].Name)
return nil
}
}

Expand Down
21 changes: 14 additions & 7 deletions cmd/coder/envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (

"cdr.dev/coder-cli/internal/x/xtabwriter"
"github.com/urfave/cli"

"go.coder.com/flog"
"golang.org/x/xerrors"
)

func makeEnvsCommand() cli.Command {
Expand All @@ -23,22 +22,30 @@ func makeEnvsCommand() cli.Command {
Usage: "list all environments owned by the active user",
Description: "List all Coder environments owned by the active user.",
ArgsUsage: "[...flags]>",
Action: func(c *cli.Context) {
Action: func(c *cli.Context) error {
entClient := requireAuth()
envs := getEnvs(entClient)
envs, err := getEnvs(entClient)
if err != nil {
return err
}

switch outputFmt {
case "human":
err := xtabwriter.WriteTable(len(envs), func(i int) interface{} {
return envs[i]
})
requireSuccess(err, "failed to write table: %v", err)
if err != nil {
return xerrors.Errorf("failed to write table: %w", err)
}
case "json":
err := json.NewEncoder(os.Stdout).Encode(envs)
requireSuccess(err, "failed to write json: %v", err)
if err != nil {
return xerrors.Errorf("failed to write environments as JSON: %w", err)
}
default:
flog.Fatal("unknown --output value %q", outputFmt)
return xerrors.Errorf("unknown --output value %q", outputFmt)
}
return nil
},
Flags: []cli.Flag{
cli.StringFlag{
Expand Down
12 changes: 0 additions & 12 deletions cmd/coder/exit.go

This file was deleted.

14 changes: 8 additions & 6 deletions cmd/coder/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"cdr.dev/coder-cli/internal/loginsrv"
"github.com/pkg/browser"
"github.com/urfave/cli"
"golang.org/x/xerrors"

"go.coder.com/flog"
)
Expand All @@ -24,20 +25,20 @@ func makeLoginCmd() cli.Command {
}
}

func login(c *cli.Context) {
func login(c *cli.Context) error {
rawURL := c.Args().First()
if rawURL == "" || !strings.HasPrefix(rawURL, "http") {
flog.Fatal("invalid URL")
return xerrors.Errorf("invalid URL")
}

u, err := url.Parse(rawURL)
if err != nil {
flog.Fatal("parse url: %v", err)
return xerrors.Errorf("parse url: %v", err)
}

listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
flog.Fatal("create login server: %+v", err)
return xerrors.Errorf("create login server: %+v", err)
}
defer listener.Close()

Expand All @@ -54,7 +55,7 @@ func login(c *cli.Context) {
(&url.URL{Scheme: u.Scheme, Host: u.Host}).String(),
)
if err != nil {
flog.Fatal("write url: %v", err)
return xerrors.Errorf("write url: %v", err)
}

authURL := url.URL{
Expand All @@ -74,7 +75,8 @@ func login(c *cli.Context) {
err = config.Session.Write(srv.Token)
srv.TokenCond.L.Unlock()
if err != nil {
flog.Fatal("set session: %v", err)
return xerrors.Errorf("set session: %v", err)
}
flog.Success("logged in")
return nil
}
8 changes: 5 additions & 3 deletions cmd/coder/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"cdr.dev/coder-cli/internal/config"
"github.com/urfave/cli"
"golang.org/x/xerrors"

"go.coder.com/flog"
)
Expand All @@ -17,14 +18,15 @@ func makeLogoutCmd() cli.Command {
}
}

func logout(c *cli.Context) {
func logout(_ *cli.Context) error {
err := config.Session.Delete()
if err != nil {
if os.IsNotExist(err) {
flog.Info("no active session")
return
return nil
}
flog.Fatal("delete session: %v", err)
return xerrors.Errorf("delete session: %w", err)
}
flog.Success("logged out")
return nil
}
7 changes: 0 additions & 7 deletions cmd/coder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,6 @@ func main() {
}
}

// requireSuccess prints the given message and format args as a fatal error if err != nil
func requireSuccess(err error, msg string, args ...interface{}) {
if err != nil {
flog.Fatal(msg, args...)
}
}

func exitHelp(c *cli.Context) {
cli.ShowCommandHelpAndExit(c, c.Command.FullName(), 1)
}
Loading