Fix raw format for other commands, add to docs! (#17730)

* Clarify when -format=raw fails

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Document Vault read's new -format=raw mode

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add raw format to usage, completion

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add missing support for raw format field printing

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Prohibit command execution with wrong formatter

This allows us to restrict the raw formatter to only commands that
understand it; otherwise, when running `vault write -format=raw`, we'd
actually hit the Vault server, but hide the output from the user. By
switching this to a flag-parse time check, we avoid running the rest of
the command if a bad formatter was specified.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
Alexander Scheel
2022-10-28 12:53:23 -04:00
committed by GitHub
parent 057b40d6ae
commit 8ff7aaabc4
6 changed files with 37 additions and 9 deletions

View File

@@ -518,9 +518,10 @@ func (c *BaseCommand) flagSet(bit FlagSetBit) *FlagSets {
Target: &c.flagFormat,
Default: "table",
EnvVar: EnvVaultFormat,
Completion: complete.PredictSet("table", "json", "yaml", "pretty"),
Completion: complete.PredictSet("table", "json", "yaml", "pretty", "raw"),
Usage: `Print the output in the given format. Valid formats
are "table", "json", "yaml", or "pretty".`,
are "table", "json", "yaml", or "pretty". "raw" is allowed
for 'vault read' operations only.`,
})
}
@@ -581,9 +582,14 @@ func (f *FlagSets) Completions() complete.Flags {
return f.completions
}
type (
ParseOptions interface{}
ParseOptionAllowRawFormat bool
)
// Parse parses the given flags, returning any errors.
// Warnings, if any, regarding the arguments format are sent to stdout
func (f *FlagSets) Parse(args []string) error {
func (f *FlagSets) Parse(args []string, opts ...ParseOptions) error {
err := f.mainSet.Parse(args)
warnings := generateFlagWarnings(f.Args())
@@ -591,7 +597,12 @@ func (f *FlagSets) Parse(args []string) error {
f.ui.Warn(warnings)
}
return err
if err != nil {
return err
}
// Now surface any other errors.
return generateFlagErrors(f, opts...)
}
// Parsed reports whether the command-line flags have been parsed.

View File

@@ -322,3 +322,20 @@ func generateFlagWarnings(args []string) string {
return ""
}
}
func generateFlagErrors(f *FlagSets, opts ...ParseOptions) error {
if Format(f.ui) == "raw" {
canUseRaw := false
for _, opt := range opts {
if value, ok := opt.(ParseOptionAllowRawFormat); ok {
canUseRaw = bool(value)
}
}
if !canUseRaw {
return fmt.Errorf("This command does not support the -format=raw option.")
}
}
return nil
}

View File

@@ -132,7 +132,7 @@ type RawFormatter struct{}
func (r RawFormatter) Format(data interface{}) ([]byte, error) {
byte_data, ok := data.([]byte)
if !ok {
return nil, fmt.Errorf("unable to type assert to []byte: %T; please share the command run", data)
return nil, fmt.Errorf("This command does not support the -format=raw option; only `vault read` does.")
}
return byte_data, nil

View File

@@ -59,7 +59,7 @@ func (c *ReadCommand) AutocompleteFlags() complete.Flags {
func (c *ReadCommand) Run(args []string) int {
f := c.Flags()
if err := f.Parse(args); err != nil {
if err := f.Parse(args, ParseOptionAllowRawFormat(true)); err != nil {
c.UI.Error(err.Error())
return 1
}

View File

@@ -104,7 +104,7 @@ func PrintRawField(ui cli.Ui, data interface{}, field string) int {
}
format := Format(ui)
if format == "" || format == "table" {
if format == "" || format == "table" || format == "raw" {
return PrintRaw(ui, fmt.Sprintf("%v", val))
}

View File

@@ -70,8 +70,8 @@ flags](/docs/commands) included on all commands.
will not have a trailing newline making it ideal for piping to other processes.
- `-format` `(string: "table")` - Print the output in the given format. Valid
formats are "table", "json", or "yaml". This can also be specified via the
`VAULT_FORMAT` environment variable.
formats are "table", "json", "yaml", or "raw". This can also be specified
via the `VAULT_FORMAT` environment variable.
For a full list of examples and paths, please see the documentation that
corresponds to the secrets engine in use.