Skip to content

Commit 6a136dc

Browse files
author
Bruno de Queiroz
committed
fix: adjusting parsing of flags when the output is a generic map[string]string and the key contains '.'
1 parent d116c5c commit 6a136dc

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

flag/flag_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,51 @@ func TestDecode(t *testing.T) {
150150
},
151151
},
152152
},
153+
{
154+
desc: "map string with '.' in key",
155+
args: []string{"--foo.name.value=bar"},
156+
element: &struct {
157+
Foo map[string]string
158+
}{},
159+
expected: &struct {
160+
Foo map[string]string
161+
}{
162+
Foo: map[string]string{
163+
"name.value": "bar",
164+
},
165+
},
166+
},
167+
{
168+
desc: "map string with '.' in key and multiple entries",
169+
args: []string{"--foo.name.value=bar", "--foo.name.value2=bar2"},
170+
element: &struct {
171+
Foo map[string]string
172+
}{},
173+
expected: &struct {
174+
Foo map[string]string
175+
}{
176+
Foo: map[string]string{
177+
"name.value": "bar",
178+
"name.value2": "bar2",
179+
},
180+
},
181+
},
182+
{
183+
desc: "map string with '.' in key and multiple mixed entries",
184+
args: []string{"--foo.name.value=bar", "--foo.name.value2=bar2", "--foo.name2=bar3"},
185+
element: &struct {
186+
Foo map[string]string
187+
}{},
188+
expected: &struct {
189+
Foo map[string]string
190+
}{
191+
Foo: map[string]string{
192+
"name.value": "bar",
193+
"name.value2": "bar2",
194+
"name2": "bar3",
195+
},
196+
},
197+
},
153198
{
154199
desc: "map struct",
155200
args: []string{"--foo.name.value=bar"},

flag/flagparser_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,39 @@ func TestParse(t *testing.T) {
131131
"traefik.foo.Name": "Bar",
132132
},
133133
},
134+
{
135+
desc: "map string with '.' in key",
136+
args: []string{"--foo.name.value=bar"},
137+
element: &struct {
138+
Foo map[string]string
139+
}{},
140+
expected: map[string]string{
141+
"traefik.foo.name.value": "bar",
142+
},
143+
},
144+
{
145+
desc: "map string with '.' in key and multiple entries",
146+
args: []string{"--foo.name.value=bar", "--foo.name2.value2=baz"},
147+
element: &struct {
148+
Foo map[string]string
149+
}{},
150+
expected: map[string]string{
151+
"traefik.foo.name.value": "bar",
152+
"traefik.foo.name2.value2": "baz",
153+
},
154+
},
155+
{
156+
desc: "map string with '.' in key and multiple mixed entries",
157+
args: []string{"--foo.name.value=bar", "--foo.name2.value2=baz", "--foo.name3=bay"},
158+
element: &struct {
159+
Foo map[string]string
160+
}{},
161+
expected: map[string]string{
162+
"traefik.foo.name.value": "bar",
163+
"traefik.foo.name2.value2": "baz",
164+
"traefik.foo.name3": "bay",
165+
},
166+
},
134167
{
135168
desc: "map struct",
136169
args: []string{"--foo.name.value=bar"},

parser/element_fill.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,17 @@ func (f filler) setSliceAsStruct(field reflect.Value, node *Node) error {
291291
return nil
292292
}
293293

294+
func (f filler) fillRecursiveAsString(parent string, node *Node, field reflect.Value) {
295+
if len(node.Children) == 0 {
296+
field.SetMapIndex(reflect.ValueOf(parent), reflect.ValueOf(node.Value))
297+
return
298+
}
299+
300+
for _, child := range node.Children {
301+
f.fillRecursiveAsString(parent+"."+child.Name, child, field)
302+
}
303+
}
304+
294305
func (f filler) setMap(field reflect.Value, node *Node) error {
295306
if field.IsNil() {
296307
field.Set(reflect.MakeMap(field.Type()))
@@ -312,6 +323,19 @@ func (f filler) setMap(field reflect.Value, node *Node) error {
312323
return nil
313324
}
314325

326+
if field.Type().Elem().Kind() == reflect.String {
327+
for _, child := range node.Children {
328+
if len(child.Children) > 0 {
329+
f.fillRecursiveAsString(child.Name, child, field)
330+
} else {
331+
field.SetMapIndex(reflect.ValueOf(child.Name), reflect.ValueOf(child.Value))
332+
}
333+
334+
}
335+
336+
return nil
337+
}
338+
315339
for _, child := range node.Children {
316340
ptrValue := reflect.New(reflect.PointerTo(field.Type().Elem()))
317341

parser/element_fill_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,97 @@ func TestFill(t *testing.T) {
692692
},
693693
},
694694
},
695+
{
696+
desc: "map string with key containing '.'",
697+
node: &Node{
698+
Name: "traefik",
699+
Kind: reflect.Struct,
700+
Children: []*Node{
701+
{
702+
Name: "Foo",
703+
FieldName: "Foo",
704+
Kind: reflect.Map,
705+
Children: []*Node{
706+
{Name: "name", Kind: reflect.Map, Children: []*Node{{Name: "value", Value: "hii", Kind: reflect.String}}},
707+
},
708+
},
709+
},
710+
},
711+
element: &struct {
712+
Foo map[string]string
713+
}{},
714+
expected: expected{
715+
element: &struct {
716+
Foo map[string]string
717+
}{
718+
Foo: map[string]string{
719+
"name.value": "hii",
720+
},
721+
},
722+
},
723+
},
724+
{
725+
desc: "map string with keys containing '.' and multiple entries",
726+
node: &Node{
727+
Name: "traefik",
728+
Kind: reflect.Struct,
729+
Children: []*Node{
730+
{
731+
Name: "Foo",
732+
FieldName: "Foo",
733+
Kind: reflect.Map,
734+
Children: []*Node{
735+
{Name: "name1", Kind: reflect.Map, Children: []*Node{{Name: "value", Value: "hii", Kind: reflect.String}, {Name: "value2", Value: "hii", Kind: reflect.String}}},
736+
},
737+
},
738+
},
739+
},
740+
element: &struct {
741+
Foo map[string]string
742+
}{},
743+
expected: expected{
744+
element: &struct {
745+
Foo map[string]string
746+
}{
747+
Foo: map[string]string{
748+
"name1.value": "hii",
749+
"name1.value2": "hii",
750+
},
751+
},
752+
},
753+
},
754+
{
755+
desc: "map string with keys containing '.' and multiple mixed entries",
756+
node: &Node{
757+
Name: "traefik",
758+
Kind: reflect.Struct,
759+
Children: []*Node{
760+
{
761+
Name: "Foo",
762+
FieldName: "Foo",
763+
Kind: reflect.Map,
764+
Children: []*Node{
765+
{Name: "name1", Kind: reflect.Map, Children: []*Node{{Name: "value", Value: "hii", Kind: reflect.String}, {Name: "value2", Value: "hii", Kind: reflect.String}}},
766+
{Name: "name2", Kind: reflect.String, Value: "hii"},
767+
},
768+
},
769+
},
770+
},
771+
element: &struct {
772+
Foo map[string]string
773+
}{},
774+
expected: expected{
775+
element: &struct {
776+
Foo map[string]string
777+
}{
778+
Foo: map[string]string{
779+
"name1.value": "hii",
780+
"name1.value2": "hii",
781+
"name2": "hii",
782+
},
783+
},
784+
},
785+
},
695786
{
696787
desc: "map struct",
697788
node: &Node{

0 commit comments

Comments
 (0)