config: add lookup function back

This commit is contained in:
Mitchell Hashimoto 2015-01-13 12:06:04 -08:00
parent 49fe0d5c7f
commit 4af4c9e16c
3 changed files with 124 additions and 132 deletions

View File

@ -17,7 +17,6 @@ func init() {
Funcs = map[string]lang.Function{
"file": interpolationFuncFile(),
"join": interpolationFuncJoin(),
//"lookup": interpolationFuncLookup(),
"element": interpolationFuncElement(),
}
}
@ -59,22 +58,22 @@ func interpolationFuncJoin() lang.Function {
// interpolationFuncLookup implements the "lookup" function that allows
// dynamic lookups of map types within a Terraform configuration.
func interpolationFuncLookup(
vs map[string]string, args ...string) (string, error) {
if len(args) != 2 {
return "", fmt.Errorf(
"lookup expects 2 arguments, got %d", len(args))
}
k := fmt.Sprintf("var.%s", strings.Join(args, "."))
func interpolationFuncLookup(vs map[string]string) lang.Function {
return lang.Function{
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
k := fmt.Sprintf("var.%s.%s", args[0].(string), args[1].(string))
v, ok := vs[k]
if !ok {
return "", fmt.Errorf(
"lookup in '%s' failed to find '%s'",
args[0], args[1])
args[0].(string), args[1].(string))
}
return v, nil
},
}
}
// interpolationFuncElement implements the "element" function that allows

View File

@ -20,7 +20,8 @@ func TestInterpolateFuncFile(t *testing.T) {
tf.Close()
defer os.Remove(path)
testFunction(t, []testFunctionCase{
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
{
fmt.Sprintf(`${file("%s")}`, path),
"foo",
@ -40,11 +41,13 @@ func TestInterpolateFuncFile(t *testing.T) {
nil,
true,
},
},
})
}
func TestInterpolateFuncJoin(t *testing.T) {
testFunction(t, []testFunctionCase{
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
{
`${join(",")}`,
nil,
@ -75,63 +78,40 @@ func TestInterpolateFuncJoin(t *testing.T) {
"foo.bar.baz",
false,
},
},
})
}
/*
func TestInterpolateFuncLookup(t *testing.T) {
testFunction(t, []testFunctionCase{
cases := []struct {
M map[string]string
Args []string
Result string
Error bool
}{
testFunction(t, testFunctionConfig{
Vars: map[string]string{"var.foo.bar": "baz"},
Cases: []testFunctionCase{
{
map[string]string{
"var.foo.bar": "baz",
},
[]string{"foo", "bar"},
`${lookup("foo", "bar")}`,
"baz",
false,
},
// Invalid key
{
map[string]string{
"var.foo.bar": "baz",
},
[]string{"foo", "baz"},
"",
`${lookup("foo", "baz")}`,
nil,
true,
},
// Too many args
{
map[string]string{
"var.foo.bar": "baz",
},
[]string{"foo", "bar", "baz"},
"",
`${lookup("foo", "bar", "baz")}`,
nil,
true,
},
}
for i, tc := range cases {
actual, err := interpolationFuncLookup(tc.M, tc.Args...)
if (err != nil) != tc.Error {
t.Fatalf("%d: err: %s", i, err)
}
if actual != tc.Result {
t.Fatalf("%d: bad: %#v", i, actual)
}
}
},
})
}
*/
func TestInterpolateFuncElement(t *testing.T) {
testFunction(t, []testFunctionCase{
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
{
fmt.Sprintf(`${element("%s", "1")}`,
"foo"+InterpSplitDelim+"baz"),
@ -160,23 +140,29 @@ func TestInterpolateFuncElement(t *testing.T) {
nil,
true,
},
},
})
}
type testFunctionConfig struct {
Cases []testFunctionCase
Vars map[string]string
}
type testFunctionCase struct {
Input string
Result interface{}
Error bool
}
func testFunction(t *testing.T, cases []testFunctionCase) {
for i, tc := range cases {
func testFunction(t *testing.T, config testFunctionConfig) {
for i, tc := range config.Cases {
ast, err := lang.Parse(tc.Input)
if err != nil {
t.Fatalf("%d: err: %s", i, err)
}
engine := langEngine(nil)
engine := langEngine(config.Vars)
out, _, err := engine.Execute(ast)
if (err != nil) != tc.Error {
t.Fatalf("%d: err: %s", i, err)

View File

@ -208,10 +208,17 @@ func langEngine(vs map[string]string) *lang.Engine {
for k, v := range vs {
varMap[k] = lang.Variable{Value: v, Type: ast.TypeString}
}
funcMap := make(map[string]lang.Function)
for k, v := range Funcs {
funcMap[k] = v
}
funcMap["lookup"] = interpolationFuncLookup(vs)
return &lang.Engine{
GlobalScope: &lang.Scope{
VarMap: varMap,
FuncMap: Funcs,
FuncMap: funcMap,
},
}
}