command: discard output from flags package and return errs directly (#22373)
Any command using meta.defaultFlagSet *might* occasionally exit before the flag package's output got written. This caused flag error messages to get lost. This PR discards the flag package output in favor of directly returning the error to the end user.
This commit is contained in:
parent
7938b2994e
commit
c9d62bb2f6
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
|
@ -29,6 +30,7 @@ func (c *ConsoleCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ func (c *FmtCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&c.recursive, "recursive", false, "recursive")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
|
@ -24,6 +25,7 @@ func (c *GetCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&update, "update", false, "update")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ func (c *GraphCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&verbose, "verbose", false, "verbose")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -353,26 +351,7 @@ func (m *Meta) contextOpts() *terraform.ContextOpts {
|
|||
// defaultFlagSet creates a default flag set for commands.
|
||||
func (m *Meta) defaultFlagSet(n string) *flag.FlagSet {
|
||||
f := flag.NewFlagSet(n, flag.ContinueOnError)
|
||||
|
||||
// Create an io.Writer that writes to our Ui properly for errors.
|
||||
// This is kind of a hack, but it does the job. Basically: create
|
||||
// a pipe, use a scanner to break it into lines, and output each line
|
||||
// to the UI. Do this forever.
|
||||
errR, errW := io.Pipe()
|
||||
errScanner := bufio.NewScanner(errR)
|
||||
go func() {
|
||||
// This only needs to be alive long enough to write the help info if
|
||||
// there is a flag error. Kill the scanner after a short duriation to
|
||||
// prevent these from accumulating during tests, and cluttering up the
|
||||
// stack traces.
|
||||
time.AfterFunc(2*time.Second, func() {
|
||||
errW.Close()
|
||||
})
|
||||
for errScanner.Scan() {
|
||||
m.Ui.Error(errScanner.Text())
|
||||
}
|
||||
}()
|
||||
f.SetOutput(errW)
|
||||
f.SetOutput(ioutil.Discard)
|
||||
|
||||
// Set the default Usage to empty
|
||||
f.Usage = func() {}
|
||||
|
|
|
@ -36,6 +36,7 @@ func (c *OutputCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&module, "module", "", "module")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ func (c *ProvidersCommand) Run(args []string) int {
|
|||
cmdFlags := c.Meta.defaultFlagSet("providers")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ func (c *ProvidersSchemaCommand) Run(args []string) int {
|
|||
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ func (c *ShowCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&jsonOutput, "json", false, "produce JSON output")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ func (c *StateListCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&statePath, "state", "", "path")
|
||||
lookupId := cmdFlags.String("id", "", "Restrict output to paths with a resource having the specified ID.")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
args = cmdFlags.Args()
|
||||
|
|
|
@ -36,7 +36,8 @@ func (c *StateMvCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&c.statePath, "state", "", "path")
|
||||
cmdFlags.StringVar(&statePathOut, "state-out", "", "path")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return cli.RunResultHelp
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
args = cmdFlags.Args()
|
||||
if len(args) != 2 {
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/states/statefile"
|
||||
"github.com/hashicorp/terraform/states/statemgr"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// StatePullCommand is a Command implementation that shows a single resource.
|
||||
|
@ -24,7 +23,8 @@ func (c *StatePullCommand) Run(args []string) int {
|
|||
|
||||
cmdFlags := c.Meta.defaultFlagSet("state pull")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return cli.RunResultHelp
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
args = cmdFlags.Args()
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ func (c *StatePushCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&c.Meta.stateLock, "lock", true, "lock state")
|
||||
cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return cli.RunResultHelp
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
args = cmdFlags.Args()
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ func (c *StateRmCommand) Run(args []string) int {
|
|||
cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
|
||||
cmdFlags.StringVar(&c.statePath, "state", "", "path")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return cli.RunResultHelp
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
args = cmdFlags.Args()
|
||||
|
|
|
@ -27,7 +27,8 @@ func (c *StateShowCommand) Run(args []string) int {
|
|||
cmdFlags := c.Meta.defaultFlagSet("state show")
|
||||
cmdFlags.StringVar(&c.Meta.statePath, "state", "", "path")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return cli.RunResultHelp
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
args = cmdFlags.Args()
|
||||
if len(args) != 1 {
|
||||
|
|
|
@ -35,6 +35,7 @@ func (c *TaintCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ func (c *UnlockCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&force, "force", false, "force")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ func (c *UntaintCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ func (c *ValidateCommand) Run(args []string) int {
|
|||
cmdFlags.Var(varFiles, "var-file", "variable file")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
|||
cmdFlags.DurationVar(&stateLockTimeout, "lock-timeout", 0, "lock timeout")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
|
@ -24,6 +25,7 @@ func (c *WorkspaceListCommand) Run(args []string) int {
|
|||
cmdFlags := c.Meta.defaultFlagSet("workspace list")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
|
|||
cmdFlags.StringVar(&statePath, "state", "", "terraform state file")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ func (c *WorkspaceSelectCommand) Run(args []string) int {
|
|||
cmdFlags := c.Meta.defaultFlagSet("workspace select")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/posener/complete"
|
||||
|
@ -19,6 +20,7 @@ func (c *WorkspaceShowCommand) Run(args []string) int {
|
|||
cmdFlags := c.Meta.extendedFlagSet("workspace show")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue