terraform/config/interpolate_walk_test.go

264 lines
4.6 KiB
Go

package config
import (
"reflect"
"testing"
"github.com/mitchellh/reflectwalk"
)
func TestInterpolationWalker_detect(t *testing.T) {
cases := []struct {
Input interface{}
Result []Interpolation
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
Result: nil,
},
{
Input: map[string]interface{}{
"foo": "${var.foo}",
},
Result: []Interpolation{
&VariableInterpolation{
Variable: &UserVariable{
Name: "foo",
key: "var.foo",
},
},
},
},
{
Input: map[string]interface{}{
"foo": "${aws_instance.foo.*.num}",
},
Result: []Interpolation{
&VariableInterpolation{
Variable: &ResourceVariable{
Type: "aws_instance",
Name: "foo",
Field: "num",
Multi: true,
Index: -1,
key: "aws_instance.foo.*.num",
},
},
},
},
{
Input: map[string]interface{}{
"foo": "${lookup(var.foo)}",
},
Result: []Interpolation{
&FunctionInterpolation{
Func: nil,
Args: []Interpolation{
&VariableInterpolation{
Variable: &UserVariable{
Name: "foo",
key: "var.foo",
},
},
},
},
},
},
{
Input: map[string]interface{}{
"foo": `${file("test.txt")}`,
},
Result: []Interpolation{
&FunctionInterpolation{
Func: nil,
Args: []Interpolation{
&LiteralInterpolation{
Literal: "test.txt",
},
},
},
},
},
{
Input: map[string]interface{}{
"foo": `${file("foo/bar.txt")}`,
},
Result: []Interpolation{
&FunctionInterpolation{
Func: nil,
Args: []Interpolation{
&LiteralInterpolation{
Literal: "foo/bar.txt",
},
},
},
},
},
{
Input: map[string]interface{}{
"foo": `${join(",", foo.bar.*.id)}`,
},
Result: []Interpolation{
&FunctionInterpolation{
Func: nil,
Args: []Interpolation{
&LiteralInterpolation{
Literal: ",",
},
&VariableInterpolation{
Variable: &ResourceVariable{
Type: "foo",
Name: "bar",
Field: "id",
Multi: true,
Index: -1,
key: "foo.bar.*.id",
},
},
},
},
},
},
{
Input: map[string]interface{}{
"foo": `${concat("localhost", ":8080")}`,
},
Result: []Interpolation{
&FunctionInterpolation{
Func: nil,
Args: []Interpolation{
&LiteralInterpolation{
Literal: "localhost",
},
&LiteralInterpolation{
Literal: ":8080",
},
},
},
},
},
}
for i, tc := range cases {
var actual []Interpolation
detectFn := func(i Interpolation) (string, error) {
actual = append(actual, i)
return "", nil
}
w := &interpolationWalker{F: detectFn}
if err := reflectwalk.Walk(tc.Input, w); err != nil {
t.Fatalf("err: %s", err)
}
for _, a := range actual {
// This is jank, but reflect.DeepEqual never has functions
// being the same.
if f, ok := a.(*FunctionInterpolation); ok {
f.Func = nil
}
}
if !reflect.DeepEqual(actual, tc.Result) {
t.Fatalf("%d: bad:\n\n%#v", i, actual)
}
}
}
func TestInterpolationWalker_replace(t *testing.T) {
cases := []struct {
Input interface{}
Output interface{}
Value string
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
Output: map[string]interface{}{
"foo": "$${var.foo}",
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": "hello, ${var.foo}",
},
Output: map[string]interface{}{
"foo": "hello, bar",
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": map[string]interface{}{
"${var.foo}": "bar",
},
},
Output: map[string]interface{}{
"foo": map[string]interface{}{
"bar": "bar",
},
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": []interface{}{
"${var.foo}",
"bing",
},
},
Output: map[string]interface{}{
"foo": []interface{}{
"bar",
"baz",
"bing",
},
},
Value: "bar" + InterpSplitDelim + "baz",
},
{
Input: map[string]interface{}{
"foo": []interface{}{
"${var.foo}",
"bing",
},
},
Output: map[string]interface{}{},
Value: UnknownVariableValue + InterpSplitDelim + "baz",
},
}
for i, tc := range cases {
fn := func(i Interpolation) (string, error) {
return tc.Value, nil
}
w := &interpolationWalker{F: fn, Replace: true}
if err := reflectwalk.Walk(tc.Input, w); err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(tc.Input, tc.Output) {
t.Fatalf("%d: bad:\n\n%#v", i, tc.Input)
}
}
}