Apply the case of the CLI flags for the configuration
This commit is contained in:
parent
cd164de776
commit
91e63dea47
5 changed files with 174 additions and 43 deletions
|
@ -625,46 +625,62 @@ func Test_execute_configuration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_execute_configuration_file(t *testing.T) {
|
func Test_execute_configuration_file(t *testing.T) {
|
||||||
rootCmd := &Command{
|
testCases := []struct {
|
||||||
Name: "root",
|
desc string
|
||||||
Description: "This is a test",
|
args []string
|
||||||
Configuration: nil,
|
}{
|
||||||
Run: func(_ []string) error {
|
{
|
||||||
return nil
|
desc: "configFile arg in camel case",
|
||||||
|
args: []string{"", "sub1", "--configFile=./fixtures/config.toml"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "configfile arg in lower case",
|
||||||
|
args: []string{"", "sub1", "--configfile=./fixtures/config.toml"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
element := &Yo{
|
for _, test := range testCases {
|
||||||
Fuu: "test",
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
rootCmd := &Command{
|
||||||
|
Name: "root",
|
||||||
|
Description: "This is a test",
|
||||||
|
Configuration: nil,
|
||||||
|
Run: func(_ []string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
element := &Yo{
|
||||||
|
Fuu: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
sub1 := &Command{
|
||||||
|
Name: "sub1",
|
||||||
|
Description: "sub1",
|
||||||
|
Configuration: element,
|
||||||
|
Resources: []ResourceLoader{&FileLoader{}, &FlagLoader{}},
|
||||||
|
Run: func(args []string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := rootCmd.AddCommand(sub1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = execute(rootCmd, test.args, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expected := &Yo{
|
||||||
|
Foo: "bar",
|
||||||
|
Fii: "bir",
|
||||||
|
Fuu: "test",
|
||||||
|
Yi: &Yi{
|
||||||
|
Foo: "foo",
|
||||||
|
Fii: "fii",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, element)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sub1 := &Command{
|
|
||||||
Name: "sub1",
|
|
||||||
Description: "sub1",
|
|
||||||
Configuration: element,
|
|
||||||
Resources: []ResourceLoader{&FileLoader{}, &FlagLoader{}},
|
|
||||||
Run: func(args []string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := rootCmd.AddCommand(sub1)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
args := []string{"", "sub1", "--configFile=./fixtures/config.toml"}
|
|
||||||
|
|
||||||
err = execute(rootCmd, args, true)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
expected := &Yo{
|
|
||||||
Foo: "bar",
|
|
||||||
Fii: "bir",
|
|
||||||
Fuu: "test",
|
|
||||||
Yi: &Yi{
|
|
||||||
Foo: "foo",
|
|
||||||
Fii: "fii",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.Equal(t, expected, element)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_execute_help(t *testing.T) {
|
func Test_execute_help(t *testing.T) {
|
||||||
|
|
|
@ -30,8 +30,15 @@ func (f *FileLoader) Load(args []string, cmd *Command) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
configFileFlag := "traefik.configfile"
|
configFileFlag := "traefik.configfile"
|
||||||
|
if _, ok := ref["traefik.configFile"]; ok {
|
||||||
|
configFileFlag = "traefik.configFile"
|
||||||
|
}
|
||||||
|
|
||||||
if f.ConfigFileFlag != "" {
|
if f.ConfigFileFlag != "" {
|
||||||
configFileFlag = "traefik." + strings.ToLower(f.ConfigFileFlag)
|
configFileFlag = "traefik." + f.ConfigFileFlag
|
||||||
|
if _, ok := ref[strings.ToLower(configFileFlag)]; ok {
|
||||||
|
configFileFlag = "traefik." + strings.ToLower(f.ConfigFileFlag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configFile, err := loadConfigFiles(ref[configFileFlag], cmd.Configuration)
|
configFile, err := loadConfigFiles(ref[configFileFlag], cmd.Configuration)
|
||||||
|
|
|
@ -136,6 +136,20 @@ func TestDecode(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "map string case sensitive",
|
||||||
|
args: []string{"--foo.caseSensitiveName=barBoo"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]string
|
||||||
|
}{},
|
||||||
|
expected: &struct {
|
||||||
|
Foo map[string]string
|
||||||
|
}{
|
||||||
|
Foo: map[string]string{
|
||||||
|
"caseSensitiveName": "barBoo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "map struct",
|
desc: "map struct",
|
||||||
args: []string{"--foo.name.value=bar"},
|
args: []string{"--foo.name.value=bar"},
|
||||||
|
|
|
@ -16,6 +16,7 @@ func Parse(args []string, element interface{}) (map[string]string, error) {
|
||||||
flagTypes: getFlagTypes(element),
|
flagTypes: getFlagTypes(element),
|
||||||
args: args,
|
args: args,
|
||||||
values: make(map[string]string),
|
values: make(map[string]string),
|
||||||
|
keys: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -35,6 +36,7 @@ type flagSet struct {
|
||||||
flagTypes map[string]reflect.Kind
|
flagTypes map[string]reflect.Kind
|
||||||
args []string
|
args []string
|
||||||
values map[string]string
|
values map[string]string
|
||||||
|
keys map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *flagSet) parseOne() (bool, error) {
|
func (f *flagSet) parseOne() (bool, error) {
|
||||||
|
@ -78,7 +80,8 @@ func (f *flagSet) parseOne() (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.flagTypes[name] == reflect.Bool || f.flagTypes[name] == reflect.Ptr {
|
n := strings.ToLower(name)
|
||||||
|
if f.flagTypes[n] == reflect.Bool || f.flagTypes[n] == reflect.Ptr {
|
||||||
f.setValue(name, "true")
|
f.setValue(name, "true")
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -98,13 +101,20 @@ func (f *flagSet) parseOne() (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *flagSet) setValue(name string, value string) {
|
func (f *flagSet) setValue(name string, value string) {
|
||||||
n := strings.ToLower(parser.DefaultRootName + "." + name)
|
srcKey := parser.DefaultRootName + "." + name
|
||||||
v, ok := f.values[n]
|
neutralKey := strings.ToLower(srcKey)
|
||||||
|
|
||||||
if ok && f.flagTypes[name] == reflect.Slice {
|
key, ok := f.keys[neutralKey]
|
||||||
f.values[n] = v + "," + value
|
if !ok {
|
||||||
|
f.keys[neutralKey] = srcKey
|
||||||
|
key = srcKey
|
||||||
|
}
|
||||||
|
|
||||||
|
v, ok := f.values[key]
|
||||||
|
if ok && f.flagTypes[strings.ToLower(name)] == reflect.Slice {
|
||||||
|
f.values[key] = v + "," + value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.values[n] = value
|
f.values[key] = value
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,16 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo": "true",
|
"traefik.foo": "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "bool value capitalized",
|
||||||
|
args: []string{"--Foo"},
|
||||||
|
element: &struct {
|
||||||
|
Foo bool
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.Foo": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "equal",
|
desc: "equal",
|
||||||
args: []string{"--foo=bar"},
|
args: []string{"--foo=bar"},
|
||||||
|
@ -39,6 +49,16 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo": "bar",
|
"traefik.foo": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "equal",
|
||||||
|
args: []string{"--Foo=Bar"},
|
||||||
|
element: &struct {
|
||||||
|
Foo string
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.Foo": "Bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "space separated",
|
desc: "space separated",
|
||||||
args: []string{"--foo", "bar"},
|
args: []string{"--foo", "bar"},
|
||||||
|
@ -49,6 +69,16 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo": "bar",
|
"traefik.foo": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "space separated capitalized",
|
||||||
|
args: []string{"--Foo", "Bar"},
|
||||||
|
element: &struct {
|
||||||
|
Foo string
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.Foo": "Bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "space separated with end of parameter",
|
desc: "space separated with end of parameter",
|
||||||
args: []string{"--foo=bir", "--", "--bar"},
|
args: []string{"--foo=bir", "--", "--bar"},
|
||||||
|
@ -91,6 +121,16 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo.name": "bar",
|
"traefik.foo.name": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "map string capitalized",
|
||||||
|
args: []string{"--foo.Name=Bar"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]string
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo.Name": "Bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "map struct",
|
desc: "map struct",
|
||||||
args: []string{"--foo.name.value=bar"},
|
args: []string{"--foo.name.value=bar"},
|
||||||
|
@ -199,6 +239,50 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo": "true",
|
"traefik.foo": "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "map string case sensitive",
|
||||||
|
args: []string{"--foo.caseSensitiveName=barBoo"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]string
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo.caseSensitiveName": "barBoo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "map struct with sub-map case senstitive",
|
||||||
|
args: []string{"--foo.Name1.bar.name2.value=firstValue", "--foo.naMe1.bar.name2.value=secondValue"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]struct {
|
||||||
|
Bar map[string]struct{ Value string }
|
||||||
|
}
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo.Name1.bar.name2.value": "secondValue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "map struct with sub-map and different case",
|
||||||
|
args: []string{"--foo.Name1.bar.name2.value=firstValue", "--foo.naMe1.bar.name2.value=secondValue"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]struct {
|
||||||
|
Bar map[string]struct{ Value string }
|
||||||
|
}
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo.Name1.bar.name2.value": "secondValue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "slice with several flags 2 and different cases.",
|
||||||
|
args: []string{"--foo", "bar", "--Foo", "baz"},
|
||||||
|
element: &struct {
|
||||||
|
Foo []string
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo": "bar,baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
Loading…
Reference in a new issue