Skip to content

Commit

Permalink
Merge pull request #3598 from hashicorp/issue-3397-error-with-extra-f…
Browse files Browse the repository at this point in the history
…lags

The `consul agent` command was ignoring extra command line arguments
which can lead to confusion when the user has for example forgotten to
add a dash in front of an argument or is not using an `=` when setting
boolean flags to `true`. `-bootstrap true` is not the same as
`-bootstrap=true`, for example.

Since all command line flags are known and we don't expect unparsed
arguments we can return an error. However, this may make it slightly
more difficult in the future if we ever wanted to have these kinds of
arguments.

Fixes #3397
  • Loading branch information
magiconair committed Oct 23, 2017
2 parents 81917ee + b97ab36 commit 5bfb280
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 225 deletions.
6 changes: 6 additions & 0 deletions agent/config/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ type Builder struct {
// NewBuilder returns a new configuration builder based on the given command
// line flags.
func NewBuilder(flags Flags) (*Builder, error) {
// We expect all flags to be parsed and flags.Args to be empty.
// Therefore, we bail if we find unparsed args.
if len(flags.Args) > 0 {
return nil, fmt.Errorf("config: Unknown extra arguments: %v", flags.Args)
}

newSource := func(name string, v interface{}) Source {
b, err := json.MarshalIndent(v, "", " ")
if err != nil {
Expand Down
12 changes: 2 additions & 10 deletions agent/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,9 @@ type Flags struct {

// HCL contains an arbitrary config in hcl format.
HCL []string
}

// ParseFlag parses the arguments into a Flags struct.
func ParseFlags(args []string) (Flags, error) {
var f Flags
fs := flag.NewFlagSet("agent", flag.ContinueOnError)
AddFlags(fs, &f)
if err := fs.Parse(args); err != nil {
return Flags{}, err
}
return f, nil
// Args contains the remaining unparsed flags.
Args []string
}

// AddFlags adds the command line flags for the agent.
Expand Down
15 changes: 10 additions & 5 deletions agent/config/flags_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"flag"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -35,10 +36,6 @@ func TestParseFlags(t *testing.T) {
args: []string{`-bootstrap=false`},
flags: Flags{Config: Config{Bootstrap: pBool(false)}},
},
{
args: []string{`-bootstrap`, `true`},
flags: Flags{Config: Config{Bootstrap: pBool(true)}},
},
{
args: []string{`-config-file`, `a`, `-config-dir`, `b`, `-config-file`, `c`, `-config-dir`, `d`},
flags: Flags{ConfigFiles: []string{"a", "b", "c", "d"}},
Expand All @@ -59,14 +56,22 @@ func TestParseFlags(t *testing.T) {
args: []string{`-node-meta`, `a:b`, `-node-meta`, `c:d`},
flags: Flags{Config: Config{NodeMeta: map[string]string{"a": "b", "c": "d"}}},
},
{
args: []string{`-bootstrap`, `true`},
flags: Flags{Config: Config{Bootstrap: pBool(true)}, Args: []string{"true"}},
},
}

for _, tt := range tests {
t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
flags, err := ParseFlags(tt.args)
flags := Flags{}
fs := flag.NewFlagSet("", flag.ContinueOnError)
AddFlags(fs, &flags)
err := fs.Parse(tt.args)
if got, want := err, tt.err; !reflect.DeepEqual(got, want) {
t.Fatalf("got error %v want %v", got, want)
}
flags.Args = fs.Args()
if !verify.Values(t, "flag", flags, tt.flags) {
t.FailNow()
}
Expand Down
Loading

0 comments on commit 5bfb280

Please sign in to comment.