Unverified Commit c9d62bb2 authored by Kristin Laemmert's avatar Kristin Laemmert Committed by GitHub
Browse files

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.
parent 7938b299
Showing with 27 additions and 28 deletions
+27 -28
......@@ -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
}
......
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
}
......
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
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment