config: add lookup function back
This commit is contained in:
parent
49fe0d5c7f
commit
4af4c9e16c
|
@ -15,9 +15,8 @@ var Funcs map[string]lang.Function
|
|||
|
||||
func init() {
|
||||
Funcs = map[string]lang.Function{
|
||||
"file": interpolationFuncFile(),
|
||||
"join": interpolationFuncJoin(),
|
||||
//"lookup": interpolationFuncLookup(),
|
||||
"file": interpolationFuncFile(),
|
||||
"join": interpolationFuncJoin(),
|
||||
"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))
|
||||
}
|
||||
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].(string), args[1].(string))
|
||||
}
|
||||
|
||||
k := fmt.Sprintf("var.%s", strings.Join(args, "."))
|
||||
v, ok := vs[k]
|
||||
if !ok {
|
||||
return "", fmt.Errorf(
|
||||
"lookup in '%s' failed to find '%s'",
|
||||
args[0], args[1])
|
||||
return v, nil
|
||||
},
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// interpolationFuncElement implements the "element" function that allows
|
||||
|
|
|
@ -20,163 +20,149 @@ func TestInterpolateFuncFile(t *testing.T) {
|
|||
tf.Close()
|
||||
defer os.Remove(path)
|
||||
|
||||
testFunction(t, []testFunctionCase{
|
||||
{
|
||||
fmt.Sprintf(`${file("%s")}`, path),
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
testFunction(t, testFunctionConfig{
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
fmt.Sprintf(`${file("%s")}`, path),
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
|
||||
// Invalid path
|
||||
{
|
||||
`${file("/i/dont/exist")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
// Invalid path
|
||||
{
|
||||
`${file("/i/dont/exist")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
// Too many args
|
||||
{
|
||||
`${file("foo", "bar")}`,
|
||||
nil,
|
||||
true,
|
||||
// Too many args
|
||||
{
|
||||
`${file("foo", "bar")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestInterpolateFuncJoin(t *testing.T) {
|
||||
testFunction(t, []testFunctionCase{
|
||||
{
|
||||
`${join(",")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
`${join(",", "foo")}`,
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
|
||||
/*
|
||||
TODO
|
||||
testFunction(t, testFunctionConfig{
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
`${join(",", "foo", "bar")}`,
|
||||
"foo,bar",
|
||||
`${join(",")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
`${join(",", "foo")}`,
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
*/
|
||||
|
||||
{
|
||||
fmt.Sprintf(`${join(".", "%s")}`,
|
||||
fmt.Sprintf(
|
||||
"foo%sbar%sbaz",
|
||||
InterpSplitDelim,
|
||||
InterpSplitDelim)),
|
||||
"foo.bar.baz",
|
||||
false,
|
||||
/*
|
||||
TODO
|
||||
{
|
||||
`${join(",", "foo", "bar")}`,
|
||||
"foo,bar",
|
||||
false,
|
||||
},
|
||||
*/
|
||||
|
||||
{
|
||||
fmt.Sprintf(`${join(".", "%s")}`,
|
||||
fmt.Sprintf(
|
||||
"foo%sbar%sbaz",
|
||||
InterpSplitDelim,
|
||||
InterpSplitDelim)),
|
||||
"foo.bar.baz",
|
||||
false,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
func TestInterpolateFuncLookup(t *testing.T) {
|
||||
testFunction(t, []testFunctionCase{
|
||||
cases := []struct {
|
||||
M map[string]string
|
||||
Args []string
|
||||
Result string
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
map[string]string{
|
||||
"var.foo.bar": "baz",
|
||||
testFunction(t, testFunctionConfig{
|
||||
Vars: map[string]string{"var.foo.bar": "baz"},
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
`${lookup("foo", "bar")}`,
|
||||
"baz",
|
||||
false,
|
||||
},
|
||||
[]string{"foo", "bar"},
|
||||
"baz",
|
||||
false,
|
||||
},
|
||||
|
||||
// Invalid key
|
||||
{
|
||||
map[string]string{
|
||||
"var.foo.bar": "baz",
|
||||
// Invalid key
|
||||
{
|
||||
`${lookup("foo", "baz")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
[]string{"foo", "baz"},
|
||||
"",
|
||||
true,
|
||||
},
|
||||
|
||||
// Too many args
|
||||
{
|
||||
map[string]string{
|
||||
"var.foo.bar": "baz",
|
||||
// Too many args
|
||||
{
|
||||
`${lookup("foo", "bar", "baz")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
[]string{"foo", "bar", "baz"},
|
||||
"",
|
||||
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{
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "1")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
"baz",
|
||||
false,
|
||||
},
|
||||
testFunction(t, testFunctionConfig{
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "1")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
"baz",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
`${element("foo", "0")}`,
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${element("foo", "0")}`,
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
|
||||
// Invalid index should wrap vs. out-of-bounds
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "2")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
// Invalid index should wrap vs. out-of-bounds
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "2")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
|
||||
// Too many args
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "0", "2")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
nil,
|
||||
true,
|
||||
// Too many args
|
||||
{
|
||||
fmt.Sprintf(`${element("%s", "0", "2")}`,
|
||||
"foo"+InterpSplitDelim+"baz"),
|
||||
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)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue