Show parse errors from looked up env vars

Signed-off-by: Waldemar Quevedo <wally@synadia.com>
This commit is contained in:
Waldemar Quevedo
2019-01-31 12:21:07 -08:00
parent 36b902675f
commit 457c442198
2 changed files with 59 additions and 21 deletions

View File

@@ -299,25 +299,30 @@ func (p *parser) processItem(it item, fp string) error {
p.popContext() p.popContext()
setValue(it, array) setValue(it, array)
case itemVariable: case itemVariable:
if value, ok := p.lookupVariable(it.val); ok { value, found, err := p.lookupVariable(it.val)
if p.pedantic { if err != nil {
switch tk := value.(type) { return fmt.Errorf("variable reference for '%s' on line %d could not be parsed: %s",
case *token: it.val, it.line, err)
// Mark the looked up variable as used, and make }
// the variable reference become handled as a token. if !found {
tk.usedVariable = true
p.setValue(&token{it, tk.Value(), false, fp})
default:
// Special case to add position context to bcrypt references.
p.setValue(&token{it, value, false, fp})
}
} else {
p.setValue(value)
}
} else {
return fmt.Errorf("variable reference for '%s' on line %d can not be found", return fmt.Errorf("variable reference for '%s' on line %d can not be found",
it.val, it.line) it.val, it.line)
} }
if p.pedantic {
switch tk := value.(type) {
case *token:
// Mark the looked up variable as used, and make
// the variable reference become handled as a token.
tk.usedVariable = true
p.setValue(&token{it, tk.Value(), false, fp})
default:
// Special case to add position context to bcrypt references.
p.setValue(&token{it, value, false, fp})
}
} else {
p.setValue(value)
}
case itemInclude: case itemInclude:
var ( var (
m map[string]interface{} m map[string]interface{}
@@ -358,10 +363,10 @@ const bcryptPrefix = "2a$"
// ignore array contexts and only process the map contexts.. // ignore array contexts and only process the map contexts..
// //
// Returns true for ok if it finds something, similar to map. // Returns true for ok if it finds something, similar to map.
func (p *parser) lookupVariable(varReference string) (interface{}, bool) { func (p *parser) lookupVariable(varReference string) (interface{}, bool, error) {
// Do special check to see if it is a raw bcrypt string. // Do special check to see if it is a raw bcrypt string.
if strings.HasPrefix(varReference, bcryptPrefix) { if strings.HasPrefix(varReference, bcryptPrefix) {
return "$" + varReference, true return "$" + varReference, true, nil
} }
// Loop through contexts currently on the stack. // Loop through contexts currently on the stack.
@@ -370,7 +375,7 @@ func (p *parser) lookupVariable(varReference string) (interface{}, bool) {
// Process if it is a map context // Process if it is a map context
if m, ok := ctx.(map[string]interface{}); ok { if m, ok := ctx.(map[string]interface{}); ok {
if v, ok := m[varReference]; ok { if v, ok := m[varReference]; ok {
return v, ok return v, ok, nil
} }
} }
} }
@@ -381,10 +386,12 @@ func (p *parser) lookupVariable(varReference string) (interface{}, bool) {
// Everything we get here will be a string value, so we need to process as a parser would. // Everything we get here will be a string value, so we need to process as a parser would.
if vmap, err := Parse(fmt.Sprintf("%s=%s", pkey, vStr)); err == nil { if vmap, err := Parse(fmt.Sprintf("%s=%s", pkey, vStr)); err == nil {
v, ok := vmap[pkey] v, ok := vmap[pkey]
return v, ok return v, ok, nil
} else {
return nil, false, err
} }
} }
return nil, false return nil, false, nil
} }
func (p *parser) setValue(val interface{}) { func (p *parser) setValue(val interface{}) {

View File

@@ -101,6 +101,37 @@ func TestEnvVariable(t *testing.T) {
test(t, fmt.Sprintf("foo = $%s", evar), ex) test(t, fmt.Sprintf("foo = $%s", evar), ex)
} }
func TestEnvVariableString(t *testing.T) {
ex := map[string]interface{}{
"foo": "xyz",
}
evar := "__UNIQ22__"
os.Setenv(evar, "xyz")
defer os.Unsetenv(evar)
test(t, fmt.Sprintf("foo = $%s", evar), ex)
}
func TestEnvVariableStringStartingWithNumber(t *testing.T) {
evar := "__UNIQ22__"
os.Setenv(evar, "3xyz")
defer os.Unsetenv(evar)
_, err := Parse("foo = $%s")
if err == nil {
t.Fatalf("Expected err not being able to process string: %v\n", err)
}
}
func TestEnvVariableStringStartingWithNumberUsingQuotes(t *testing.T) {
ex := map[string]interface{}{
"foo": "3xyz",
}
evar := "__UNIQ22__"
os.Setenv(evar, "'3xyz'")
defer os.Unsetenv(evar)
test(t, fmt.Sprintf("foo = $%s", evar), ex)
}
func TestBcryptVariable(t *testing.T) { func TestBcryptVariable(t *testing.T) {
ex := map[string]interface{}{ ex := map[string]interface{}{
"password": "$2a$11$ooo", "password": "$2a$11$ooo",