Skip to content

Commit e8959cf

Browse files
committed
500 problems remaining...
Pretty up cliui logs
1 parent eeb9500 commit e8959cf

20 files changed

+253
-197
lines changed

cli/agent.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/coder/coder/agent/reaper"
2525
"github.com/coder/coder/buildinfo"
2626
"github.com/coder/coder/cli/clibase"
27-
"github.com/coder/coder/cli/cliflag"
2827
"github.com/coder/coder/codersdk/agentsdk"
2928
)
3029

@@ -208,10 +207,36 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
208207
},
209208
}
210209

211-
cliflag.StringVarP(cmd.Flags(), &auth, "auth", "", "CODER_AGENT_AUTH", "token", "Specify the authentication type to use for the agent")
212-
cliflag.StringVarP(cmd.Flags(), &logDir, "log-dir", "", "CODER_AGENT_LOG_DIR", os.TempDir(), "Specify the location for the agent log files")
213-
cliflag.StringVarP(cmd.Flags(), &pprofAddress, "pprof-address", "", "CODER_AGENT_PPROF_ADDRESS", "127.0.0.1:6060", "The address to serve pprof.")
214-
cliflag.BoolVarP(cmd.Flags(), &noReap, "no-reap", "", "", false, "Do not start a process reaper.")
210+
cmd.Options = clibase.OptionSet{
211+
{
212+
Name: "auth",
213+
Default: "token",
214+
Description: "Specify the authentication type to use for the agent",
215+
Env: "CODER_AGENT_AUTH",
216+
Value: clibase.StringOf(&auth),
217+
},
218+
{
219+
Name: "log-dir",
220+
Default: os.TempDir(),
221+
Description: "Specify the location for the agent log files",
222+
Env: "CODER_AGENT_LOG_DIR",
223+
Value: clibase.StringOf(&logDir),
224+
},
225+
{
226+
Name: "pprof-address",
227+
Default: "127.0.0.1:6060",
228+
Env: "CODER_AGENT_PPROF_ADDRESS",
229+
Value: clibase.StringOf(&pprofAddress),
230+
},
231+
{
232+
Name: "no-reap",
233+
Default: "false",
234+
Env: "",
235+
Description: "Do not start a process reaper.",
236+
Value: clibase.BoolOf(&noReap),
237+
},
238+
}
239+
215240
return cmd
216241
}
217242

cli/clibase/values.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type NoOptDefValuer interface {
2828

2929
type Int64 int64
3030

31+
func Int64Of(i *int64) *Int64 {
32+
return (*Int64)(i)
33+
}
34+
3135
func (i *Int64) Set(s string) error {
3236
ii, err := strconv.ParseInt(s, 10, 64)
3337
*i = Int64(ii)
@@ -48,6 +52,10 @@ func (Int64) Type() string {
4852

4953
type Bool bool
5054

55+
func BoolOf(b *bool) *Bool {
56+
return (*Bool)(b)
57+
}
58+
5159
func (b *Bool) Set(s string) error {
5260
if s == "" {
5361
*b = Bool(false)
@@ -76,6 +84,10 @@ func (Bool) Type() string {
7684

7785
type String string
7886

87+
func StringOf(s *string) *String {
88+
return (*String)(s)
89+
}
90+
7991
func (*String) NoOptDefValue() string {
8092
return ""
8193
}
@@ -102,6 +114,10 @@ var _ pflag.SliceValue = &Strings{}
102114
// Strings is a slice of strings that implements pflag.Value and pflag.SliceValue.
103115
type Strings []string
104116

117+
func StringsOf(ss *[]string) *Strings {
118+
return (*Strings)(ss)
119+
}
120+
105121
func (s *Strings) Append(v string) error {
106122
*s = append(*s, v)
107123
return nil
@@ -152,6 +168,10 @@ func (Strings) Type() string {
152168

153169
type Duration time.Duration
154170

171+
func DurationOf(d *time.Duration) *Duration {
172+
return (*Duration)(d)
173+
}
174+
155175
func (d *Duration) Set(v string) error {
156176
dd, err := time.ParseDuration(v)
157177
*d = Duration(dd)
@@ -185,6 +205,10 @@ func (Duration) Type() string {
185205

186206
type URL url.URL
187207

208+
func URLOf(u *url.URL) *URL {
209+
return (*URL)(u)
210+
}
211+
188212
func (u *URL) Set(v string) error {
189213
uu, err := url.Parse(v)
190214
if err != nil {

cli/cliui/cliui.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ var Styles = struct {
5353
FocusedPrompt: defaultStyles.FocusedPrompt.Foreground(lipgloss.Color("#651fff")),
5454
Fuchsia: defaultStyles.SelectedMenuItem.Copy(),
5555
Logo: defaultStyles.Logo.SetString("Coder"),
56-
Warn: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#ECFD65"}),
57-
Wrap: lipgloss.NewStyle().Width(80),
56+
Warn: lipgloss.NewStyle().Foreground(
57+
lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#ECFD65"},
58+
),
59+
Wrap: lipgloss.NewStyle().Width(80),
5860
}

cli/cliui/log.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,24 @@ import (
1010

1111
// cliMessage provides a human-readable message for CLI errors and messages.
1212
type cliMessage struct {
13-
Level string
1413
Style lipgloss.Style
1514
Header string
15+
Prefix string
1616
Lines []string
1717
}
1818

1919
// String formats the CLI message for consumption by a human.
2020
func (m cliMessage) String() string {
2121
var str strings.Builder
22-
_, _ = fmt.Fprintf(&str, "%s\r\n",
23-
Styles.Bold.Render(m.Header))
22+
23+
if m.Prefix != "" {
24+
_, _ = fmt.Fprintf(&str, "%v", m.Style.Bold(true).Render(m.Prefix))
25+
}
26+
27+
_, _ = fmt.Fprintf(
28+
&str, "%s\r\n",
29+
m.Style.Bold(false).Render(m.Header),
30+
)
2431
for _, line := range m.Lines {
2532
_, _ = fmt.Fprintf(&str, " %s %s\r\n", m.Style.Render("|"), line)
2633
}
@@ -30,8 +37,26 @@ func (m cliMessage) String() string {
3037
// Warn writes a log to the writer provided.
3138
func Warn(wtr io.Writer, header string, lines ...string) {
3239
_, _ = fmt.Fprint(wtr, cliMessage{
33-
Level: "warning",
3440
Style: Styles.Warn,
41+
Prefix: "WARN: ",
42+
Header: header,
43+
Lines: lines,
44+
}.String())
45+
}
46+
47+
// Info writes a log to the writer provided.
48+
func Info(wtr io.Writer, header string, lines ...string) {
49+
_, _ = fmt.Fprint(wtr, cliMessage{
50+
Header: header,
51+
Lines: lines,
52+
}.String())
53+
}
54+
55+
// Error writes a log to the writer provided.
56+
func Error(wtr io.Writer, header string, lines ...string) {
57+
_, _ = fmt.Fprint(wtr, cliMessage{
58+
Style: Styles.Error,
59+
Prefix: "ERROR: ",
3560
Header: header,
3661
Lines: lines,
3762
}.String())

cli/cliui/prompt.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,17 @@ type PromptOptions struct {
2727

2828
const skipPromptFlag = "yes"
2929

30-
func AllowSkipPrompt(inv *clibase.Invokation) {
31-
inv.ParsedFlags().BoolP(skipPromptFlag, "y", false, "Bypass prompts")
30+
// AllowSkipPrompt adds a "yes" flag to the cmd that can be used to skip
31+
// prompts.
32+
func AllowSkipPrompt() clibase.Option {
33+
return clibase.Option{
34+
Name: skipPromptFlag,
35+
Flag: skipPromptFlag,
36+
FlagShorthand: "y",
37+
Description: "Bypass prompts",
38+
Env: "CODER_SKIP_PROMPT",
39+
Value: &clibase.DiscardValue{},
40+
}
3241
}
3342

3443
const (

cli/cliui/prompt_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func TestPrompt(t *testing.T) {
7979
Text: "ShouldNotSeeThis",
8080
IsConfirm: true,
8181
}, func(inv *clibase.Invokation) {
82-
cliui.AllowSkipPrompt(inv)
82+
inv.Command.Options = append(inv.Command.Options, cliui.AllowSkipPrompt())
8383
inv.Args = []string{"-y"}
8484
})
8585
assert.NoError(t, err)

cli/configssh.go

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"golang.org/x/xerrors"
2323

2424
"github.com/coder/coder/cli/clibase"
25-
"github.com/coder/coder/cli/cliflag"
2625
"github.com/coder/coder/cli/cliui"
2726
"github.com/coder/coder/codersdk"
2827
)
@@ -166,7 +165,7 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
166165
if dryRun {
167166
// Print everything except diff to stderr so
168167
// that it's possible to capture the diff.
169-
out = cmd.OutOrStderr()
168+
out = inv.Stderr
170169
}
171170
coderBinary, err := currentBinPath(out)
172171
if err != nil {
@@ -177,7 +176,7 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
177176
return xerrors.Errorf("escape coder binary for ssh failed: %w", err)
178177
}
179178

180-
root := createConfig(cmd)
179+
root := r.createConfig()
181180
escapedGlobalConfig, err := sshConfigExecEscape(string(root))
182181
if err != nil {
183182
return xerrors.Errorf("escape global config for ssh failed: %w", err)
@@ -369,13 +368,49 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
369368
return nil
370369
},
371370
}
372-
cliflag.StringVarP(cmd.Flags(), &sshConfigFile, "ssh-config-file", "", "CODER_SSH_CONFIG_FILE", sshDefaultConfigFileName, "Specifies the path to an SSH config.")
373-
cmd.Flags().StringArrayVarP(&sshConfigOpts.sshOptions, "ssh-option", "o", []string{}, "Specifies additional SSH options to embed in each host stanza.")
374-
cmd.Flags().BoolVarP(&dryRun, "dry-run", "n", false, "Perform a trial run with no changes made, showing a diff at the end.")
375-
cmd.Flags().BoolVarP(&skipProxyCommand, "skip-proxy-command", "", false, "Specifies whether the ProxyCommand option should be skipped. Useful for testing.")
376-
_ = inv.ParsedFlags().MarkHidden("skip-proxy-command")
377-
cliflag.BoolVarP(cmd.Flags(), &usePreviousOpts, "use-previous-options", "", "CODER_SSH_USE_PREVIOUS_OPTIONS", false, "Specifies whether or not to keep options from previous run of config-ssh.")
378-
cliui.AllowSkipPrompt(inv)
371+
372+
cmd.Options = []clibase.Option{
373+
{
374+
Name: "ssh-config-file",
375+
Flag: "ssh-config-file",
376+
Env: "CODER_SSH_CONFIG_FILE",
377+
Default: sshDefaultConfigFileName,
378+
Description: "Specifies the path to an SSH config.",
379+
Value: clibase.StringOf(&sshConfigFile),
380+
},
381+
{
382+
Name: "ssh-config-opts",
383+
Flag: "ssh-config-opts",
384+
FlagShorthand: "o",
385+
Env: "CODER_SSH_CONFIG_OPTS",
386+
Description: "Specifies additional SSH options to embed in each host stanza.",
387+
Value: clibase.StringsOf(&sshConfigOpts.sshOptions),
388+
},
389+
{
390+
Name: "dry-run",
391+
Flag: "dry-run",
392+
FlagShorthand: "n",
393+
Env: "CODER_SSH_DRY_RUN",
394+
Description: "Perform a trial run with no changes made, showing a diff at the end.",
395+
Value: clibase.BoolOf(&dryRun),
396+
},
397+
{
398+
Name: "skip-proxy-command",
399+
Flag: "skip-proxy-command",
400+
Env: "CODER_SSH_SKIP_PROXY_COMMAND",
401+
Description: "Specifies whether the ProxyCommand option should be skipped. Useful for testing.",
402+
Value: clibase.BoolOf(&skipProxyCommand),
403+
Hidden: true,
404+
},
405+
{
406+
Name: "use-previous-options",
407+
Flag: "use-previous-options",
408+
Env: "CODER_SSH_USE_PREVIOUS_OPTIONS",
409+
Description: "Specifies whether or not to keep options from previous run of config-ssh.",
410+
Value: clibase.BoolOf(&usePreviousOpts),
411+
},
412+
cliui.AllowSkipPrompt(),
413+
}
379414

380415
return cmd
381416
}

cli/configssh_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func TestConfigSSH(t *testing.T) {
181181
pty = ptytest.New(t)
182182
// Set HOME because coder config is included from ~/.ssh/coder.
183183
sshCmd.Env = append(sshCmd.Env, fmt.Sprintf("HOME=%s", home))
184-
sshinv.Stderr = pty.Output()
184+
inv.Stderr = pty.Output()
185185
data, err := sshCmd.Output()
186186
require.NoError(t, err)
187187
require.Equal(t, "test", strings.TrimSpace(string(data)))

0 commit comments

Comments
 (0)