terraform/config/interpolate_walk_test.go

201 lines
3.6 KiB
Go
Raw Normal View History

2014-07-21 20:24:44 +02:00
package config
import (
2015-01-13 19:27:57 +01:00
"fmt"
2014-07-21 20:24:44 +02:00
"reflect"
"testing"
2016-01-31 08:38:37 +01:00
"github.com/hashicorp/hil/ast"
"github.com/hashicorp/terraform/config/hcl2shim"
2014-07-21 20:24:44 +02:00
"github.com/mitchellh/reflectwalk"
)
func TestInterpolationWalker_detect(t *testing.T) {
cases := []struct {
Input interface{}
2015-01-13 19:27:57 +01:00
Result []string
2014-07-21 20:24:44 +02:00
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
2016-01-19 22:17:47 +01:00
Result: []string{
"Literal(TypeString, ${var.foo})",
},
2014-07-21 20:24:44 +02:00
},
{
Input: map[string]interface{}{
"foo": "${var.foo}",
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Variable(var.foo)",
2014-07-21 20:24:44 +02:00
},
},
2014-08-05 19:11:56 +02:00
{
Input: map[string]interface{}{
"foo": "${aws_instance.foo.*.num}",
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Variable(aws_instance.foo.*.num)",
2014-08-05 19:11:56 +02:00
},
},
{
Input: map[string]interface{}{
"foo": "${lookup(var.foo)}",
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Call(lookup, Variable(var.foo))",
},
},
{
Input: map[string]interface{}{
"foo": `${file("test.txt")}`,
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Call(file, Literal(TypeString, test.txt))",
},
},
2014-08-21 20:33:52 +02:00
{
Input: map[string]interface{}{
"foo": `${file("foo/bar.txt")}`,
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Call(file, Literal(TypeString, foo/bar.txt))",
2014-08-21 20:33:52 +02:00
},
},
2014-10-10 06:22:35 +02:00
{
Input: map[string]interface{}{
"foo": `${join(",", foo.bar.*.id)}`,
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Call(join, Literal(TypeString, ,), Variable(foo.bar.*.id))",
2014-10-10 06:22:35 +02:00
},
},
{
Input: map[string]interface{}{
"foo": `${concat("localhost", ":8080")}`,
},
2015-01-13 19:27:57 +01:00
Result: []string{
"Call(concat, Literal(TypeString, localhost), Literal(TypeString, :8080))",
},
},
2014-07-21 20:24:44 +02:00
}
for i, tc := range cases {
2015-01-13 19:27:57 +01:00
var actual []string
detectFn := func(root ast.Node) (interface{}, error) {
2015-01-13 19:27:57 +01:00
actual = append(actual, fmt.Sprintf("%s", root))
2014-07-21 20:24:44 +02:00
return "", nil
}
w := &interpolationWalker{F: detectFn}
if err := reflectwalk.Walk(tc.Input, w); err != nil {
t.Fatalf("err: %s", err)
}
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{}
core: support native list variables in config This commit adds support for native list variables and outputs, building up on the previous change to state. Interpolation functions now return native lists in preference to StringList. List variables are defined like this: variable "test" { # This can also be inferred type = "list" default = ["Hello", "World"] } output "test_out" { value = "${var.a_list}" } This results in the following state: ``` ... "outputs": { "test_out": [ "hello", "world" ] }, ... ``` And the result of terraform output is as follows: ``` $ terraform output test_out = [ hello world ] ``` Using the output name, an xargs-friendly representation is output: ``` $ terraform output test_out hello world ``` The output command also supports indexing into the list (with appropriate range checking and no wrapping): ``` $ terraform output test_out 1 world ``` Along with maps, list outputs from one module may be passed as variables into another, removing the need for the `join(",", var.list_as_string)` and `split(",", var.list_as_string)` which was previously necessary in Terraform configuration. This commit also updates the tests and implementations of built-in interpolation functions to take and return native lists where appropriate. A backwards compatibility note: previously the concat interpolation function was capable of concatenating either strings or lists. The strings use case was deprectated a long time ago but still remained. Because we cannot return `ast.TypeAny` from an interpolation function, this use case is no longer supported for strings - `concat` is only capable of concatenating lists. This should not be a huge issue - the type checker picks up incorrect parameters, and the native HIL string concatenation - or the `join` function - can be used to replicate the missing behaviour.
2016-04-22 02:03:24 +02:00
Value interface{}
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
Output: map[string]interface{}{
2016-01-19 22:17:47 +01:00
"foo": "bar",
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": "hello, ${var.foo}",
},
Output: map[string]interface{}{
2015-01-13 19:27:57 +01:00
"foo": "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",
},
},
core: support native list variables in config This commit adds support for native list variables and outputs, building up on the previous change to state. Interpolation functions now return native lists in preference to StringList. List variables are defined like this: variable "test" { # This can also be inferred type = "list" default = ["Hello", "World"] } output "test_out" { value = "${var.a_list}" } This results in the following state: ``` ... "outputs": { "test_out": [ "hello", "world" ] }, ... ``` And the result of terraform output is as follows: ``` $ terraform output test_out = [ hello world ] ``` Using the output name, an xargs-friendly representation is output: ``` $ terraform output test_out hello world ``` The output command also supports indexing into the list (with appropriate range checking and no wrapping): ``` $ terraform output test_out 1 world ``` Along with maps, list outputs from one module may be passed as variables into another, removing the need for the `join(",", var.list_as_string)` and `split(",", var.list_as_string)` which was previously necessary in Terraform configuration. This commit also updates the tests and implementations of built-in interpolation functions to take and return native lists where appropriate. A backwards compatibility note: previously the concat interpolation function was capable of concatenating either strings or lists. The strings use case was deprectated a long time ago but still remained. Because we cannot return `ast.TypeAny` from an interpolation function, this use case is no longer supported for strings - `concat` is only capable of concatenating lists. This should not be a huge issue - the type checker picks up incorrect parameters, and the native HIL string concatenation - or the `join` function - can be used to replicate the missing behaviour.
2016-04-22 02:03:24 +02:00
Value: []interface{}{"bar", "baz"},
},
{
Input: map[string]interface{}{
"foo": []interface{}{
"${var.foo}",
"bing",
},
},
Output: map[string]interface{}{
"foo": []interface{}{
hcl2shim.UnknownVariableValue,
"baz",
"bing",
},
},
Value: []interface{}{hcl2shim.UnknownVariableValue, "baz"},
},
}
for i, tc := range cases {
fn := func(ast.Node) (interface{}, error) {
return tc.Value, nil
}
t.Run(fmt.Sprintf("walk-%d", i), func(t *testing.T) {
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\nexpected:%#v\ngot:%#v", i, tc.Output, tc.Input)
}
})
}
}