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

Commit aa300a2

Browse files
committed
Migrate to cobra
1 parent e26341d commit aa300a2

File tree

14 files changed

+361
-340
lines changed

14 files changed

+361
-340
lines changed

ci/integration/integration_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,21 @@ func TestCoderCLI(t *testing.T) {
3939

4040
c.Run(ctx, "coder --help").Assert(t,
4141
tcli.Success(),
42-
tcli.StdoutMatches("COMMANDS:"),
43-
tcli.StdoutMatches("USAGE:"),
42+
tcli.StdoutMatches("Available Commands"),
4443
)
4544

4645
headlessLogin(ctx, t, c)
4746

4847
c.Run(ctx, "coder envs").Assert(t,
49-
tcli.Error(),
48+
tcli.Success(),
5049
)
5150

5251
c.Run(ctx, "coder envs ls").Assert(t,
5352
tcli.Success(),
5453
)
5554

5655
c.Run(ctx, "coder urls").Assert(t,
57-
tcli.Error(),
56+
tcli.Success(),
5857
)
5958

6059
c.Run(ctx, "coder sync").Assert(t,

ci/integration/secrets_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestSecrets(t *testing.T) {
3939
)
4040

4141
// this tests the "Value:" prompt fallback
42-
c.Run(ctx, fmt.Sprintf("echo %s | coder secrets create --from-prompt %s", value, name)).Assert(t,
42+
c.Run(ctx, fmt.Sprintf("echo %s | coder secrets create %s --from-prompt", value, name)).Assert(t,
4343
tcli.Success(),
4444
tcli.StderrEmpty(),
4545
)
@@ -70,7 +70,7 @@ func TestSecrets(t *testing.T) {
7070

7171
name, value = randString(8), randString(8)
7272

73-
c.Run(ctx, fmt.Sprintf("coder secrets create --from-literal %s %s", value, name)).Assert(t,
73+
c.Run(ctx, fmt.Sprintf("coder secrets create %s --from-literal %s", name, value)).Assert(t,
7474
tcli.Success(),
7575
tcli.StderrEmpty(),
7676
)
@@ -84,7 +84,7 @@ func TestSecrets(t *testing.T) {
8484
c.Run(ctx, fmt.Sprintf("echo %s > ~/secret.json", value)).Assert(t,
8585
tcli.Success(),
8686
)
87-
c.Run(ctx, fmt.Sprintf("coder secrets create --from-file ~/secret.json %s", name)).Assert(t,
87+
c.Run(ctx, fmt.Sprintf("coder secrets create %s --from-file ~/secret.json", name)).Assert(t,
8888
tcli.Success(),
8989
)
9090
//

cmd/coder/configssh.go

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,29 @@ import (
1313

1414
"cdr.dev/coder-cli/internal/config"
1515
"cdr.dev/coder-cli/internal/entclient"
16-
"github.com/urfave/cli/v2"
16+
"github.com/spf13/cobra"
1717
"golang.org/x/xerrors"
1818
)
1919

20-
func makeConfigSSHCmd() *cli.Command {
20+
func makeConfigSSHCmd() *cobra.Command {
2121
var (
2222
configpath string
2323
remove = false
2424
)
2525

26-
return &cli.Command{
27-
Name: "config-ssh",
28-
Usage: "Configure SSH to access Coder environments",
29-
Description: "Inject the proper OpenSSH configuration into your local SSH config file.",
30-
Action: configSSH(&configpath, &remove),
31-
Flags: []cli.Flag{
32-
&cli.StringFlag{
33-
Name: "filepath",
34-
Usage: "overide the default path of your ssh config file",
35-
Value: filepath.Join(os.Getenv("HOME"), ".ssh", "config"),
36-
TakesFile: true,
37-
Destination: &configpath,
38-
},
39-
&cli.BoolFlag{
40-
Name: "remove",
41-
Usage: "remove the auto-generated Coder Enterprise ssh config",
42-
Destination: &remove,
43-
},
44-
},
26+
cmd := &cobra.Command{
27+
Use: "config-ssh",
28+
Short: "Configure SSH to access Coder environments",
29+
Long: "Inject the proper OpenSSH configuration into your local SSH config file.",
30+
RunE: configSSH(&configpath, &remove),
4531
}
32+
cmd.Flags().StringVar(&configpath, "filepath", filepath.Join(os.Getenv("HOME"), ".ssh", "config"), "overide the default path of your ssh config file")
33+
cmd.Flags().BoolVar(&remove, "remove", false, "remove the auto-generated Coder Enterprise ssh config")
34+
35+
return cmd
4636
}
4737

48-
func configSSH(filepath *string, remove *bool) func(c *cli.Context) error {
38+
func configSSH(filepath *string, remove *bool) func(cmd *cobra.Command, _ []string) error {
4939
startToken := "# ------------START-CODER-ENTERPRISE-----------"
5040
startMessage := `# The following has been auto-generated by "coder config-ssh"
5141
# to make accessing your Coder Enterprise environments easier.
@@ -57,7 +47,7 @@ func configSSH(filepath *string, remove *bool) func(c *cli.Context) error {
5747
# You should not hand-edit this section, unless you are deleting it.`
5848
endToken := "# ------------END-CODER-ENTERPRISE------------"
5949

60-
return func(c *cli.Context) error {
50+
return func(cmd *cobra.Command, _ []string) error {
6151
ctx, cancel := context.WithCancel(context.Background())
6252
defer cancel()
6353

cmd/coder/envs.go

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,58 +5,50 @@ import (
55
"os"
66

77
"cdr.dev/coder-cli/internal/x/xtabwriter"
8-
"github.com/urfave/cli/v2"
8+
"github.com/spf13/cobra"
99
"golang.org/x/xerrors"
1010
)
1111

12-
func makeEnvsCommand() *cli.Command {
12+
func makeEnvsCommand() *cobra.Command {
1313
var outputFmt string
14-
return &cli.Command{
15-
Name: "envs",
16-
Usage: "Interact with Coder environments",
17-
Description: "Perform operations on the Coder environments owned by the active user.",
18-
Action: exitHelp,
19-
Subcommands: []*cli.Command{
20-
{
21-
Name: "ls",
22-
Usage: "list all environments owned by the active user",
23-
Description: "List all Coder environments owned by the active user.",
24-
ArgsUsage: "[...flags]",
25-
Action: func(c *cli.Context) error {
26-
entClient := requireAuth()
27-
envs, err := getEnvs(entClient)
28-
if err != nil {
29-
return err
30-
}
14+
cmd := &cobra.Command{
15+
Use: "envs",
16+
Short: "Interact with Coder environments",
17+
Long: "Perform operations on the Coder environments owned by the active user.",
18+
}
19+
20+
lsCmd := &cobra.Command{
21+
Use: "ls",
22+
Short: "list all environments owned by the active user",
23+
Long: "List all Coder environments owned by the active user.",
24+
RunE: func(cmd *cobra.Command, args []string) error {
25+
entClient := requireAuth()
26+
envs, err := getEnvs(entClient)
27+
if err != nil {
28+
return err
29+
}
3130

32-
switch outputFmt {
33-
case "human":
34-
err := xtabwriter.WriteTable(len(envs), func(i int) interface{} {
35-
return envs[i]
36-
})
37-
if err != nil {
38-
return xerrors.Errorf("write table: %w", err)
39-
}
40-
case "json":
41-
err := json.NewEncoder(os.Stdout).Encode(envs)
42-
if err != nil {
43-
return xerrors.Errorf("write environments as JSON: %w", err)
44-
}
45-
default:
46-
return xerrors.Errorf("unknown --output value %q", outputFmt)
47-
}
48-
return nil
49-
},
50-
Flags: []cli.Flag{
51-
&cli.StringFlag{
52-
Name: "output",
53-
Aliases: []string{"o"},
54-
Usage: "json | human",
55-
Value: "human",
56-
Destination: &outputFmt,
57-
},
58-
},
59-
},
31+
switch outputFmt {
32+
case "human":
33+
err := xtabwriter.WriteTable(len(envs), func(i int) interface{} {
34+
return envs[i]
35+
})
36+
if err != nil {
37+
return xerrors.Errorf("write table: %w", err)
38+
}
39+
case "json":
40+
err := json.NewEncoder(os.Stdout).Encode(envs)
41+
if err != nil {
42+
return xerrors.Errorf("write environments as JSON: %w", err)
43+
}
44+
default:
45+
return xerrors.Errorf("unknown --output value %q", outputFmt)
46+
}
47+
return nil
6048
},
6149
}
50+
lsCmd.Flags().StringVarP(&outputFmt, "output", "o", "human", "human | json")
51+
cmd.AddCommand(lsCmd)
52+
53+
return cmd
6254
}

cmd/coder/login.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@ import (
1010
"cdr.dev/coder-cli/internal/config"
1111
"cdr.dev/coder-cli/internal/loginsrv"
1212
"github.com/pkg/browser"
13-
"github.com/urfave/cli/v2"
13+
"github.com/spf13/cobra"
1414
"golang.org/x/xerrors"
1515

1616
"go.coder.com/flog"
1717
)
1818

19-
func makeLoginCmd() *cli.Command {
20-
return &cli.Command{
21-
Name: "login",
22-
Usage: "Authenticate this client for future operations",
23-
ArgsUsage: "[Coder Enterprise URL eg. http://my.coder.domain/]",
24-
Action: login,
19+
func makeLoginCmd() *cobra.Command {
20+
cmd := &cobra.Command{
21+
Use: "login [Coder Enterprise URL eg. http://my.coder.domain/]",
22+
Short: "Authenticate this client for future operations",
23+
Args: cobra.ExactArgs(1),
24+
RunE: login,
2525
}
26+
return cmd
2627
}
2728

28-
func login(c *cli.Context) error {
29-
rawURL := c.Args().First()
29+
func login(cmd *cobra.Command, args []string) error {
30+
rawURL := args[0]
3031
if rawURL == "" || !strings.HasPrefix(rawURL, "http") {
3132
return xerrors.Errorf("invalid URL")
3233
}

cmd/coder/logout.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import (
44
"os"
55

66
"cdr.dev/coder-cli/internal/config"
7-
"github.com/urfave/cli/v2"
7+
"github.com/spf13/cobra"
88
"golang.org/x/xerrors"
99

1010
"go.coder.com/flog"
1111
)
1212

13-
func makeLogoutCmd() *cli.Command {
14-
return &cli.Command{
15-
Name: "logout",
16-
Usage: "Remove local authentication credentials if any exist",
17-
Action: logout,
13+
func makeLogoutCmd() *cobra.Command {
14+
return &cobra.Command{
15+
Use: "logout",
16+
Short: "Remove local authentication credentials if any exist",
17+
RunE: logout,
1818
}
1919
}
2020

21-
func logout(_ *cli.Context) error {
21+
func logout(_ *cobra.Command, _ []string) error {
2222
err := config.Session.Delete()
2323
if err != nil {
2424
if os.IsNotExist(err) {

cmd/coder/main.go

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"runtime"
1010

1111
"cdr.dev/coder-cli/internal/x/xterminal"
12-
"github.com/urfave/cli/v2"
12+
"github.com/spf13/cobra"
1313

1414
"go.coder.com/flog"
1515
)
@@ -31,16 +31,13 @@ func main() {
3131
}
3232
defer xterminal.Restore(os.Stdout.Fd(), stdoutState)
3333

34-
app := cli.NewApp()
35-
app.Name = "coder"
36-
app.Usage = "coder provides a CLI for working with an existing Coder Enterprise installation"
37-
app.Version = fmt.Sprintf("%s %s %s/%s", version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
38-
app.CommandNotFound = func(c *cli.Context, s string) {
39-
flog.Fatal("command %q not found", s)
34+
app := &cobra.Command{
35+
Use: "coder",
36+
Short: "coder provides a CLI for working with an existing Coder Enterprise installation",
37+
Version: fmt.Sprintf("%s %s %s/%s", version, runtime.Version(), runtime.GOOS, runtime.GOARCH),
4038
}
41-
app.Action = exitHelp
4239

43-
app.Commands = []*cli.Command{
40+
app.AddCommand(
4441
makeLoginCmd(),
4542
makeLogoutCmd(),
4643
makeShellCmd(),
@@ -50,14 +47,62 @@ func main() {
5047
makeEnvsCommand(),
5148
makeSyncCmd(),
5249
makeURLCmd(),
53-
}
54-
err = app.Run(os.Args)
50+
completionCmd,
51+
)
52+
err = app.Execute()
5553
if err != nil {
56-
flog.Fatal("%v", err)
54+
os.Exit(1)
5755
}
5856
}
5957

60-
func exitHelp(c *cli.Context) error {
61-
cli.ShowCommandHelpAndExit(c, c.Command.FullName(), 1)
62-
return nil
58+
// reference: https://github.com/spf13/cobra/blob/master/shell_completions.md
59+
var completionCmd = &cobra.Command{
60+
Use: "completion [bash|zsh|fish|powershell]",
61+
Short: "Generate completion script",
62+
Long: `To load completions:
63+
64+
Bash:
65+
66+
$ source <(yourprogram completion bash)
67+
68+
# To load completions for each session, execute once:
69+
Linux:
70+
$ yourprogram completion bash > /etc/bash_completion.d/yourprogram
71+
MacOS:
72+
$ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram
73+
74+
Zsh:
75+
76+
# If shell completion is not already enabled in your environment you will need
77+
# to enable it. You can execute the following once:
78+
79+
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
80+
81+
# To load completions for each session, execute once:
82+
$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
83+
84+
# You will need to start a new shell for this setup to take effect.
85+
86+
Fish:
87+
88+
$ yourprogram completion fish | source
89+
90+
# To load completions for each session, execute once:
91+
$ yourprogram completion fish > ~/.config/fish/completions/yourprogram.fish
92+
`,
93+
DisableFlagsInUseLine: true,
94+
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
95+
Args: cobra.ExactValidArgs(1),
96+
Run: func(cmd *cobra.Command, args []string) {
97+
switch args[0] {
98+
case "bash":
99+
cmd.Root().GenBashCompletion(os.Stdout)
100+
case "zsh":
101+
cmd.Root().GenZshCompletion(os.Stdout)
102+
case "fish":
103+
cmd.Root().GenFishCompletion(os.Stdout, true)
104+
case "powershell":
105+
cmd.Root().GenPowerShellCompletion(os.Stdout)
106+
}
107+
},
63108
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy