-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLI Enhancements #3897
CLI Enhancements #3897
Changes from 32 commits
c14210e
58be122
a1fcb87
e149184
45627d6
ae12135
fa462a4
14e70dd
caae214
e0f96d6
c8cfcb5
d2ba2fe
8f2a229
204180b
2cd9e8e
c9573ea
7ecec64
189f8c9
60184e9
a7225da
2b3f18d
63d4957
53d4534
4ff62dd
3ff53bc
a81c42e
79992f3
07cf36e
7982def
9ca29d3
df07a3d
1583e23
51a07e2
9b62480
d0e35e1
e4ae7ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"sort" | ||
"strings" | ||
|
||
|
@@ -19,29 +20,37 @@ const ( | |
hopeDelim = "♨" | ||
) | ||
|
||
func OutputSecret(ui cli.Ui, format string, secret *api.Secret) int { | ||
return outputWithFormat(ui, format, secret, secret) | ||
type FormatOptions struct { | ||
Format string | ||
} | ||
|
||
func OutputList(ui cli.Ui, format string, secret *api.Secret) int { | ||
return outputWithFormat(ui, format, secret, secret.Data["keys"]) | ||
func OutputSecret(ui cli.Ui, secret *api.Secret) int { | ||
return outputWithFormat(ui, secret, secret) | ||
} | ||
|
||
func outputWithFormat(ui cli.Ui, format string, secret *api.Secret, data interface{}) int { | ||
// If we had a colored UI, pull out the nested ui so we don't add escape | ||
// sequences for outputting json, etc. | ||
colorUI, ok := ui.(*cli.ColoredUi) | ||
if ok { | ||
ui = colorUI.Ui | ||
func OutputList(ui cli.Ui, data interface{}) int { | ||
switch data.(type) { | ||
case *api.Secret: | ||
secret := data.(*api.Secret) | ||
return outputWithFormat(ui, secret, secret.Data["keys"]) | ||
default: | ||
return outputWithFormat(ui, nil, data) | ||
} | ||
} | ||
|
||
func OutputData(ui cli.Ui, data interface{}) int { | ||
return outputWithFormat(ui, nil, data) | ||
} | ||
|
||
formatter, ok := Formatters[strings.ToLower(format)] | ||
func outputWithFormat(ui cli.Ui, secret *api.Secret, data interface{}) int { | ||
formatter, ok := Formatters[Format()] | ||
if !ok { | ||
ui.Error(fmt.Sprintf("Invalid output format: %s", format)) | ||
ui.Error(fmt.Sprintf("Invalid output format: %s", Format())) | ||
return 1 | ||
} | ||
|
||
if err := formatter.Output(ui, secret, data); err != nil { | ||
ui.Error(fmt.Sprintf("Could not output secret: %s", err.Error())) | ||
ui.Error(fmt.Sprintf("Could not parse output: %s", err.Error())) | ||
return 1 | ||
} | ||
return 0 | ||
|
@@ -58,6 +67,14 @@ var Formatters = map[string]Formatter{ | |
"yml": YamlFormatter{}, | ||
} | ||
|
||
func Format() string { | ||
format := os.Getenv(EnvVaultFormat) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we retrieve this as part of an init function instead of doing the envvar lookup each time? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We just got away from init functions in favor of being able to intercept the args earlier in the main run function. This isn't going to be meaningfully slow for interactive uses, is there a reason not to just call this a couple of times? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've experienced |
||
if format == "" { | ||
format = "table" | ||
} | ||
return format | ||
} | ||
|
||
// An output formatter for json output of an object | ||
type JsonFormatter struct{} | ||
|
||
|
@@ -87,19 +104,32 @@ type TableFormatter struct { | |
} | ||
|
||
func (t TableFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) error { | ||
// TODO: this should really use reflection like the other formatters do | ||
if s, ok := data.(*api.Secret); ok { | ||
return t.OutputSecret(ui, s) | ||
switch data.(type) { | ||
case *api.Secret: | ||
return t.OutputSecret(ui, secret) | ||
case []interface{}: | ||
return t.OutputList(ui, secret, data) | ||
case []string: | ||
return t.OutputList(ui, nil, data) | ||
default: | ||
return errors.New("Cannot use the table formatter for this type") | ||
} | ||
if s, ok := data.([]interface{}); ok { | ||
return t.OutputList(ui, secret, s) | ||
} | ||
return errors.New("Cannot use the table formatter for this type") | ||
} | ||
|
||
func (t TableFormatter) OutputList(ui cli.Ui, secret *api.Secret, list []interface{}) error { | ||
func (t TableFormatter) OutputList(ui cli.Ui, secret *api.Secret, data interface{}) error { | ||
t.printWarnings(ui, secret) | ||
|
||
switch data.(type) { | ||
case []interface{}: | ||
case []string: | ||
ui.Output(tableOutput(data.([]string), nil)) | ||
return nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done below. |
||
default: | ||
return errors.New("Error: table formatter cannot output list for this data type") | ||
} | ||
|
||
list := data.([]interface{}) | ||
|
||
if len(list) > 0 { | ||
keys := make([]string, len(list)) | ||
for i, v := range list { | ||
|
@@ -208,7 +238,14 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret *api.Secret) error { | |
return nil | ||
} | ||
|
||
// OutputSealStatus will print *api.SealStatusResponse in the CLI according to the format provided | ||
func OutputSealStatus(ui cli.Ui, client *api.Client, status *api.SealStatusResponse) int { | ||
switch Format() { | ||
case "table": | ||
default: | ||
return OutputData(ui, status) | ||
} | ||
|
||
var sealPrefix string | ||
if status.RecoverySeal { | ||
sealPrefix = "Recovery " | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove this and the var below if we are just using the envvar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to allow it in a flag but not advertise it. Now that you mention autocorrect below, I wonder if it's better to just remove it rather than have people get it autocorrected and then complain that it's not documented. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the code will be a lot simpler if we drop the flag entirely. People are more likely to "never want colored output" that "not want colored output for this specific command", and even in the latter case, they can specify the envvar first.