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

Commit 659aabc

Browse files
committed
Migrate secrets to urfave
1 parent ad0f9c9 commit 659aabc

File tree

2 files changed

+120
-138
lines changed

2 files changed

+120
-138
lines changed

cmd/coder/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ func (r *rootCmd) Subcommands() []cdrcli.Command {
4040
&envsCmd{},
4141
&syncCmd{},
4242
&urlsCmd{},
43-
&secretsCmd{},
4443
}
4544
}
4645

@@ -67,6 +66,7 @@ func main() {
6766
makeShellCmd(),
6867
makeUsersCmd(),
6968
makeConfigSSHCmd(),
69+
makeSecretsCmd(),
7070
}
7171
err = app.Run(os.Args)
7272
if err != nil {

cmd/coder/secrets.go

Lines changed: 119 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,132 @@ import (
77

88
"cdr.dev/coder-cli/internal/entclient"
99
"cdr.dev/coder-cli/internal/x/xtabwriter"
10-
"cdr.dev/coder-cli/internal/x/xvalidate"
1110
"github.com/manifoldco/promptui"
12-
"github.com/spf13/pflag"
11+
"github.com/urfave/cli"
1312
"golang.org/x/xerrors"
1413

1514
"go.coder.com/flog"
16-
17-
"go.coder.com/cli"
1815
)
1916

20-
type secretsCmd struct {
21-
}
22-
23-
func (cmd secretsCmd) Spec() cli.CommandSpec {
24-
return cli.CommandSpec{
25-
Name: "secrets",
26-
Usage: "[subcommand]",
27-
Desc: "interact with secrets",
28-
}
29-
}
30-
31-
func (cmd secretsCmd) Run(fl *pflag.FlagSet) {
32-
exitUsage(fl)
33-
}
34-
35-
func (cmd secretsCmd) RegisterFlags(fl *pflag.FlagSet) {}
36-
37-
func (cmd secretsCmd) Subcommands() []cli.Command {
38-
return []cli.Command{
39-
&listSecretsCmd{},
40-
&viewSecretsCmd{},
41-
&createSecretCmd{},
42-
&deleteSecretsCmd{},
17+
func makeSecretsCmd() cli.Command {
18+
return cli.Command{
19+
Name: "secrets",
20+
Usage: "",
21+
Description: "interact with secrets",
22+
Subcommands: []cli.Command{
23+
{
24+
Name: "ls",
25+
Usage: "",
26+
Description: "",
27+
Action: listSecrets,
28+
},
29+
makeCreateSecret(),
30+
{
31+
Name: "rm",
32+
Usage: "",
33+
Description: "",
34+
Action: removeSecret,
35+
},
36+
{
37+
Name: "view",
38+
Usage: "",
39+
Description: "",
40+
Action: viewSecret,
41+
},
42+
},
43+
Flags: nil,
4344
}
4445
}
4546

46-
type listSecretsCmd struct{}
47+
func makeCreateSecret() cli.Command {
48+
var (
49+
fromFile string
50+
fromLiteral string
51+
fromPrompt bool
52+
description string
53+
)
4754

48-
func (cmd *listSecretsCmd) Spec() cli.CommandSpec {
49-
return cli.CommandSpec{
50-
Name: "ls",
51-
Desc: "list all secrets",
55+
return cli.Command{
56+
Name: "create",
57+
Usage: "",
58+
Description: "",
59+
Before: func(c *cli.Context) error {
60+
if c.Args().First() == "" {
61+
return xerrors.Errorf("[name] is a required field argument")
62+
}
63+
if fromPrompt && (fromLiteral != "" || fromFile != "") {
64+
return xerrors.Errorf("--from-prompt cannot be set along with --from-file or --from-literal")
65+
}
66+
if fromLiteral != "" && fromFile != "" {
67+
return xerrors.Errorf("--from-literal and --from-file cannot both be set")
68+
}
69+
if !fromPrompt && fromFile == "" && fromLiteral == "" {
70+
return xerrors.Errorf("one of [--from-literal, --from-file, --from-prompt] is required")
71+
}
72+
return nil
73+
},
74+
Action: func(c *cli.Context) {
75+
var (
76+
client = requireAuth()
77+
name = c.Args().First()
78+
value string
79+
err error
80+
)
81+
if fromLiteral != "" {
82+
value = fromLiteral
83+
} else if fromFile != "" {
84+
contents, err := ioutil.ReadFile(fromFile)
85+
requireSuccess(err, "failed to read file: %v", err)
86+
value = string(contents)
87+
} else {
88+
prompt := promptui.Prompt{
89+
Label: "value",
90+
Mask: '*',
91+
Validate: func(s string) error {
92+
if len(s) < 1 {
93+
return xerrors.Errorf("a length > 0 is required")
94+
}
95+
return nil
96+
},
97+
}
98+
value, err = prompt.Run()
99+
requireSuccess(err, "failed to prompt for value: %v", err)
100+
}
101+
102+
err = client.InsertSecret(entclient.InsertSecretReq{
103+
Name: name,
104+
Value: value,
105+
Description: description,
106+
})
107+
requireSuccess(err, "failed to insert secret: %v", err)
108+
},
109+
Flags: []cli.Flag{
110+
cli.StringFlag{
111+
Name: "from-file",
112+
Usage: "a file from which to read the value of the secret",
113+
TakesFile: true,
114+
Destination: &fromFile,
115+
},
116+
cli.StringFlag{
117+
Name: "from-literal",
118+
Usage: "the value of the secret",
119+
Destination: &fromLiteral,
120+
},
121+
cli.BoolFlag{
122+
Name: "from-prompt",
123+
Usage: "enter the secret value through a terminal prompt",
124+
Destination: &fromPrompt,
125+
},
126+
cli.StringFlag{
127+
Name: "description",
128+
Usage: "a description of the secret",
129+
Destination: &description,
130+
},
131+
},
52132
}
53133
}
54134

55-
func (cmd *listSecretsCmd) Run(fl *pflag.FlagSet) {
135+
func listSecrets(_ *cli.Context) {
56136
client := requireAuth()
57137

58138
secrets, err := client.Secrets()
@@ -76,25 +156,13 @@ func (cmd *listSecretsCmd) Run(fl *pflag.FlagSet) {
76156
requireSuccess(err, "failed to flush writer: %v", err)
77157
}
78158

79-
func (cmd *listSecretsCmd) RegisterFlags(fl *pflag.FlagSet) {}
80-
81-
type viewSecretsCmd struct{}
82-
83-
func (cmd viewSecretsCmd) Spec() cli.CommandSpec {
84-
return cli.CommandSpec{
85-
Name: "view",
86-
Usage: "[secret_name]",
87-
Desc: "view a secret",
88-
}
89-
}
90-
91-
func (cmd viewSecretsCmd) Run(fl *pflag.FlagSet) {
159+
func viewSecret(c *cli.Context) {
92160
var (
93161
client = requireAuth()
94-
name = fl.Arg(0)
162+
name = c.Args().First()
95163
)
96164
if name == "" {
97-
exitUsage(fl)
165+
flog.Fatal("[name] is a required argument")
98166
}
99167

100168
secret, err := client.SecretByName(name)
@@ -104,99 +172,13 @@ func (cmd viewSecretsCmd) Run(fl *pflag.FlagSet) {
104172
requireSuccess(err, "failed to write: %v", err)
105173
}
106174

107-
type createSecretCmd struct {
108-
description string
109-
fromFile string
110-
fromLiteral string
111-
fromPrompt bool
112-
}
113-
114-
func (cmd *createSecretCmd) Spec() cli.CommandSpec {
115-
return cli.CommandSpec{
116-
Name: "create",
117-
Usage: `[secret_name] [...flags]`,
118-
Desc: "create a new secret",
119-
}
120-
}
121-
122-
func (cmd *createSecretCmd) Validate(fl *pflag.FlagSet) (e []error) {
123-
if cmd.fromPrompt && (cmd.fromLiteral != "" || cmd.fromFile != "") {
124-
e = append(e, xerrors.Errorf("--from-prompt cannot be set along with --from-file or --from-literal"))
125-
}
126-
if cmd.fromLiteral != "" && cmd.fromFile != "" {
127-
e = append(e, xerrors.Errorf("--from-literal and --from-file cannot both be set"))
128-
}
129-
if !cmd.fromPrompt && cmd.fromFile == "" && cmd.fromLiteral == "" {
130-
e = append(e, xerrors.Errorf("one of [--from-literal, --from-file, --from-prompt] is required"))
131-
}
132-
return e
133-
}
134-
135-
func (cmd *createSecretCmd) Run(fl *pflag.FlagSet) {
136-
var (
137-
client = requireAuth()
138-
name = fl.Arg(0)
139-
value string
140-
err error
141-
)
142-
if name == "" {
143-
exitUsage(fl)
144-
}
145-
xvalidate.Validate(fl, cmd)
146-
147-
if cmd.fromLiteral != "" {
148-
value = cmd.fromLiteral
149-
} else if cmd.fromFile != "" {
150-
contents, err := ioutil.ReadFile(cmd.fromFile)
151-
requireSuccess(err, "failed to read file: %v", err)
152-
value = string(contents)
153-
} else {
154-
prompt := promptui.Prompt{
155-
Label: "value",
156-
Mask: '*',
157-
Validate: func(s string) error {
158-
if len(s) < 1 {
159-
return xerrors.Errorf("a length > 0 is required")
160-
}
161-
return nil
162-
},
163-
}
164-
value, err = prompt.Run()
165-
requireSuccess(err, "failed to prompt for value: %v", err)
166-
}
167-
168-
err = client.InsertSecret(entclient.InsertSecretReq{
169-
Name: name,
170-
Value: value,
171-
Description: cmd.description,
172-
})
173-
requireSuccess(err, "failed to insert secret: %v", err)
174-
}
175-
176-
func (cmd *createSecretCmd) RegisterFlags(fl *pflag.FlagSet) {
177-
fl.StringVar(&cmd.fromFile, "from-file", "", "specify a file from which to read the value of the secret")
178-
fl.StringVar(&cmd.fromLiteral, "from-literal", "", "specify the value of the secret")
179-
fl.BoolVar(&cmd.fromPrompt, "from-prompt", false, "specify the value of the secret through a prompt")
180-
fl.StringVar(&cmd.description, "description", "", "specify a description of the secret")
181-
}
182-
183-
type deleteSecretsCmd struct{}
184-
185-
func (cmd *deleteSecretsCmd) Spec() cli.CommandSpec {
186-
return cli.CommandSpec{
187-
Name: "rm",
188-
Usage: "[secret_name]",
189-
Desc: "remove a secret",
190-
}
191-
}
192-
193-
func (cmd *deleteSecretsCmd) Run(fl *pflag.FlagSet) {
175+
func removeSecret(c *cli.Context) {
194176
var (
195177
client = requireAuth()
196-
name = fl.Arg(0)
178+
name = c.Args().First()
197179
)
198180
if name == "" {
199-
exitUsage(fl)
181+
flog.Fatal("[name] is a required argument")
200182
}
201183

202184
err := client.DeleteSecretByName(name)

0 commit comments

Comments
 (0)