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

Commit b957f37

Browse files
committed
Mirgation to urfave/cli
1 parent bae77f0 commit b957f37

File tree

19 files changed

+628
-781
lines changed

19 files changed

+628
-781
lines changed

ci/integration/integration_test.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,16 @@ func TestCoderCLI(t *testing.T) {
3434
tcli.StderrEmpty(),
3535
)
3636

37-
c.Run(ctx, "coder version").Assert(t,
37+
c.Run(ctx, "coder --version").Assert(t,
3838
tcli.StderrEmpty(),
3939
tcli.Success(),
4040
tcli.StdoutMatches("linux"),
4141
)
4242

43-
c.Run(ctx, "coder help").Assert(t,
43+
c.Run(ctx, "coder --help").Assert(t,
4444
tcli.Success(),
45-
tcli.StderrMatches("Commands:"),
46-
tcli.StderrMatches("Usage: coder"),
47-
tcli.StdoutEmpty(),
45+
tcli.StdoutMatches("COMMANDS:"),
46+
tcli.StdoutMatches("USAGE:"),
4847
)
4948

5049
headlessLogin(ctx, t, c)
@@ -53,6 +52,10 @@ func TestCoderCLI(t *testing.T) {
5352
tcli.Success(),
5453
)
5554

55+
c.Run(ctx, "coder envs ls").Assert(t,
56+
tcli.Success(),
57+
)
58+
5659
c.Run(ctx, "coder urls").Assert(t,
5760
tcli.Error(),
5861
)
@@ -66,14 +69,14 @@ func TestCoderCLI(t *testing.T) {
6669
)
6770

6871
var user entclient.User
69-
c.Run(ctx, `coder users ls -o json | jq -c '.[] | select( .username == "charlie")'`).Assert(t,
72+
c.Run(ctx, `coder users ls --output json | jq -c '.[] | select( .username == "charlie")'`).Assert(t,
7073
tcli.Success(),
7174
stdoutUnmarshalsJSON(&user),
7275
)
7376
assert.Equal(t, "user email is as expected", "charlie@coder.com", user.Email)
7477
assert.Equal(t, "username is as expected", "Charlie", user.Name)
7578

76-
c.Run(ctx, "coder users ls -o human | grep charlie").Assert(t,
79+
c.Run(ctx, "coder users ls --output human | grep charlie").Assert(t,
7780
tcli.Success(),
7881
tcli.StdoutMatches("charlie"),
7982
)
@@ -82,7 +85,7 @@ func TestCoderCLI(t *testing.T) {
8285
tcli.Success(),
8386
)
8487

85-
c.Run(ctx, "coder envs").Assert(t,
88+
c.Run(ctx, "coder envs ls").Assert(t,
8689
tcli.Error(),
8790
)
8891
}

ci/integration/secrets_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ func TestSecrets(t *testing.T) {
3636

3737
c.Run(ctx, "coder secrets create").Assert(t,
3838
tcli.Error(),
39-
tcli.StdoutEmpty(),
4039
)
4140

4241
// this tests the "Value:" prompt fallback

cmd/coder/configssh.go

Lines changed: 106 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -11,162 +11,165 @@ import (
1111
"strings"
1212
"time"
1313

14-
"github.com/spf13/pflag"
15-
"go.coder.com/cli"
16-
"go.coder.com/flog"
17-
1814
"cdr.dev/coder-cli/internal/config"
1915
"cdr.dev/coder-cli/internal/entclient"
20-
)
16+
"github.com/urfave/cli"
2117

22-
var (
23-
privateKeyFilepath = filepath.Join(os.Getenv("HOME"), ".ssh", "coder_enterprise")
18+
"go.coder.com/flog"
2419
)
2520

26-
type configSSHCmd struct {
27-
filepath string
28-
remove bool
29-
30-
startToken, startMessage, endToken string
31-
}
32-
33-
func (cmd *configSSHCmd) Spec() cli.CommandSpec {
34-
return cli.CommandSpec{
35-
Name: "config-ssh",
36-
Usage: "",
37-
Desc: "add your Coder Enterprise environments to ~/.ssh/config",
21+
func makeConfigSSHCmd() cli.Command {
22+
var (
23+
configpath string
24+
remove = false
25+
)
26+
27+
return cli.Command{
28+
Name: "config-ssh",
29+
Usage: "Configure SSH to access Coder environments",
30+
Description: "Inject the proper OpenSSH configuration into your local SSH config file.",
31+
Action: configSSH(&configpath, &remove),
32+
Flags: []cli.Flag{
33+
cli.StringFlag{
34+
Name: "filepath",
35+
Usage: "overide the default path of your ssh config file",
36+
Value: filepath.Join(os.Getenv("HOME"), ".ssh", "config"),
37+
TakesFile: true,
38+
Destination: &configpath,
39+
},
40+
cli.BoolFlag{
41+
Name: "remove",
42+
Usage: "remove the auto-generated Coder Enterprise ssh config",
43+
Destination: &remove,
44+
},
45+
},
3846
}
3947
}
4048

41-
func (cmd *configSSHCmd) RegisterFlags(fl *pflag.FlagSet) {
42-
fl.BoolVar(&cmd.remove, "remove", false, "remove the auto-generated Coder Enterprise ssh config")
43-
home := os.Getenv("HOME")
44-
defaultPath := filepath.Join(home, ".ssh", "config")
45-
fl.StringVar(&cmd.filepath, "config-path", defaultPath, "overide the default path of your ssh config file")
46-
47-
cmd.startToken = "# ------------START-CODER-ENTERPRISE-----------"
48-
cmd.startMessage = `# The following has been auto-generated by "coder config-ssh"
49+
func configSSH(filepath *string, remove *bool) func(c *cli.Context) {
50+
startToken := "# ------------START-CODER-ENTERPRISE-----------"
51+
startMessage := `# The following has been auto-generated by "coder config-ssh"
4952
# to make accessing your Coder Enterprise environments easier.
5053
#
5154
# To remove this blob, run:
5255
#
5356
# coder config-ssh --remove
5457
#
5558
# You should not hand-edit this section, unless you are deleting it.`
56-
cmd.endToken = "# ------------END-CODER-ENTERPRISE------------"
57-
}
58-
59-
func (cmd *configSSHCmd) Run(fl *pflag.FlagSet) {
60-
ctx, cancel := context.WithCancel(context.Background())
61-
defer cancel()
59+
endToken := "# ------------END-CODER-ENTERPRISE------------"
60+
61+
return func(c *cli.Context) {
62+
ctx, cancel := context.WithCancel(context.Background())
63+
defer cancel()
64+
65+
currentConfig, err := readStr(*filepath)
66+
if os.IsNotExist(err) {
67+
// SSH configs are not always already there.
68+
currentConfig = ""
69+
} else if err != nil {
70+
flog.Fatal("failed to read ssh config file %q: %v", filepath, err)
71+
}
6272

63-
currentConfig, err := readStr(cmd.filepath)
64-
if os.IsNotExist(err) {
65-
// SSH configs are not always already there.
66-
currentConfig = ""
67-
} else if err != nil {
68-
flog.Fatal("failed to read ssh config file %q: %v", cmd.filepath, err)
69-
}
73+
startIndex := strings.Index(currentConfig, startToken)
74+
endIndex := strings.Index(currentConfig, endToken)
7075

71-
startIndex := strings.Index(currentConfig, cmd.startToken)
72-
endIndex := strings.Index(currentConfig, cmd.endToken)
76+
if *remove {
77+
if startIndex == -1 || endIndex == -1 {
78+
flog.Fatal("the Coder Enterprise ssh configuration section could not be safely deleted or does not exist")
79+
}
80+
currentConfig = currentConfig[:startIndex-1] + currentConfig[endIndex+len(endToken)+1:]
7381

74-
if cmd.remove {
75-
if startIndex == -1 || endIndex == -1 {
76-
flog.Fatal("the Coder Enterprise ssh configuration section could not be safely deleted or does not exist")
77-
}
78-
currentConfig = currentConfig[:startIndex-1] + currentConfig[endIndex+len(cmd.endToken)+1:]
82+
err = writeStr(*filepath, currentConfig)
83+
if err != nil {
84+
flog.Fatal("failed to write to ssh config file %q: %v", *filepath, err)
85+
}
7986

80-
err = writeStr(cmd.filepath, currentConfig)
81-
if err != nil {
82-
flog.Fatal("failed to write to ssh config file %q: %v", cmd.filepath, err)
87+
return
8388
}
8489

85-
return
86-
}
90+
entClient := requireAuth()
8791

88-
entClient := requireAuth()
92+
sshAvailable := isSSHAvailable(ctx)
93+
if !sshAvailable {
94+
flog.Fatal("SSH is disabled or not available for your Coder Enterprise deployment.")
95+
}
8996

90-
sshAvailable := cmd.ensureSSHAvailable(ctx)
91-
if !sshAvailable {
92-
flog.Fatal("SSH is disabled or not available for your Coder Enterprise deployment.")
93-
}
97+
me, err := entClient.Me()
98+
if err != nil {
99+
flog.Fatal("failed to fetch username: %v", err)
100+
}
94101

95-
me, err := entClient.Me()
96-
if err != nil {
97-
flog.Fatal("failed to fetch username: %v", err)
98-
}
102+
envs := getEnvs(entClient)
103+
if len(envs) < 1 {
104+
flog.Fatal("no environments found")
105+
}
106+
newConfig, err := makeNewConfigs(me.Username, envs, startToken, startMessage, endToken)
107+
if err != nil {
108+
flog.Fatal("failed to make new ssh configurations: %v", err)
109+
}
99110

100-
envs := getEnvs(entClient)
101-
if len(envs) < 1 {
102-
flog.Fatal("no environments found")
103-
}
104-
newConfig, err := cmd.makeNewConfigs(me.Username, envs)
105-
if err != nil {
106-
flog.Fatal("failed to make new ssh configurations: %v", err)
107-
}
111+
// if we find the old config, remove those chars from the string
112+
if startIndex != -1 && endIndex != -1 {
113+
currentConfig = currentConfig[:startIndex-1] + currentConfig[endIndex+len(endToken)+1:]
114+
}
108115

109-
// if we find the old config, remove those chars from the string
110-
if startIndex != -1 && endIndex != -1 {
111-
currentConfig = currentConfig[:startIndex-1] + currentConfig[endIndex+len(cmd.endToken)+1:]
112-
}
116+
err = writeStr(*filepath, currentConfig+newConfig)
117+
if err != nil {
118+
flog.Fatal("failed to write new configurations to ssh config file %q: %v", filepath, err)
119+
}
120+
err = writeSSHKey(ctx, entClient)
121+
if err != nil {
122+
flog.Fatal("failed to fetch and write ssh key: %v", err)
123+
}
113124

114-
err = writeStr(cmd.filepath, currentConfig+newConfig)
115-
if err != nil {
116-
flog.Fatal("failed to write new configurations to ssh config file %q: %v", cmd.filepath, err)
117-
}
118-
err = writeSSHKey(ctx, entClient)
119-
if err != nil {
120-
flog.Fatal("failed to fetch and write ssh key: %v", err)
125+
fmt.Printf("An auto-generated ssh config was written to %q\n", *filepath)
126+
fmt.Printf("Your private ssh key was written to %q\n", privateKeyFilepath)
127+
fmt.Println("You should now be able to ssh into your environment")
128+
fmt.Printf("For example, try running\n\n\t$ ssh coder.%s\n\n", envs[0].Name)
121129
}
122-
123-
fmt.Printf("An auto-generated ssh config was written to %q\n", cmd.filepath)
124-
fmt.Printf("Your private ssh key was written to %q\n", privateKeyFilepath)
125-
fmt.Println("You should now be able to ssh into your environment")
126-
fmt.Printf("For example, try running\n\n\t$ ssh coder.%s\n\n", envs[0].Name)
127130
}
128131

132+
var (
133+
privateKeyFilepath = filepath.Join(os.Getenv("HOME"), ".ssh", "coder_enterprise")
134+
)
135+
129136
func writeSSHKey(ctx context.Context, client *entclient.Client) error {
130137
key, err := client.SSHKey()
131138
if err != nil {
132139
return err
133140
}
134-
err = ioutil.WriteFile(privateKeyFilepath, []byte(key.PrivateKey), 0400)
135-
if err != nil {
136-
return err
137-
}
138-
return nil
141+
return ioutil.WriteFile(privateKeyFilepath, []byte(key.PrivateKey), 0400)
139142
}
140143

141-
func (cmd *configSSHCmd) makeNewConfigs(userName string, envs []entclient.Environment) (string, error) {
144+
func makeNewConfigs(userName string, envs []entclient.Environment, startToken, startMsg, endToken string) (string, error) {
142145
hostname, err := configuredHostname()
143146
if err != nil {
144147
return "", nil
145148
}
146149

147-
newConfig := fmt.Sprintf("\n%s\n%s\n\n", cmd.startToken, cmd.startMessage)
150+
newConfig := fmt.Sprintf("\n%s\n%s\n\n", startToken, startMsg)
148151
for _, env := range envs {
149-
newConfig += cmd.makeConfig(hostname, userName, env.Name)
152+
newConfig += makeSSHConfig(hostname, userName, env.Name)
150153
}
151-
newConfig += fmt.Sprintf("\n%s\n", cmd.endToken)
154+
newConfig += fmt.Sprintf("\n%s\n", endToken)
152155

153156
return newConfig, nil
154157
}
155158

156-
func (cmd *configSSHCmd) makeConfig(host, userName, envName string) string {
159+
func makeSSHConfig(host, userName, envName string) string {
157160
return fmt.Sprintf(
158161
`Host coder.%s
159-
HostName %s
160-
User %s-%s
161-
StrictHostKeyChecking no
162-
ConnectTimeout=0
163-
IdentityFile=%s
164-
ServerAliveInterval 60
165-
ServerAliveCountMax 3
162+
HostName %s
163+
User %s-%s
164+
StrictHostKeyChecking no
165+
ConnectTimeout=0
166+
IdentityFile=%s
167+
ServerAliveInterval 60
168+
ServerAliveCountMax 3
166169
`, envName, host, userName, envName, privateKeyFilepath)
167170
}
168171

169-
func (cmd *configSSHCmd) ensureSSHAvailable(ctx context.Context) bool {
172+
func isSSHAvailable(ctx context.Context) bool {
170173
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
171174
defer cancel()
172175

cmd/coder/envs.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,30 @@ package main
33
import (
44
"fmt"
55

6-
"github.com/spf13/pflag"
7-
8-
"go.coder.com/cli"
6+
"github.com/urfave/cli"
97
)
108

11-
type envsCmd struct {
12-
}
13-
14-
func (cmd envsCmd) Spec() cli.CommandSpec {
15-
return cli.CommandSpec{
16-
Name: "envs",
17-
Desc: "get a list of environments owned by the authenticated user",
18-
}
19-
}
20-
21-
func (cmd envsCmd) Run(fl *pflag.FlagSet) {
22-
entClient := requireAuth()
23-
24-
envs := getEnvs(entClient)
25-
26-
for _, env := range envs {
27-
fmt.Println(env.Name)
9+
func makeEnvsCommand() cli.Command {
10+
return cli.Command{
11+
Name: "envs",
12+
Usage: "Interact with Coder environments",
13+
Description: "Perform operations on the Coder environments owned by the active user.",
14+
Subcommands: []cli.Command{
15+
{
16+
Name: "ls",
17+
Usage: "list all environments owned by the active user",
18+
Description: "List all Coder environments owned by the active user.",
19+
ArgsUsage: "[...flags]>",
20+
Action: func(c *cli.Context) {
21+
entClient := requireAuth()
22+
envs := getEnvs(entClient)
23+
24+
for _, env := range envs {
25+
fmt.Println(env.Name)
26+
}
27+
},
28+
Flags: nil,
29+
},
30+
},
2831
}
2932
}

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