diff --git a/pkg/config/flag/flagparser.go b/pkg/config/flag/flagparser.go index 5638e7649..5a66ef89a 100644 --- a/pkg/config/flag/flagparser.go +++ b/pkg/config/flag/flagparser.go @@ -3,6 +3,7 @@ package flag import ( "fmt" "reflect" + "regexp" "strings" "github.com/containous/traefik/v2/pkg/config/parser" @@ -80,8 +81,8 @@ func (f *flagSet) parseOne() (bool, error) { return true, nil } - n := strings.ToLower(name) - if f.flagTypes[n] == reflect.Bool || f.flagTypes[n] == reflect.Ptr { + flagType := f.getFlagType(name) + if flagType == reflect.Bool || flagType == reflect.Ptr { f.setValue(name, "true") return true, nil } @@ -111,10 +112,30 @@ func (f *flagSet) setValue(name string, value string) { } v, ok := f.values[key] - if ok && f.flagTypes[strings.ToLower(name)] == reflect.Slice { + if ok && f.getFlagType(name) == reflect.Slice { f.values[key] = v + "," + value return } f.values[key] = value } + +func (f *flagSet) getFlagType(name string) reflect.Kind { + neutral := strings.ToLower(name) + + kind, ok := f.flagTypes[neutral] + if ok { + return kind + } + + for n, k := range f.flagTypes { + if strings.Contains(n, parser.MapNamePlaceholder) { + p := strings.NewReplacer(".", `\.`, parser.MapNamePlaceholder, `([^.]+)`).Replace(n) + if regexp.MustCompile(p).MatchString(neutral) { + return k + } + } + } + + return reflect.Invalid +} diff --git a/pkg/config/flag/flagparser_test.go b/pkg/config/flag/flagparser_test.go index 8c45fdaf5..461dfad70 100644 --- a/pkg/config/flag/flagparser_test.go +++ b/pkg/config/flag/flagparser_test.go @@ -250,7 +250,7 @@ func TestParse(t *testing.T) { }, }, { - desc: "map struct with sub-map case senstitive", + desc: "map struct with sub-map case sensitive", args: []string{"--foo.Name1.bar.name2.value=firstValue", "--foo.naMe1.bar.name2.value=secondValue"}, element: &struct { Foo map[string]struct { @@ -273,6 +273,20 @@ func TestParse(t *testing.T) { "traefik.foo.Name1.bar.name2.value": "secondValue", }, }, + { + desc: "pointer of struct and map without explicit value", + args: []string{"--foo.default.bar.fuu"}, + element: &struct { + Foo map[string]struct { + Bar *struct { + Fuu *struct{ Value string } + } + } + }{}, + expected: map[string]string{ + "traefik.foo.default.bar.fuu": "true", + }, + }, { desc: "slice with several flags 2 and different cases.", args: []string{"--foo", "bar", "--Foo", "baz"},