Commit 1ca34c4e authored by Matthew Holt's avatar Matthew Holt

Couple fixes for env var replacements and tests

parent 837ee9f0
...@@ -69,9 +69,7 @@ func (p *parser) addresses() error { ...@@ -69,9 +69,7 @@ func (p *parser) addresses() error {
var expectingAnother bool var expectingAnother bool
for { for {
tkn := p.Val() tkn := replaceEnvVars(p.Val())
tkn = getValFromEnv(tkn)
// special case: import directive replaces tokens during parse-time // special case: import directive replaces tokens during parse-time
if tkn == "import" && p.isNewLine() { if tkn == "import" && p.isNewLine() {
...@@ -243,7 +241,7 @@ func (p *parser) directive() error { ...@@ -243,7 +241,7 @@ func (p *parser) directive() error {
} else if p.Val() == "}" && nesting == 0 { } else if p.Val() == "}" && nesting == 0 {
return p.Err("Unexpected '}' because no matching opening brace") return p.Err("Unexpected '}' because no matching opening brace")
} }
p.tokens[p.cursor].text = getValFromEnv(p.tokens[p.cursor].text) p.tokens[p.cursor].text = replaceEnvVars(p.tokens[p.cursor].text)
p.block.Tokens[dir] = append(p.block.Tokens[dir], p.tokens[p.cursor]) p.block.Tokens[dir] = append(p.block.Tokens[dir], p.tokens[p.cursor])
} }
...@@ -306,6 +304,31 @@ func standardAddress(str string) (host, port string, err error) { ...@@ -306,6 +304,31 @@ func standardAddress(str string) (host, port string, err error) {
return return
} }
// replaceEnvVars replaces environment variables that appear in the token
// and understands both the Unix $SYNTAX and Windows %SYNTAX%.
func replaceEnvVars(s string) string {
s = replaceEnvReferences(s, "{%", "%}")
s = replaceEnvReferences(s, "{$", "}")
return s
}
// replaceEnvReferences performs the actual replacement of env variables
// in s, given the placeholder start and placeholder end strings.
func replaceEnvReferences(s, refStart, refEnd string) string {
index := strings.Index(s, refStart)
for index != -1 {
endIndex := strings.Index(s, refEnd)
if endIndex != -1 {
ref := s[index : endIndex+len(refEnd)]
s = strings.Replace(s, ref, os.Getenv(ref[len(refStart):len(ref)-len(refEnd)]), -1)
} else {
return s
}
index = strings.Index(s, refStart)
}
return s
}
type ( type (
// serverBlock associates tokens with a list of addresses // serverBlock associates tokens with a list of addresses
// and groups tokens by directive name. // and groups tokens by directive name.
...@@ -330,26 +353,3 @@ func (sb serverBlock) HostList() []string { ...@@ -330,26 +353,3 @@ func (sb serverBlock) HostList() []string {
} }
return sbHosts return sbHosts
} }
func getValFromEnv(s string) string {
s = replaceEnvReferences(s, "{$", "}")
s = replaceEnvReferences(s, "{%", "%}")
return s
}
func replaceEnvReferences(s, refStart, refEnd string) string {
index := strings.Index(s, refStart)
for index != -1 {
endIndex := strings.Index(s, refEnd)
if endIndex != -1 {
ref := s[index : endIndex+len(refEnd)]
s = strings.Replace(s, ref, os.Getenv(ref[len(refStart):len(ref)-len(refEnd)]), -1)
} else {
return s
}
index = strings.Index(s, refStart)
}
return s
}
...@@ -368,75 +368,76 @@ func TestParseAll(t *testing.T) { ...@@ -368,75 +368,76 @@ func TestParseAll(t *testing.T) {
func TestEnvironmentReplacement(t *testing.T) { func TestEnvironmentReplacement(t *testing.T) {
setupParseTests() setupParseTests()
os.Setenv("MY_PORT", "8080") os.Setenv("PORT", "8080")
os.Setenv("MY_ADDRESS", "servername.com") os.Setenv("ADDRESS", "servername.com")
os.Setenv("MY_ADDRESS2", "127.0.0.1") os.Setenv("FOOBAR", "foobar")
for i, test := range []struct { // basic test; unix-style env vars
input string p := testParser(`{$ADDRESS}`)
addresses [][]address // addresses per server block, in order blocks, _ := p.parseAll()
}{ if actual, expected := blocks[0].Addresses[0].Host, "servername.com"; expected != actual {
{`{$MY_ADDRESS}`, [][]address{ t.Errorf("Expected host to be '%s' but was '%s'", expected, actual)
{{"servername.com", ""}}, }
}},
{`{$MY_ADDRESS}:{$MY_PORT}`, [][]address{ // multiple vars per token
[]address{{"servername.com", "8080"}}, p = testParser(`{$ADDRESS}:{$PORT}`)
}}, blocks, _ = p.parseAll()
if actual, expected := blocks[0].Addresses[0].Host, "servername.com"; expected != actual {
t.Errorf("Expected host to be '%s' but was '%s'", expected, actual)
}
if actual, expected := blocks[0].Addresses[0].Port, "8080"; expected != actual {
t.Errorf("Expected port to be '%s' but was '%s'", expected, actual)
}
{`{$MY_ADDRESS2}:1234 { // windows-style var and unix style in same token
} p = testParser(`{%ADDRESS%}:{$PORT}`)
localhost:{$MY_PORT} { blocks, _ = p.parseAll()
}`, [][]address{ if actual, expected := blocks[0].Addresses[0].Host, "servername.com"; expected != actual {
[]address{{"127.0.0.1", "1234"}}, t.Errorf("Expected host to be '%s' but was '%s'", expected, actual)
[]address{{"localhost", "8080"}}, }
}}, if actual, expected := blocks[0].Addresses[0].Port, "8080"; expected != actual {
t.Errorf("Expected port to be '%s' but was '%s'", expected, actual)
}
{`{%MY_ADDRESS%}`, [][]address{ // reverse order
{{"servername.com", ""}}, p = testParser(`{$ADDRESS}:{%PORT%}`)
}}, blocks, _ = p.parseAll()
if actual, expected := blocks[0].Addresses[0].Host, "servername.com"; expected != actual {
t.Errorf("Expected host to be '%s' but was '%s'", expected, actual)
}
if actual, expected := blocks[0].Addresses[0].Port, "8080"; expected != actual {
t.Errorf("Expected port to be '%s' but was '%s'", expected, actual)
}
{`{%MY_ADDRESS%}:{%MY_PORT%}`, [][]address{ // env var in server block body as argument
[]address{{"servername.com", "8080"}}, p = testParser(":{%PORT%}\ndir1 {$FOOBAR}")
}}, blocks, _ = p.parseAll()
if actual, expected := blocks[0].Addresses[0].Port, "8080"; expected != actual {
t.Errorf("Expected port to be '%s' but was '%s'", expected, actual)
}
if actual, expected := blocks[0].Tokens["dir1"][1].text, "foobar"; expected != actual {
t.Errorf("Expected argument to be '%s' but was '%s'", expected, actual)
}
{`{%MY_ADDRESS2%}:1234 { // combined windows env vars in argument
} p = testParser(":{%PORT%}\ndir1 {%ADDRESS%}/{%FOOBAR%}")
localhost:{%MY_PORT%} { blocks, _ = p.parseAll()
}`, [][]address{ if actual, expected := blocks[0].Tokens["dir1"][1].text, "servername.com/foobar"; expected != actual {
[]address{{"127.0.0.1", "1234"}}, t.Errorf("Expected argument to be '%s' but was '%s'", expected, actual)
[]address{{"localhost", "8080"}}, }
}},
} {
p := testParser(test.input)
blocks, err := p.parseAll()
if err != nil { // malformed env var (windows)
t.Errorf("Test %d: Expected no error, but got: %v", i, err) p = testParser(":1234\ndir1 {%ADDRESS}")
} blocks, _ = p.parseAll()
if actual, expected := blocks[0].Tokens["dir1"][1].text, "{%ADDRESS}"; expected != actual {
t.Errorf("Expected host to be '%s' but was '%s'", expected, actual)
}
if len(blocks) != len(test.addresses) { // malformed (non-existent) env var (unix)
t.Errorf("Test %d: Expected %d server blocks, got %d", p = testParser(`:{$PORT$}`)
i, len(test.addresses), len(blocks)) blocks, _ = p.parseAll()
continue if actual, expected := blocks[0].Addresses[0].Port, ""; expected != actual {
} t.Errorf("Expected port to be '%s' but was '%s'", expected, actual)
for j, block := range blocks {
if len(block.Addresses) != len(test.addresses[j]) {
t.Errorf("Test %d: Expected %d addresses in block %d, got %d",
i, len(test.addresses[j]), j, len(block.Addresses))
continue
}
for k, addr := range block.Addresses {
if addr.Host != test.addresses[j][k].Host {
t.Errorf("Test %d, block %d, address %d: Expected host to be '%s', but was '%s'",
i, j, k, test.addresses[j][k].Host, addr.Host)
}
if addr.Port != test.addresses[j][k].Port {
t.Errorf("Test %d, block %d, address %d: Expected port to be '%s', but was '%s'",
i, j, k, test.addresses[j][k].Port, addr.Port)
}
}
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment