better error handling when using interpolate funcs; don't swallow func errors

This commit is contained in:
Megan Marsh 2019-07-08 13:49:14 -07:00
parent a87ce366b3
commit 2bbc3d50d7
2 changed files with 18 additions and 4 deletions

View File

@ -366,9 +366,15 @@ func (c *Core) init() error {
c.variables[k] = renderedV
ctx.UserVariables = c.variables
case ttmp.ExecError:
shouldRetry = true
failedInterpolation = fmt.Sprintf(`"%s": "%s"`, k, v)
continue
castError := err.(ttmp.ExecError)
switch castError.Err.(type) {
case interpolate.ErrVariableNotSet:
shouldRetry = true
failedInterpolation = fmt.Sprintf(`"%s": "%s"; error: %s`, k, v, err)
continue
default:
return err
}
default:
return fmt.Errorf(
// unexpected interpolation error: abort the run

View File

@ -47,6 +47,14 @@ var FuncGens = map[string]FuncGenerator{
"lower": funcGenPrimitive(strings.ToLower),
}
type ErrVariableNotSet struct {
Var string // Name of template.
}
func (e ErrVariableNotSet) Error() string {
return fmt.Sprintf("variable %s not set", e.Var)
}
// FuncGenerator is a function that given a context generates a template
// function for the template.
type FuncGenerator func(*Context) interface{}
@ -168,7 +176,7 @@ func funcGenUser(ctx *Context) interface{} {
// error and retry if we're interpolating UserVariables. But if
// we're elsewhere in the template, just return the empty string.
if !ok {
return "", errors.New(fmt.Sprintf("variable %s not set", k))
return "", ErrVariableNotSet{k}
}
}
return val, nil