-
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 21 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 |
---|---|---|
|
@@ -19,29 +19,55 @@ const ( | |
hopeDelim = "♨" | ||
) | ||
|
||
type FormatOptions struct { | ||
Format string | ||
} | ||
|
||
func OutputSecret(ui cli.Ui, format string, secret *api.Secret) int { | ||
return outputWithFormat(ui, format, secret, secret) | ||
} | ||
|
||
func OutputList(ui cli.Ui, format string, secret *api.Secret) int { | ||
return outputWithFormat(ui, format, secret, secret.Data["keys"]) | ||
func OutputList(ui cli.Ui, format string, data interface{}) int { | ||
switch data.(type) { | ||
case *api.Secret: | ||
secret := data.(*api.Secret) | ||
return outputWithFormat(ui, format, secret, secret.Data["keys"]) | ||
default: | ||
return outputWithFormat(ui, format, nil, data) | ||
} | ||
} | ||
|
||
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 | ||
// OutputWithFormat supports printing arbitrary data under a specified format. | ||
func OutputWithFormat(ui cli.Ui, format string, data interface{}) int { | ||
switch data.(type) { | ||
case *api.Secret: | ||
secret := data.(*api.Secret) | ||
// Best-guess effort that is this a list, so parse out the keys | ||
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. What's the reason for doing this? There could very well be "keys" coming back from various different backends, including k/v. 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. Right, so in that case you output things that are inside 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.
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.
But....why? :-) 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. This is the original OutputList behavior: https://github.com/hashicorp/vault/pull/3897/files#diff-3e4377911a05a6f261016d1d5e1fec91L27 If you just passed in the
Instead of:
|
||
if listVals, ok := secret.Data["keys"]; ok { | ||
return outputWithFormat(ui, format, secret, listVals) | ||
} | ||
return outputWithFormat(ui, format, secret, secret) | ||
default: | ||
return outputWithFormat(ui, format, nil, data) | ||
} | ||
} | ||
|
||
func outputWithFormat(ui cli.Ui, format string, secret *api.Secret, data interface{}) int { | ||
formatter, ok := Formatters[strings.ToLower(format)] | ||
if !ok { | ||
ui.Error(fmt.Sprintf("Invalid output format: %s", format)) | ||
return 1 | ||
} | ||
|
||
// Type-check formatter, and ignore colored UI if it's a non-table output | ||
if _, ok := formatter.(TableFormatter); !ok { | ||
// If we had a colored UI, pull out the nested ui so we don't add escape | ||
// sequences for outputting json, etc. | ||
ui = getBasicUI(ui) | ||
} | ||
|
||
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 | ||
|
@@ -87,19 +113,30 @@ 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) | ||
} | ||
if s, ok := data.([]interface{}); ok { | ||
return t.OutputList(ui, secret, 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") | ||
} | ||
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. |
||
} | ||
|
||
list := data.([]interface{}) | ||
|
||
if len(list) > 0 { | ||
keys := make([]string, len(list)) | ||
for i, v := range list { | ||
|
@@ -208,7 +245,14 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret *api.Secret) error { | |
return nil | ||
} | ||
|
||
func OutputSealStatus(ui cli.Ui, client *api.Client, status *api.SealStatusResponse) int { | ||
// OutputSealStatus will print *api.SealStatusResponse in the CLI according to the format provided | ||
func OutputSealStatus(ui cli.Ui, format string, client *api.Client, status *api.SealStatusResponse) int { | ||
switch format { | ||
case "table": | ||
default: | ||
return OutputWithFormat(ui, format, 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.