diff --git a/command/format.go b/command/format.go index 76d018acd..d20e785bf 100644 --- a/command/format.go +++ b/command/format.go @@ -59,6 +59,7 @@ func outputWithFormat(ui cli.Ui, secret *api.Secret, data interface{}) int { type Formatter interface { Output(ui cli.Ui, secret *api.Secret, data interface{}) error + Format(data interface{}) ([]byte, error) } var Formatters = map[string]Formatter{ @@ -87,8 +88,12 @@ func Format(ui cli.Ui) string { // An output formatter for json output of an object type JsonFormatter struct{} +func (j JsonFormatter) Format(data interface{}) ([]byte, error) { + return json.MarshalIndent(data, "", " ") +} + func (j JsonFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) error { - b, err := json.MarshalIndent(data, "", " ") + b, err := j.Format(data) if err != nil { return err } @@ -100,8 +105,12 @@ func (j JsonFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) e type YamlFormatter struct { } +func (y YamlFormatter) Format(data interface{}) ([]byte, error) { + return yaml.Marshal(data) +} + func (y YamlFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) error { - b, err := yaml.Marshal(data) + b, err := y.Format(data) if err == nil { ui.Output(strings.TrimSpace(string(b))) } @@ -112,6 +121,11 @@ func (y YamlFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) e type TableFormatter struct { } +// We don't use this +func (t TableFormatter) Format(data interface{}) ([]byte, error) { + return nil, nil +} + func (t TableFormatter) Output(ui cli.Ui, secret *api.Secret, data interface{}) error { switch data.(type) { case *api.Secret: diff --git a/command/util.go b/command/util.go index f6268d392..04e04fc6a 100644 --- a/command/util.go +++ b/command/util.go @@ -34,7 +34,7 @@ func DefaultTokenHelper() (token.TokenHelper, error) { // RawField extracts the raw field from the given data and returns it as a // string for printing purposes. -func RawField(secret *api.Secret, field string) (string, bool) { +func RawField(secret *api.Secret, field string) (interface{}, bool) { var val interface{} switch { case secret.Auth != nil: @@ -75,24 +75,47 @@ func RawField(secret *api.Secret, field string) (string, bool) { switch field { case "refresh_interval": val = secret.LeaseDuration + case "data": + var ok bool + val, ok = secret.Data["data"] + if !ok { + val = secret.Data + } default: val = secret.Data[field] } } - str := fmt.Sprintf("%v", val) - return str, val != nil + return val, val != nil } // PrintRawField prints raw field from the secret. func PrintRawField(ui cli.Ui, secret *api.Secret, field string) int { - str, ok := RawField(secret, field) + val, ok := RawField(secret, field) if !ok { ui.Error(fmt.Sprintf("Field %q not present in secret", field)) return 1 } - return PrintRaw(ui, str) + format := Format(ui) + if format == "" || format == "table" { + return PrintRaw(ui, fmt.Sprintf("%v", val)) + } + + // Handle specific format flags as best as possible + formatter, ok := Formatters[format] + if !ok { + ui.Error(fmt.Sprintf("Invalid output format: %s", format)) + return 1 + } + + b, err := formatter.Format(val) + if err != nil { + ui.Error(fmt.Sprintf("Error formatting output: %s", err)) + return 1 + } + + return PrintRaw(ui, string(b)) } // PrintRaw prints a raw value to the terminal. If the process is being "piped"