Merge pull request #3598 from hashicorp/issue-3397-error-with-extra-flags

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
pull/3607/merge
Frank Schroeder 2017-10-23 10:47:04 +02:00
commit 5bfb2808f9
No known key found for this signature in database
GPG Key ID: 4D65C6EAEC87DECD
7 changed files with 237 additions and 225 deletions

View File

@ -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 {

View File

@ -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.

View File

@ -1,6 +1,7 @@
package config
import (
"flag"
"reflect"
"strings"
"testing"
@ -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"}},
@ -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()
}

View File

@ -27,7 +27,7 @@ import (
type configTest struct {
desc string
flags []string
args []string
pre, post func()
json, jsontail []string
hcl, hcltail []string
@ -56,7 +56,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
{
desc: "-advertise",
flags: []string{
args: []string{
`-advertise=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -75,7 +75,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-advertise-wan",
flags: []string{
args: []string{
`-advertise-wan=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -91,7 +91,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-advertise and -advertise-wan",
flags: []string{
args: []string{
`-advertise=1.2.3.4`,
`-advertise-wan=5.6.7.8`,
`-data-dir=` + dataDir,
@ -111,7 +111,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-bind",
flags: []string{
args: []string{
`-bind=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -134,7 +134,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-bootstrap",
flags: []string{
args: []string{
`-bootstrap`,
`-server`,
`-data-dir=` + dataDir,
@ -150,7 +150,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-bootstrap-expect",
flags: []string{
args: []string{
`-bootstrap-expect=3`,
`-server`,
`-data-dir=` + dataDir,
@ -166,7 +166,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-client",
flags: []string{
args: []string{
`-client=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -179,21 +179,21 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-data-dir empty",
flags: []string{
args: []string{
`-data-dir=`,
},
err: "data_dir cannot be empty",
},
{
desc: "-data-dir non-directory",
flags: []string{
args: []string{
`-data-dir=runtime_test.go`,
},
err: `data_dir "runtime_test.go" is not a directory`,
},
{
desc: "-datacenter",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -204,7 +204,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-datacenter empty",
flags: []string{
args: []string{
`-datacenter=`,
`-data-dir=` + dataDir,
},
@ -212,7 +212,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-dev",
flags: []string{
args: []string{
`-dev`,
},
patch: func(rt *RuntimeConfig) {
@ -252,7 +252,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-disable-host-node-id",
flags: []string{
args: []string{
`-disable-host-node-id`,
`-data-dir=` + dataDir,
},
@ -263,7 +263,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-disable-keyring-file",
flags: []string{
args: []string{
`-disable-keyring-file`,
`-data-dir=` + dataDir,
},
@ -274,7 +274,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-dns-port",
flags: []string{
args: []string{
`-dns-port=123`,
`-data-dir=` + dataDir,
},
@ -286,7 +286,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-domain",
flags: []string{
args: []string{
`-domain=a`,
`-data-dir=` + dataDir,
},
@ -297,7 +297,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-enable-script-checks",
flags: []string{
args: []string{
`-enable-script-checks`,
`-data-dir=` + dataDir,
},
@ -308,7 +308,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-encrypt",
flags: []string{
args: []string{
`-encrypt=i0P+gFTkLPg0h53eNYjydg==`,
`-data-dir=` + dataDir,
},
@ -319,7 +319,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-http-port",
flags: []string{
args: []string{
`-http-port=123`,
`-data-dir=` + dataDir,
},
@ -331,7 +331,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-join",
flags: []string{
args: []string{
`-join=a`,
`-join=b`,
`-data-dir=` + dataDir,
@ -343,7 +343,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-join-wan",
flags: []string{
args: []string{
`-join-wan=a`,
`-join-wan=b`,
`-data-dir=` + dataDir,
@ -355,7 +355,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-log-level",
flags: []string{
args: []string{
`-log-level=a`,
`-data-dir=` + dataDir,
},
@ -366,7 +366,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-node",
flags: []string{
args: []string{
`-node=a`,
`-data-dir=` + dataDir,
},
@ -377,7 +377,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-node-id",
flags: []string{
args: []string{
`-node-id=a`,
`-data-dir=` + dataDir,
},
@ -388,7 +388,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-node-meta",
flags: []string{
args: []string{
`-node-meta=a:b`,
`-node-meta=c:d`,
`-data-dir=` + dataDir,
@ -400,7 +400,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-non-voting-server",
flags: []string{
args: []string{
`-non-voting-server`,
`-data-dir=` + dataDir,
},
@ -411,7 +411,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-pid-file",
flags: []string{
args: []string{
`-pid-file=a`,
`-data-dir=` + dataDir,
},
@ -422,7 +422,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-protocol",
flags: []string{
args: []string{
`-protocol=1`,
`-data-dir=` + dataDir,
},
@ -433,7 +433,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-raft-protocol",
flags: []string{
args: []string{
`-raft-protocol=1`,
`-data-dir=` + dataDir,
},
@ -444,7 +444,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-recursor",
flags: []string{
args: []string{
`-recursor=1.2.3.4`,
`-recursor=5.6.7.8`,
`-data-dir=` + dataDir,
@ -456,7 +456,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-rejoin",
flags: []string{
args: []string{
`-rejoin`,
`-data-dir=` + dataDir,
},
@ -467,7 +467,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-interval",
flags: []string{
args: []string{
`-retry-interval=5s`,
`-data-dir=` + dataDir,
},
@ -478,7 +478,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-interval-wan",
flags: []string{
args: []string{
`-retry-interval-wan=5s`,
`-data-dir=` + dataDir,
},
@ -489,7 +489,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-join",
flags: []string{
args: []string{
`-retry-join=a`,
`-retry-join=b`,
`-data-dir=` + dataDir,
@ -501,7 +501,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-join-wan",
flags: []string{
args: []string{
`-retry-join-wan=a`,
`-retry-join-wan=b`,
`-data-dir=` + dataDir,
@ -513,7 +513,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-max",
flags: []string{
args: []string{
`-retry-max=1`,
`-data-dir=` + dataDir,
},
@ -524,7 +524,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-retry-max-wan",
flags: []string{
args: []string{
`-retry-max-wan=1`,
`-data-dir=` + dataDir,
},
@ -535,7 +535,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-serf-lan-bind",
flags: []string{
args: []string{
`-serf-lan-bind=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -546,7 +546,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-serf-wan-bind",
flags: []string{
args: []string{
`-serf-wan-bind=1.2.3.4`,
`-data-dir=` + dataDir,
},
@ -557,7 +557,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-server",
flags: []string{
args: []string{
`-server`,
`-data-dir=` + dataDir,
},
@ -570,7 +570,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-syslog",
flags: []string{
args: []string{
`-syslog`,
`-data-dir=` + dataDir,
},
@ -581,7 +581,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-ui",
flags: []string{
args: []string{
`-ui`,
`-data-dir=` + dataDir,
},
@ -592,7 +592,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "-ui-dir",
flags: []string{
args: []string{
`-ui-dir=a`,
`-data-dir=` + dataDir,
},
@ -608,7 +608,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
{
desc: "bind addr any v4",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr":"0.0.0.0" }`},
hcl: []string{`bind_addr = "0.0.0.0"`},
patch: func(rt *RuntimeConfig) {
@ -630,7 +630,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bind addr any v6",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr":"::" }`},
hcl: []string{`bind_addr = "::"`},
patch: func(rt *RuntimeConfig) {
@ -655,7 +655,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bind addr any and advertise set should not detect",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr":"0.0.0.0", "advertise_addr": "1.2.3.4" }`},
hcl: []string{`bind_addr = "0.0.0.0" advertise_addr = "1.2.3.4"`},
patch: func(rt *RuntimeConfig) {
@ -680,7 +680,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client addr and ports == 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr":"0.0.0.0",
"ports":{}
@ -698,7 +698,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client addr and ports < 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr":"0.0.0.0",
"ports": { "dns":-1, "http":-2, "https":-3 }
@ -718,7 +718,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client addr and ports > 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr":"0.0.0.0",
"ports":{ "dns": 1, "http": 2, "https": 3 }
@ -741,7 +741,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
{
desc: "client addr, addresses and ports == 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr":"0.0.0.0",
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3" },
@ -761,7 +761,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client addr, addresses and ports < 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr":"0.0.0.0",
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3" },
@ -783,7 +783,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client addr, addresses and ports",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr": "0.0.0.0",
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3" },
@ -807,7 +807,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client template and ports",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
"ports":{ "dns":1, "http":2, "https":3 }
@ -829,7 +829,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client, address template and ports",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
"addresses": {
@ -861,7 +861,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address lan template",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "advertise_addr": "{{ printf \"1.2.3.4\" }}" }`},
hcl: []string{`advertise_addr = "{{ printf \"1.2.3.4\" }}"`},
patch: func(rt *RuntimeConfig) {
@ -879,7 +879,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address wan template",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "advertise_addr_wan": "{{ printf \"1.2.3.4\" }}" }`},
hcl: []string{`advertise_addr_wan = "{{ printf \"1.2.3.4\" }}"`},
patch: func(rt *RuntimeConfig) {
@ -894,7 +894,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address lan with ports",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"ports": {
"server": 1000,
@ -932,7 +932,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address wan with ports",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{
"ports": {
"server": 1000,
@ -970,7 +970,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "serf bind address lan template",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "serf_lan": "{{ printf \"1.2.3.4\" }}" }`},
hcl: []string{`serf_lan = "{{ printf \"1.2.3.4\" }}"`},
patch: func(rt *RuntimeConfig) {
@ -980,7 +980,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "serf bind address wan template",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "serf_wan": "{{ printf \"1.2.3.4\" }}" }`},
hcl: []string{`serf_wan = "{{ printf \"1.2.3.4\" }}"`},
patch: func(rt *RuntimeConfig) {
@ -990,7 +990,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "dns recursor templates with deduplication",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "recursors": [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] }`},
hcl: []string{`recursors = [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] `},
patch: func(rt *RuntimeConfig) {
@ -1005,7 +1005,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
{
desc: "precedence: merge order",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{
`{
"bootstrap": true,
@ -1077,7 +1077,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
start_join = ["a", "b"]
`,
},
flags: []string{
args: []string{
`-advertise=1.1.1.1`,
`-advertise-wan=2.2.2.2`,
`-bootstrap=false`,
@ -1115,7 +1115,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
//
{
desc: "raft performance scaling",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "performance": { "raft_multiplier": 9} }`},
hcl: []string{`performance = { raft_multiplier=9 }`},
patch: func(rt *RuntimeConfig) {
@ -1132,14 +1132,14 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
{
desc: "invalid input",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`this is not JSON`},
hcl: []string{`*** 0123 this is not HCL`},
err: "Error parsing",
},
{
desc: "datacenter is lower-cased",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "datacenter": "A" }`},
hcl: []string{`datacenter = "A"`},
patch: func(rt *RuntimeConfig) {
@ -1149,7 +1149,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "acl_datacenter is lower-cased",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "acl_datacenter": "A" }`},
hcl: []string{`acl_datacenter = "A"`},
patch: func(rt *RuntimeConfig) {
@ -1159,7 +1159,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "acl_replication_token enables acl replication",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "acl_replication_token": "a" }`},
hcl: []string{`acl_replication_token = "a"`},
patch: func(rt *RuntimeConfig) {
@ -1170,7 +1170,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect fails v4",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "0.0.0.0"}`},
hcl: []string{`bind_addr = "0.0.0.0"`},
privatev4: func() ([]*net.IPAddr, error) {
@ -1180,7 +1180,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect none v4",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "0.0.0.0"}`},
hcl: []string{`bind_addr = "0.0.0.0"`},
privatev4: func() ([]*net.IPAddr, error) {
@ -1190,7 +1190,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect multiple v4",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "0.0.0.0"}`},
hcl: []string{`bind_addr = "0.0.0.0"`},
privatev4: func() ([]*net.IPAddr, error) {
@ -1200,7 +1200,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect fails v6",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "::"}`},
hcl: []string{`bind_addr = "::"`},
publicv6: func() ([]*net.IPAddr, error) {
@ -1210,7 +1210,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect none v6",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "::"}`},
hcl: []string{`bind_addr = "::"`},
publicv6: func() ([]*net.IPAddr, error) {
@ -1220,7 +1220,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise address detect multiple v6",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "::"}`},
hcl: []string{`bind_addr = "::"`},
publicv6: func() ([]*net.IPAddr, error) {
@ -1230,21 +1230,21 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "ae_interval invalid == 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
jsontail: []string{`{ "ae_interval": "0s" }`},
hcltail: []string{`ae_interval = "0s"`},
err: `ae_interval cannot be 0s. Must be positive`,
},
{
desc: "ae_interval invalid < 0",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
jsontail: []string{`{ "ae_interval": "-1s" }`},
hcltail: []string{`ae_interval = "-1s"`},
err: `ae_interval cannot be -1s. Must be positive`,
},
{
desc: "acl_datacenter invalid",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1254,7 +1254,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "autopilot.max_trailing_logs invalid",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1264,28 +1264,28 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bind_addr cannot be empty",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "" }`},
hcl: []string{`bind_addr = ""`},
err: "bind_addr cannot be empty",
},
{
desc: "bind_addr does not allow multiple addresses",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "1.1.1.1 2.2.2.2" }`},
hcl: []string{`bind_addr = "1.1.1.1 2.2.2.2"`},
err: "bind_addr cannot contain multiple addresses",
},
{
desc: "bind_addr cannot be a unix socket",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "bind_addr": "unix:///foo" }`},
hcl: []string{`bind_addr = "unix:///foo"`},
err: "bind_addr cannot be a unix socket",
},
{
desc: "bootstrap without server",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1295,7 +1295,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect without server",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1305,7 +1305,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect invalid",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1315,7 +1315,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect and dev mode",
flags: []string{
args: []string{
`-dev`,
`-datacenter=a`,
`-data-dir=` + dataDir,
@ -1326,7 +1326,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect and bootstrap",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1336,7 +1336,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect=1 equals bootstrap",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "bootstrap_expect": 1, "server": true }`},
@ -1353,7 +1353,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect=2 warning",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "bootstrap_expect": 2, "server": true }`},
@ -1372,7 +1372,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "bootstrap-expect > 2 but even warning",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "bootstrap_expect": 4, "server": true }`},
@ -1391,7 +1391,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client mode sets LeaveOnTerm and SkipLeaveOnInt correctly",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "server": false }`},
@ -1405,7 +1405,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "client does not allow socket",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1415,14 +1415,14 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "datacenter invalid",
flags: []string{`-data-dir=` + dataDir},
args: []string{`-data-dir=` + dataDir},
json: []string{`{ "datacenter": "%" }`},
hcl: []string{`datacenter = "%"`},
err: `datacenter cannot be "%". Please use only [a-z0-9-_]`,
},
{
desc: "dns does not allow socket",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1432,7 +1432,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "ui and ui_dir",
flags: []string{
args: []string{
`-datacenter=a`,
`-data-dir=` + dataDir,
},
@ -1447,7 +1447,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
// to avoid combinatory explosion for tests use 0.0.0.0, :: or [::] but not all of them
{
desc: "advertise_addr any",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "advertise_addr": "0.0.0.0" }`},
@ -1456,7 +1456,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "advertise_addr_wan any",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "advertise_addr_wan": "::" }`},
@ -1465,7 +1465,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "recursors any",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "recursors": ["::"] }`},
@ -1474,7 +1474,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "dns_config.udp_answer_limit invalid",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "dns_config": { "udp_answer_limit": -1 } }`},
@ -1483,7 +1483,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "performance.raft_multiplier < 0",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "performance": { "raft_multiplier": -1 } }`},
@ -1492,7 +1492,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "performance.raft_multiplier == 0",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "performance": { "raft_multiplier": 0 } }`},
@ -1501,7 +1501,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "performance.raft_multiplier > 10",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "performance": { "raft_multiplier": 20 } }`},
@ -1510,7 +1510,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "node_name invalid",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
`-node=`,
},
@ -1519,7 +1519,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "node_meta key too long",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1534,7 +1534,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "node_meta value too long",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1549,7 +1549,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "node_meta too many keys",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1564,7 +1564,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique listeners dns vs http",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1579,7 +1579,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique listeners dns vs https",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1594,7 +1594,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique listeners http vs https",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1609,7 +1609,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique advertise addresses HTTP vs RPC",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1624,7 +1624,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique advertise addresses RPC vs Serf LAN",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1637,7 +1637,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "unique advertise addresses RPC vs Serf WAN",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1650,7 +1650,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "telemetry.prefix_filter cannot be empty",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1666,7 +1666,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "telemetry.prefix_filter must start with + or -",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1684,7 +1684,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "telemetry.enable_deprecated_names adds allow rule for whitelist",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
@ -1702,7 +1702,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "encrypt has invalid key",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "encrypt": "this is not a valid key" }`},
@ -1711,7 +1711,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "encrypt given but LAN keyring exists",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "encrypt": "i0P+gFTkLPg0h53eNYjydg==" }`},
@ -1730,7 +1730,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "encrypt given but WAN keyring exists",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "encrypt": "i0P+gFTkLPg0h53eNYjydg==", "server": true }`},
@ -1752,7 +1752,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "multiple check files",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1773,7 +1773,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "multiple service files",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1794,7 +1794,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
},
{
desc: "translated keys",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{
@ -1886,10 +1886,14 @@ func testConfig(t *testing.T, tests []configTest, dataDir string) {
t.Run(strings.Join(desc, ":"), func(t *testing.T) {
// first parse the flags
flags, err := ParseFlags(tt.flags)
flags := Flags{}
fs := flag.NewFlagSet("", flag.ContinueOnError)
AddFlags(fs, &flags)
err := fs.Parse(tt.args)
if err != nil {
t.Fatalf("ParseFlags failed: %s", err)
}
flags.Args = fs.Args()
// Then create a builder with the flags.
b, err := NewBuilder(flags)

View File

@ -16,7 +16,7 @@ func TestSegments(t *testing.T) {
tests := []configTest{
{
desc: "segment name not in OSS",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "server": true, "segment": "a" }`},
@ -25,7 +25,7 @@ func TestSegments(t *testing.T) {
},
{
desc: "segment port must be set",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "segments":[{ "name":"x" }] }`},
@ -34,7 +34,7 @@ func TestSegments(t *testing.T) {
},
{
desc: "segments not in OSS",
flags: []string{
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{ "segments":[{ "name":"x", "port": 123 }] }`},

View File

@ -90,6 +90,7 @@ func (c *cmd) readConfig() *config.RuntimeConfig {
}
return nil
}
c.flagArgs.Args = c.flags.Args()
b, err := config.NewBuilder(c.flagArgs)
if err != nil {

View File

@ -31,6 +31,10 @@ func TestConfigFail(t *testing.T) {
args: []string{"agent", "-server", "-bind=10.0.0.1", "-datacenter="},
out: "==> datacenter cannot be empty\n",
},
{
args: []string{"agent", "-server", "-bind=10.0.0.1", "-datacenter=foo", "some-other-arg"},
out: "==> config: Unknown extra arguments: [some-other-arg]\n",
},
{
args: []string{"agent", "-server", "-bind=10.0.0.1"},
out: "==> data_dir cannot be empty\n",