mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
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() {
|
func init() {
|
||||||
Funcs = map[string]lang.Function{
|
Funcs = map[string]lang.Function{
|
||||||
"file": interpolationFuncFile(),
|
"file": interpolationFuncFile(),
|
||||||
"join": interpolationFuncJoin(),
|
"join": interpolationFuncJoin(),
|
||||||
//"lookup": interpolationFuncLookup(),
|
|
||||||
"element": interpolationFuncElement(),
|
"element": interpolationFuncElement(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,22 +58,22 @@ func interpolationFuncJoin() lang.Function {
|
|||||||
|
|
||||||
// interpolationFuncLookup implements the "lookup" function that allows
|
// interpolationFuncLookup implements the "lookup" function that allows
|
||||||
// dynamic lookups of map types within a Terraform configuration.
|
// dynamic lookups of map types within a Terraform configuration.
|
||||||
func interpolationFuncLookup(
|
func interpolationFuncLookup(vs map[string]string) lang.Function {
|
||||||
vs map[string]string, args ...string) (string, error) {
|
return lang.Function{
|
||||||
if len(args) != 2 {
|
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
|
||||||
return "", fmt.Errorf(
|
ReturnType: ast.TypeString,
|
||||||
"lookup expects 2 arguments, got %d", len(args))
|
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, "."))
|
return v, nil
|
||||||
v, ok := vs[k]
|
},
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf(
|
|
||||||
"lookup in '%s' failed to find '%s'",
|
|
||||||
args[0], args[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpolationFuncElement implements the "element" function that allows
|
// interpolationFuncElement implements the "element" function that allows
|
||||||
|
@ -20,163 +20,149 @@ func TestInterpolateFuncFile(t *testing.T) {
|
|||||||
tf.Close()
|
tf.Close()
|
||||||
defer os.Remove(path)
|
defer os.Remove(path)
|
||||||
|
|
||||||
testFunction(t, []testFunctionCase{
|
testFunction(t, testFunctionConfig{
|
||||||
{
|
Cases: []testFunctionCase{
|
||||||
fmt.Sprintf(`${file("%s")}`, path),
|
{
|
||||||
"foo",
|
fmt.Sprintf(`${file("%s")}`, path),
|
||||||
false,
|
"foo",
|
||||||
},
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
// Invalid path
|
// Invalid path
|
||||||
{
|
{
|
||||||
`${file("/i/dont/exist")}`,
|
`${file("/i/dont/exist")}`,
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Too many args
|
// Too many args
|
||||||
{
|
{
|
||||||
`${file("foo", "bar")}`,
|
`${file("foo", "bar")}`,
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInterpolateFuncJoin(t *testing.T) {
|
func TestInterpolateFuncJoin(t *testing.T) {
|
||||||
testFunction(t, []testFunctionCase{
|
testFunction(t, testFunctionConfig{
|
||||||
{
|
Cases: []testFunctionCase{
|
||||||
`${join(",")}`,
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
`${join(",", "foo")}`,
|
|
||||||
"foo",
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO
|
|
||||||
{
|
{
|
||||||
`${join(",", "foo", "bar")}`,
|
`${join(",")}`,
|
||||||
"foo,bar",
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
`${join(",", "foo")}`,
|
||||||
|
"foo",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
/*
|
||||||
fmt.Sprintf(`${join(".", "%s")}`,
|
TODO
|
||||||
fmt.Sprintf(
|
{
|
||||||
"foo%sbar%sbaz",
|
`${join(",", "foo", "bar")}`,
|
||||||
InterpSplitDelim,
|
"foo,bar",
|
||||||
InterpSplitDelim)),
|
false,
|
||||||
"foo.bar.baz",
|
},
|
||||||
false,
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
fmt.Sprintf(`${join(".", "%s")}`,
|
||||||
|
fmt.Sprintf(
|
||||||
|
"foo%sbar%sbaz",
|
||||||
|
InterpSplitDelim,
|
||||||
|
InterpSplitDelim)),
|
||||||
|
"foo.bar.baz",
|
||||||
|
false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func TestInterpolateFuncLookup(t *testing.T) {
|
func TestInterpolateFuncLookup(t *testing.T) {
|
||||||
testFunction(t, []testFunctionCase{
|
testFunction(t, testFunctionConfig{
|
||||||
cases := []struct {
|
Vars: map[string]string{"var.foo.bar": "baz"},
|
||||||
M map[string]string
|
Cases: []testFunctionCase{
|
||||||
Args []string
|
{
|
||||||
Result string
|
`${lookup("foo", "bar")}`,
|
||||||
Error bool
|
"baz",
|
||||||
}{
|
false,
|
||||||
{
|
|
||||||
map[string]string{
|
|
||||||
"var.foo.bar": "baz",
|
|
||||||
},
|
},
|
||||||
[]string{"foo", "bar"},
|
|
||||||
"baz",
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Invalid key
|
// Invalid key
|
||||||
{
|
{
|
||||||
map[string]string{
|
`${lookup("foo", "baz")}`,
|
||||||
"var.foo.bar": "baz",
|
nil,
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
[]string{"foo", "baz"},
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Too many args
|
// Too many args
|
||||||
{
|
{
|
||||||
map[string]string{
|
`${lookup("foo", "bar", "baz")}`,
|
||||||
"var.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) {
|
func TestInterpolateFuncElement(t *testing.T) {
|
||||||
testFunction(t, []testFunctionCase{
|
testFunction(t, testFunctionConfig{
|
||||||
{
|
Cases: []testFunctionCase{
|
||||||
fmt.Sprintf(`${element("%s", "1")}`,
|
{
|
||||||
"foo"+InterpSplitDelim+"baz"),
|
fmt.Sprintf(`${element("%s", "1")}`,
|
||||||
"baz",
|
"foo"+InterpSplitDelim+"baz"),
|
||||||
false,
|
"baz",
|
||||||
},
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
`${element("foo", "0")}`,
|
`${element("foo", "0")}`,
|
||||||
"foo",
|
"foo",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Invalid index should wrap vs. out-of-bounds
|
// Invalid index should wrap vs. out-of-bounds
|
||||||
{
|
{
|
||||||
fmt.Sprintf(`${element("%s", "2")}`,
|
fmt.Sprintf(`${element("%s", "2")}`,
|
||||||
"foo"+InterpSplitDelim+"baz"),
|
"foo"+InterpSplitDelim+"baz"),
|
||||||
"foo",
|
"foo",
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Too many args
|
// Too many args
|
||||||
{
|
{
|
||||||
fmt.Sprintf(`${element("%s", "0", "2")}`,
|
fmt.Sprintf(`${element("%s", "0", "2")}`,
|
||||||
"foo"+InterpSplitDelim+"baz"),
|
"foo"+InterpSplitDelim+"baz"),
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testFunctionConfig struct {
|
||||||
|
Cases []testFunctionCase
|
||||||
|
Vars map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
type testFunctionCase struct {
|
type testFunctionCase struct {
|
||||||
Input string
|
Input string
|
||||||
Result interface{}
|
Result interface{}
|
||||||
Error bool
|
Error bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFunction(t *testing.T, cases []testFunctionCase) {
|
func testFunction(t *testing.T, config testFunctionConfig) {
|
||||||
for i, tc := range cases {
|
for i, tc := range config.Cases {
|
||||||
ast, err := lang.Parse(tc.Input)
|
ast, err := lang.Parse(tc.Input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%d: err: %s", i, err)
|
t.Fatalf("%d: err: %s", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
engine := langEngine(nil)
|
engine := langEngine(config.Vars)
|
||||||
out, _, err := engine.Execute(ast)
|
out, _, err := engine.Execute(ast)
|
||||||
if (err != nil) != tc.Error {
|
if (err != nil) != tc.Error {
|
||||||
t.Fatalf("%d: err: %s", i, err)
|
t.Fatalf("%d: err: %s", i, err)
|
||||||
|
@ -208,10 +208,17 @@ func langEngine(vs map[string]string) *lang.Engine {
|
|||||||
for k, v := range vs {
|
for k, v := range vs {
|
||||||
varMap[k] = lang.Variable{Value: v, Type: ast.TypeString}
|
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{
|
return &lang.Engine{
|
||||||
GlobalScope: &lang.Scope{
|
GlobalScope: &lang.Scope{
|
||||||
VarMap: varMap,
|
VarMap: varMap,
|
||||||
FuncMap: Funcs,
|
FuncMap: funcMap,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user