From fcc0323fc4f8725d778aa603c081fcab463b74c3 Mon Sep 17 00:00:00 2001 From: GodFather Date: Thu, 28 Sep 2017 23:00:20 -0700 Subject: [PATCH 1/2] Make defaults work with nested env variables ie: ${FOO:-${HOME}/bar} Signed-off-by: GodFather --- config/interpolation.go | 36 ++++++++++++++++++++++------- config/interpolation_test.go | 45 ++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/config/interpolation.go b/config/interpolation.go index 3010e68e3..5abcc544c 100644 --- a/config/interpolation.go +++ b/config/interpolation.go @@ -42,12 +42,16 @@ func parseVariable(line string, pos int, mapping func(string) string) (string, i return mapping(buffer.String()), pos, true } -func parseDefaultValue(line string, pos int) (string, int, bool) { +func parseDefaultValue(line string, pos int, mapping func(string) string) (string, int, bool) { var buffer bytes.Buffer + success := false + replaced := "" + fmt.Printf("INCOMING: %v\n", string(line[pos])) // only skip :, :- and - at the beginning for ; pos < len(line); pos++ { c := line[pos] + fmt.Printf("SKIP: %v\n", string(c)) if c == ':' || c == '-' { continue } @@ -55,13 +59,29 @@ func parseDefaultValue(line string, pos int) (string, int, bool) { } for ; pos < len(line); pos++ { c := line[pos] - if c == '}' { + switch { + case c == '$': + if line[pos-1] != '\\' { + fmt.Printf("NESTED: %v pos: %v\n", string(c), pos) + replaced, pos, success = parseInterpolationExpression(line, pos + 1, mapping) + _, err := buffer.WriteString(replaced) + fmt.Printf("REPLACED: %v pos: %v\n", replaced, pos) + if success == false || err != nil { + return "", 0, false + } + } + case c == '}': + fmt.Printf("ENDIT: %v\n", string(c)) return buffer.String(), pos - 1, true + default: + fmt.Printf("APPEND: %v\n", string(c)) + // err := buffer.WriteByte(c) + if err := buffer.WriteByte(c); err != nil { + return "", pos, false + } + fmt.Printf("APPEND: %v\n", string(c)) } - err := buffer.WriteByte(c) - if err != nil { - return "", pos, false - } + fmt.Printf("BUFFER: %v\n", string(buffer.String())) } return "", 0, false } @@ -71,11 +91,11 @@ func parseVariableWithBraces(line string, pos int, mapping func(string) string) for ; pos < len(line); pos++ { c := line[pos] + fmt.Printf("val: %v\n", string(c)) switch { case c == '}': bufferString := buffer.String() - if bufferString == "" { return "", 0, false } @@ -84,7 +104,7 @@ func parseVariableWithBraces(line string, pos int, mapping func(string) string) buffer.WriteByte(c) case validVariableDefault(c, line, pos): defaultValue := "" - defaultValue, pos, _ = parseDefaultValue(line, pos) + defaultValue, pos, _ = parseDefaultValue(line, pos, mapping) defaultValues[buffer.String()] = defaultValue default: return "", 0, false diff --git a/config/interpolation_test.go b/config/interpolation_test.go index cffdffd13..2c6130097 100644 --- a/config/interpolation_test.go +++ b/config/interpolation_test.go @@ -15,6 +15,7 @@ func testInterpolatedLine(t *testing.T, expectedLine, interpolatedLine string, e return envVariables[s] }) + fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedLine, interpolatedLine) assert.Equal(t, expectedLine, interpolatedLine) } @@ -26,10 +27,25 @@ func testInvalidInterpolatedLine(t *testing.T, line string) { assert.Equal(t, false, success) } -func testInterpolatedDefault(t *testing.T, line string, delim string, expectedVar string, expectedVal string) { - envVar, _ := parseLine(line, func(env string) string { return env }) +func testInterpolatedDefault(t *testing.T, line string, delim string, expectedVar string, expectedVal string, envVariables map[string]string) { + envVar, _ := parseLine(line, func(s string) string { + fmt.Printf("request: %v\n", s) + if val, ok := envVariables[s]; ok { + return val + } + return s + }) + pos := strings.Index(line, delim) - envDefault, _, _ := parseDefaultValue(line, pos) + envDefault, _, _ := parseDefaultValue(line, pos, func(s string) string { + fmt.Printf("request: %v\n", s) + if val, ok := envVariables[s]; ok { + return val + } + return s + }) + fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedVal, envDefault) + fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedVar, envVar) assert.Equal(t, expectedVal, envDefault) assert.Equal(t, expectedVar, envVar) } @@ -45,16 +61,25 @@ func TestParseLine(t *testing.T) { "9aNumber": "WORKED", "a9Number": "WORKED", "defTest": "WORKED", + "test_domain": "127.0.0.1:27017", + "HOME": "/home/foo", + "test_tilde": "~/.home/test", } - testInterpolatedDefault(t, "${defVar:-defVal}", ":-", "defVar", "defVal") - testInterpolatedDefault(t, "${defVar2-defVal2}", "-", "defVar2", "defVal2") - testInterpolatedDefault(t, "${defVar:-def:Val}", ":-", "defVar", "def:Val") - testInterpolatedDefault(t, "${defVar:-def-Val}", ":-", "defVar", "def-Val") + testInterpolatedDefault(t, "${defVar:-defVal}", ":-", "defVar", "defVal", variables) + testInterpolatedDefault(t, "${defVar2-defVal2}", "-", "defVar2", "defVal2", variables) + testInterpolatedDefault(t, "${defVar:-def:Val}", ":-", "defVar", "def:Val", variables) + testInterpolatedDefault(t, "${defVar:-def-Val}", ":-", "defVar", "def-Val", variables) + testInterpolatedDefault(t, "${defVar:-~/foo/bar}", ":-", "defVar", "~/foo/bar", variables) + testInterpolatedDefault(t, "${defVar:-${HOME}/.bar/test}", ":-", "defVar", "/home/foo/.bar/test", variables) + testInterpolatedDefault(t, "${defVar:-127.0.0.1:27017}", ":-", "defVar", "127.0.0.1:27017", variables) testInterpolatedLine(t, "WORKED", "$lower", variables) testInterpolatedLine(t, "WORKED", "${MiXeD}", variables) testInterpolatedLine(t, "WORKED", "${split_VaLue}", variables) + testInterpolatedLine(t, "127.0.0.1:27017", "${test_domain}", variables) + testInterpolatedLine(t, "~/.home/test", "${test_tilde}", variables) + testInterpolatedLine(t, "~/.home/test", "${test_tilde}", variables) // make sure variable name is parsed correctly with default value testInterpolatedLine(t, "WORKED", "${defTest:-sometest}", variables) testInterpolatedLine(t, "WORKED", "${defTest-sometest}", variables) @@ -190,6 +215,8 @@ func TestInterpolate(t *testing.T) { # dictionary item value labels: mylabel: "myvalue==" + domainlable: "127.0.0.1:27017" + tildelabel: "~/.home/test" # unset value hostname: "host-" @@ -207,6 +234,8 @@ func TestInterpolate(t *testing.T) { # dictionary item value labels: mylabel: "${LABEL_VALUE}" + domainlable: "${TEST_DOMAIN}" + tildelabel: "${TILDE_DIR}" # unset value hostname: "host-${UNSET_VALUE}" @@ -215,6 +244,8 @@ func TestInterpolate(t *testing.T) { command: "$${ESCAPED}"`, map[string]string{ "IMAGE": "=busybox", "HOST_PORT": "=", + "TEST_DOMAIN": "127.0.0.1:27017", + "TILDE_DIR": "~/.home/test", "LABEL_VALUE": "myvalue==", }) // same as above but with default values From 628498254cf9da3ab00dad397b64a17d11d65140 Mon Sep 17 00:00:00 2001 From: GodFather Date: Thu, 28 Sep 2017 23:02:38 -0700 Subject: [PATCH 2/2] Removing print statements & formatting Signed-off-by: GodFather --- config/interpolation.go | 12 +----------- config/interpolation_test.go | 5 ----- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/config/interpolation.go b/config/interpolation.go index 5abcc544c..4faa667d6 100644 --- a/config/interpolation.go +++ b/config/interpolation.go @@ -47,11 +47,9 @@ func parseDefaultValue(line string, pos int, mapping func(string) string) (strin success := false replaced := "" - fmt.Printf("INCOMING: %v\n", string(line[pos])) // only skip :, :- and - at the beginning for ; pos < len(line); pos++ { c := line[pos] - fmt.Printf("SKIP: %v\n", string(c)) if c == ':' || c == '-' { continue } @@ -62,26 +60,19 @@ func parseDefaultValue(line string, pos int, mapping func(string) string) (strin switch { case c == '$': if line[pos-1] != '\\' { - fmt.Printf("NESTED: %v pos: %v\n", string(c), pos) - replaced, pos, success = parseInterpolationExpression(line, pos + 1, mapping) + replaced, pos, success = parseInterpolationExpression(line, pos+1, mapping) _, err := buffer.WriteString(replaced) - fmt.Printf("REPLACED: %v pos: %v\n", replaced, pos) if success == false || err != nil { return "", 0, false } } case c == '}': - fmt.Printf("ENDIT: %v\n", string(c)) return buffer.String(), pos - 1, true default: - fmt.Printf("APPEND: %v\n", string(c)) - // err := buffer.WriteByte(c) if err := buffer.WriteByte(c); err != nil { return "", pos, false } - fmt.Printf("APPEND: %v\n", string(c)) } - fmt.Printf("BUFFER: %v\n", string(buffer.String())) } return "", 0, false } @@ -91,7 +82,6 @@ func parseVariableWithBraces(line string, pos int, mapping func(string) string) for ; pos < len(line); pos++ { c := line[pos] - fmt.Printf("val: %v\n", string(c)) switch { case c == '}': diff --git a/config/interpolation_test.go b/config/interpolation_test.go index 2c6130097..798c6ffb4 100644 --- a/config/interpolation_test.go +++ b/config/interpolation_test.go @@ -15,7 +15,6 @@ func testInterpolatedLine(t *testing.T, expectedLine, interpolatedLine string, e return envVariables[s] }) - fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedLine, interpolatedLine) assert.Equal(t, expectedLine, interpolatedLine) } @@ -29,7 +28,6 @@ func testInvalidInterpolatedLine(t *testing.T, line string) { func testInterpolatedDefault(t *testing.T, line string, delim string, expectedVar string, expectedVal string, envVariables map[string]string) { envVar, _ := parseLine(line, func(s string) string { - fmt.Printf("request: %v\n", s) if val, ok := envVariables[s]; ok { return val } @@ -38,14 +36,11 @@ func testInterpolatedDefault(t *testing.T, line string, delim string, expectedVa pos := strings.Index(line, delim) envDefault, _, _ := parseDefaultValue(line, pos, func(s string) string { - fmt.Printf("request: %v\n", s) if val, ok := envVariables[s]; ok { return val } return s }) - fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedVal, envDefault) - fmt.Printf("EXPECTED: %s and ACTUAL: %s\n", expectedVar, envVar) assert.Equal(t, expectedVal, envDefault) assert.Equal(t, expectedVar, envVar) }