Add ability to append to slice during config file merge

If key ends in "+" the value of the key is appended to previous
values found.  If values are string instead of a slice they are
automatically converted to a slice of one string.

Signed-off-by: Darren Shepherd <darren@rancher.com>
pull/3241/head
Darren Shepherd 4 years ago committed by Brad Davidson
parent 7a10a9971f
commit 8f1a20c0d3

@ -142,9 +142,12 @@ func readConfigFile(file string) (result []string, _ error) {
files = append([]string{file}, files...)
}
keySeen := map[string]bool{}
for i := len(files) - 1; i >= 0; i-- {
file := files[i]
var (
keySeen = map[string]bool{}
keyOrder []string
values = map[string]interface{}{}
)
for _, file := range files {
bytes, err := readConfigFileData(file)
if err != nil {
return nil, err
@ -157,30 +160,58 @@ func readConfigFile(file string) (result []string, _ error) {
for _, i := range data {
k, v := convert.ToString(i.Key), i.Value
if keySeen[k] {
continue
}
keySeen[k] = true
isAppend := strings.HasSuffix(k, "+")
k = strings.TrimSuffix(k, "+")
prefix := "--"
if len(k) == 1 {
prefix = "-"
if !keySeen[k] {
keySeen[k] = true
keyOrder = append(keyOrder, k)
}
if slice, ok := v.([]interface{}); ok {
for _, v := range slice {
result = append(result, prefix+k+"="+convert.ToString(v))
}
if oldValue, ok := values[k]; ok && isAppend {
values[k] = append(toSlice(oldValue), toSlice(v)...)
} else {
str := convert.ToString(v)
result = append(result, prefix+k+"="+str)
values[k] = v
}
}
}
for _, k := range keyOrder {
v := values[k]
prefix := "--"
if len(k) == 1 {
prefix = "-"
}
if slice, ok := v.([]interface{}); ok {
for _, v := range slice {
result = append(result, prefix+k+"="+convert.ToString(v))
}
} else {
str := convert.ToString(v)
result = append(result, prefix+k+"="+str)
}
}
return
}
func toSlice(v interface{}) []interface{} {
switch k := v.(type) {
case string:
return []interface{}{k}
case []interface{}:
return k
default:
str := strings.TrimSpace(convert.ToString(v))
if str == "" {
return nil
}
return []interface{}{str}
}
}
func readConfigFileData(file string) ([]byte, error) {
u, err := url.Parse(file)
if err != nil {

@ -160,6 +160,15 @@ func TestParse(t *testing.T) {
"-c=b",
"--isfalse=false",
"--islast=true",
"--b-string=one",
"--b-string=two",
"--c-slice=one",
"--c-slice=two",
"--c-slice=three",
"--d-slice=three",
"--d-slice=four",
"--e-slice=one",
"--e-slice=two",
}
defParser := Parser{
@ -224,9 +233,17 @@ func TestParse(t *testing.T) {
FlagNames: []string{"-c", "--config"},
DefaultConfig: "missing",
},
input: []string{"before", "server", "before", "-c", "./testdata/data.yaml.d/02-data.yaml", "after"},
output: []string{"before", "server", "--foo-bar=bar-foo", "before", "-c", "./testdata/data.yaml.d/02-data.yaml", "after"},
what: "read single config file",
input: []string{"before", "server", "before", "-c", "./testdata/data.yaml.d/02-data.yaml", "after"},
output: []string{"before", "server",
"--foo-bar=bar-foo",
"--b-string=two",
"--c-slice=three",
"--d-slice=three",
"--d-slice=four",
"--e-slice=one",
"--e-slice=two",
"before", "-c", "./testdata/data.yaml.d/02-data.yaml", "after"},
what: "read single config file",
},
}

@ -4,4 +4,11 @@ a-slice:
- "1.5"
- "2"
- ""
- three
- three
b-string: one
c-slice:
- one
- two
d-slice:
- one
- two

@ -1 +1,10 @@
foo-bar: bar-foo
foo-bar: bar-foo
b-string+: two
c-slice+:
- three
d-slice:
- three
- four
e-slice+:
- one
- two
Loading…
Cancel
Save