2014-07-21 22:12:43 +02:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2014-10-10 06:22:35 +02:00
|
|
|
"fmt"
|
2014-07-23 03:35:36 +02:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2015-01-13 20:50:44 +01:00
|
|
|
"reflect"
|
2014-07-21 22:12:43 +02:00
|
|
|
"testing"
|
2016-12-02 00:02:39 +01:00
|
|
|
"time"
|
2014-08-19 22:14:45 +02:00
|
|
|
|
2017-01-18 22:11:19 +01:00
|
|
|
"path/filepath"
|
|
|
|
|
2016-01-31 08:38:37 +01:00
|
|
|
"github.com/hashicorp/hil"
|
|
|
|
"github.com/hashicorp/hil/ast"
|
2017-01-18 22:11:19 +01:00
|
|
|
"github.com/mitchellh/go-homedir"
|
2017-05-22 12:02:32 +02:00
|
|
|
"golang.org/x/crypto/bcrypt"
|
2015-01-13 20:50:44 +01:00
|
|
|
)
|
2014-08-19 22:14:45 +02:00
|
|
|
|
2016-10-26 16:33:54 +02:00
|
|
|
func TestInterpolateFuncZipMap(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${zipmap(var.list, var.list2)}`,
|
|
|
|
map[string]interface{}{
|
|
|
|
"Hello": "bar",
|
|
|
|
"World": "baz",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${zipmap(var.list, var.nonstrings)}`,
|
|
|
|
map[string]interface{}{
|
|
|
|
"Hello": []interface{}{"bar", "baz"},
|
|
|
|
"World": []interface{}{"boo", "foo"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${zipmap(var.nonstrings, var.list2)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${zipmap(var.list, var.differentlengthlist)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.list": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "Hello",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "World",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.list2": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "bar",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.differentlengthlist": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "bar",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "boo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.nonstrings": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "bar",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "boo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-07-07 14:19:41 +02:00
|
|
|
func TestInterpolateFuncList(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// empty input returns empty list
|
|
|
|
{
|
|
|
|
`${list()}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// single input returns list of length 1
|
|
|
|
{
|
|
|
|
`${list("hello")}`,
|
|
|
|
[]interface{}{"hello"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// two inputs returns list of length 2
|
|
|
|
{
|
|
|
|
`${list("hello", "world")}`,
|
|
|
|
[]interface{}{"hello", "world"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// not a string input gives error
|
|
|
|
{
|
2016-07-19 19:39:40 +02:00
|
|
|
`${list("hello", 42)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// list of lists
|
|
|
|
{
|
|
|
|
`${list("${var.list}", "${var.list2}")}`,
|
|
|
|
[]interface{}{[]interface{}{"Hello", "World"}, []interface{}{"bar", "baz"}},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// list of maps
|
|
|
|
{
|
|
|
|
`${list("${var.map}", "${var.map2}")}`,
|
|
|
|
[]interface{}{map[string]interface{}{"key": "bar"}, map[string]interface{}{"key2": "baz"}},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// error on a heterogeneous list
|
|
|
|
{
|
|
|
|
`${list("first", "${var.list}")}`,
|
2016-07-07 14:19:41 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.list": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "Hello",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "World",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-07-19 19:39:40 +02:00
|
|
|
"var.list2": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "bar",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"var.map": {
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"key": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.map2": {
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"key2": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-07-07 14:19:41 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-10-28 19:49:31 +02:00
|
|
|
func TestInterpolateFuncMax(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${max()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${max("")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${max(-1, 0, 1)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${max(1, 0, -1)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${max(-1, -2)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${max(-1)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncMin(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${min()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${min("")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${min(-1, 0, 1)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${min(1, 0, -1)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${min(-1, -2)}`,
|
|
|
|
"-2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${min(-1)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-17 23:46:33 +02:00
|
|
|
func TestInterpolateFuncPow(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${pow(1, 0)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(1, 1)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${pow(2, 0)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(2, 1)}`,
|
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(3, 2)}`,
|
|
|
|
"9",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(-3, 2)}`,
|
|
|
|
"9",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(2, -2)}`,
|
|
|
|
"0.25",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(0, 2)}`,
|
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
2017-05-18 16:30:10 +02:00
|
|
|
{
|
|
|
|
`${pow("invalid-input", 2)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(2, "invalid-input")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pow(2)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2017-05-17 23:46:33 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-10-28 19:49:31 +02:00
|
|
|
func TestInterpolateFuncFloor(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${floor()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${floor("")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${floor("-1.3")}`, // there appears to be a AST bug where the parsed argument ends up being -1 without the "s
|
|
|
|
"-2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${floor(1.7)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncCeil(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${ceil()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${ceil("")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${ceil(-1.8)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${ceil(1.2)}`,
|
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-25 23:41:33 +02:00
|
|
|
func TestInterpolateFuncLog(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${log(1, 10)}`,
|
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${log(10, 10)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${log(0, 10)}`,
|
|
|
|
"-Inf",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${log(10, 0)}`,
|
|
|
|
"-0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-06 13:14:09 +02:00
|
|
|
func TestInterpolateFuncChomp(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${chomp()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${chomp("hello world")}`,
|
|
|
|
"hello world",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
2017-04-07 10:41:55 +02:00
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\ncruel\nworld"),
|
|
|
|
"goodbye\ncruel\nworld",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\r\nwindows\r\nworld"),
|
|
|
|
"goodbye\r\nwindows\r\nworld",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\ncruel\nworld\n"),
|
|
|
|
"goodbye\ncruel\nworld",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\ncruel\nworld\n\n\n\n"),
|
|
|
|
"goodbye\ncruel\nworld",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\r\nwindows\r\nworld\r\n"),
|
|
|
|
"goodbye\r\nwindows\r\nworld",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${chomp("%s")}`, "goodbye\r\nwindows\r\nworld\r\n\r\n\r\n\r\n"),
|
|
|
|
"goodbye\r\nwindows\r\nworld",
|
2017-04-06 13:14:09 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
config: Add map() interpolation function
* `map(key, value, ...)` - Returns a map consisting of the key/value pairs
specified as arguments. Every odd argument must be a string key, and every
even argument must have the same type as the other values specified.
Duplicate keys are not allowed. Examples:
* `map("hello", "world")`
* `map("us-east", list("a", "b", "c"), "us-west", list("b", "c", "d"))`
2016-07-27 19:42:46 +02:00
|
|
|
func TestInterpolateFuncMap(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// empty input returns empty map
|
|
|
|
{
|
|
|
|
`${map()}`,
|
|
|
|
map[string]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// odd args is error
|
|
|
|
{
|
|
|
|
`${map("odd")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// two args returns map w/ one k/v
|
|
|
|
{
|
|
|
|
`${map("hello", "world")}`,
|
|
|
|
map[string]interface{}{"hello": "world"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// four args get two k/v
|
|
|
|
{
|
|
|
|
`${map("hello", "world", "what's", "up?")}`,
|
|
|
|
map[string]interface{}{"hello": "world", "what's": "up?"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// map of lists is okay
|
|
|
|
{
|
|
|
|
`${map("hello", list("world"), "what's", list("up?"))}`,
|
|
|
|
map[string]interface{}{
|
|
|
|
"hello": []interface{}{"world"},
|
|
|
|
"what's": []interface{}{"up?"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// map of maps is okay
|
|
|
|
{
|
|
|
|
`${map("hello", map("there", "world"), "what's", map("really", "up?"))}`,
|
|
|
|
map[string]interface{}{
|
|
|
|
"hello": map[string]interface{}{"there": "world"},
|
|
|
|
"what's": map[string]interface{}{"really": "up?"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// keys have to be strings
|
|
|
|
{
|
|
|
|
`${map(list("listkey"), "val")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// types have to match
|
|
|
|
{
|
|
|
|
`${map("some", "strings", "also", list("lists"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// duplicate keys are an error
|
|
|
|
{
|
|
|
|
`${map("key", "val", "key", "again")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-09-15 15:50:31 +02:00
|
|
|
func TestInterpolateFuncCompact(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// empty string within array
|
|
|
|
{
|
2015-09-16 11:09:34 +02:00
|
|
|
`${compact(split(",", "a,,b"))}`,
|
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
|
|
|
[]interface{}{"a", "b"},
|
2015-09-15 15:50:31 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// empty string at the end of array
|
|
|
|
{
|
2015-09-16 11:09:34 +02:00
|
|
|
`${compact(split(",", "a,b,"))}`,
|
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
|
|
|
[]interface{}{"a", "b"},
|
2015-09-15 15:50:31 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// single empty string
|
|
|
|
{
|
|
|
|
`${compact(split(",", ""))}`,
|
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
|
|
|
[]interface{}{},
|
2015-09-15 15:50:31 +02:00
|
|
|
false,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
|
|
|
|
// errrors on list of lists
|
|
|
|
{
|
|
|
|
`${compact(list(list("a"), list("b")))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2015-09-15 15:50:31 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-10-22 17:10:42 +02:00
|
|
|
func TestInterpolateFuncCidrHost(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${cidrhost("192.168.1.0/24", 5)}`,
|
|
|
|
"192.168.1.5",
|
|
|
|
false,
|
|
|
|
},
|
2017-04-19 13:26:49 +02:00
|
|
|
{
|
|
|
|
`${cidrhost("192.168.1.0/24", -5)}`,
|
|
|
|
"192.168.1.251",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrhost("192.168.1.0/24", -256)}`,
|
|
|
|
"192.168.1.0",
|
|
|
|
false,
|
|
|
|
},
|
2015-10-22 17:10:42 +02:00
|
|
|
{
|
|
|
|
`${cidrhost("192.168.1.0/30", 255)}`,
|
|
|
|
nil,
|
|
|
|
true, // 255 doesn't fit in two bits
|
|
|
|
},
|
2017-04-19 13:26:49 +02:00
|
|
|
{
|
|
|
|
`${cidrhost("192.168.1.0/30", -255)}`,
|
|
|
|
nil,
|
|
|
|
true, // 255 doesn't fit in two bits
|
|
|
|
},
|
2015-10-22 17:10:42 +02:00
|
|
|
{
|
|
|
|
`${cidrhost("not-a-cidr", 6)}`,
|
|
|
|
nil,
|
|
|
|
true, // not a valid CIDR mask
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrhost("10.256.0.0/8", 6)}`,
|
|
|
|
nil,
|
|
|
|
true, // can't have an octet >255
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncCidrNetmask(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${cidrnetmask("192.168.1.0/24")}`,
|
|
|
|
"255.255.255.0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrnetmask("192.168.1.0/32")}`,
|
|
|
|
"255.255.255.255",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrnetmask("0.0.0.0/0")}`,
|
|
|
|
"0.0.0.0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// This doesn't really make sense for IPv6 networks
|
|
|
|
// but it ought to do something sensible anyway.
|
|
|
|
`${cidrnetmask("1::/64")}`,
|
|
|
|
"ffff:ffff:ffff:ffff::",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrnetmask("not-a-cidr")}`,
|
|
|
|
nil,
|
|
|
|
true, // not a valid CIDR mask
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrnetmask("10.256.0.0/8")}`,
|
|
|
|
nil,
|
|
|
|
true, // can't have an octet >255
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncCidrSubnet(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${cidrsubnet("192.168.2.0/20", 4, 6)}`,
|
|
|
|
"192.168.6.0/24",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrsubnet("fe80::/48", 16, 6)}`,
|
|
|
|
"fe80:0:0:6::/64",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// IPv4 address encoded in IPv6 syntax gets normalized
|
|
|
|
`${cidrsubnet("::ffff:192.168.0.0/112", 8, 6)}`,
|
|
|
|
"192.168.6.0/24",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrsubnet("192.168.0.0/30", 4, 6)}`,
|
|
|
|
nil,
|
|
|
|
true, // not enough bits left
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrsubnet("192.168.0.0/16", 2, 16)}`,
|
|
|
|
nil,
|
|
|
|
true, // can't encode 16 in 2 bits
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrsubnet("not-a-cidr", 4, 6)}`,
|
|
|
|
nil,
|
|
|
|
true, // not a valid CIDR mask
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${cidrsubnet("10.256.0.0/8", 4, 6)}`,
|
|
|
|
nil,
|
|
|
|
true, // can't have an octet >255
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-11-08 07:34:56 +01:00
|
|
|
func TestInterpolateFuncCoalesce(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${coalesce("first", "second", "third")}`,
|
|
|
|
"first",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalesce("", "second", "third")}`,
|
|
|
|
"second",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalesce("", "", "")}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalesce("foo")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-08 21:36:01 +01:00
|
|
|
func TestInterpolateFuncCoalesceList(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${coalescelist(list("first"), list("second"), list("third"))}`,
|
|
|
|
[]interface{}{"first"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalescelist(list(), list("second"), list("third"))}`,
|
|
|
|
[]interface{}{"second"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalescelist(list(), list(), list())}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${coalescelist(list("foo"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-05-03 16:53:33 +02:00
|
|
|
func TestInterpolateFuncConcat(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// String + list
|
2016-08-01 21:06:20 +02:00
|
|
|
// no longer supported, now returns an error
|
2015-05-03 16:53:33 +02:00
|
|
|
{
|
|
|
|
`${concat("a", split(",", "b,c"))}`,
|
2016-08-01 21:06:20 +02:00
|
|
|
nil,
|
|
|
|
true,
|
2015-05-03 16:53:33 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
// List + string
|
2016-08-01 21:06:20 +02:00
|
|
|
// no longer supported, now returns an error
|
2015-05-03 16:53:33 +02:00
|
|
|
{
|
|
|
|
`${concat(split(",", "a,b"), "c")}`,
|
2016-08-01 21:06:20 +02:00
|
|
|
nil,
|
|
|
|
true,
|
2015-05-03 16:53:33 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
// Single list
|
|
|
|
{
|
|
|
|
`${concat(split(",", ",foo,"))}`,
|
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
|
|
|
[]interface{}{"", "foo", ""},
|
2015-05-03 16:53:33 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${concat(split(",", "a,b,c"))}`,
|
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
|
|
|
[]interface{}{"a", "b", "c"},
|
2015-05-03 16:53:33 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Two lists
|
|
|
|
{
|
|
|
|
`${concat(split(",", "a,b,c"), split(",", "d,e"))}`,
|
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
|
|
|
[]interface{}{"a", "b", "c", "d", "e"},
|
2015-05-03 16:53:33 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
// Two lists with different separators
|
|
|
|
{
|
|
|
|
`${concat(split(",", "a,b,c"), split(" ", "d e"))}`,
|
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
|
|
|
[]interface{}{"a", "b", "c", "d", "e"},
|
2015-05-03 16:53:33 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// More lists
|
|
|
|
{
|
|
|
|
`${concat(split(",", "a,b"), split(",", "c,d"), split(",", "e,f"), split(",", "0,1"))}`,
|
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
|
|
|
[]interface{}{"a", "b", "c", "d", "e", "f", "0", "1"},
|
2015-05-03 16:53:33 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2016-07-19 23:21:14 +02:00
|
|
|
// list vars
|
|
|
|
{
|
|
|
|
`${concat("${var.list}", "${var.list}")}`,
|
|
|
|
[]interface{}{"a", "b", "a", "b"},
|
|
|
|
false,
|
2016-06-12 20:21:47 +02:00
|
|
|
},
|
2016-07-19 23:21:14 +02:00
|
|
|
// lists of lists
|
2016-06-12 20:21:47 +02:00
|
|
|
{
|
2016-07-19 23:21:14 +02:00
|
|
|
`${concat("${var.lists}", "${var.lists}")}`,
|
|
|
|
[]interface{}{[]interface{}{"c", "d"}, []interface{}{"c", "d"}},
|
|
|
|
false,
|
2016-06-12 20:21:47 +02:00
|
|
|
},
|
|
|
|
|
2016-07-19 23:21:14 +02:00
|
|
|
// lists of maps
|
|
|
|
{
|
|
|
|
`${concat("${var.maps}", "${var.maps}")}`,
|
|
|
|
[]interface{}{map[string]interface{}{"key1": "a", "key2": "b"}, map[string]interface{}{"key1": "a", "key2": "b"}},
|
|
|
|
false,
|
|
|
|
},
|
2016-06-12 20:21:47 +02:00
|
|
|
|
2016-08-01 21:06:20 +02:00
|
|
|
// multiple strings
|
|
|
|
// no longer supported, now returns an error
|
|
|
|
{
|
|
|
|
`${concat("string1", "string2")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
2016-07-19 23:21:14 +02:00
|
|
|
// mismatched types
|
|
|
|
{
|
|
|
|
`${concat("${var.lists}", "${var.maps}")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.list": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "a",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "b",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.lists": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "c",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "d",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.maps": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"key1": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "a",
|
|
|
|
},
|
|
|
|
"key2": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "b",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2016-06-12 20:21:47 +02:00
|
|
|
}
|
|
|
|
|
2016-08-02 00:10:53 +02:00
|
|
|
func TestInterpolateFuncMerge(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// basic merge
|
|
|
|
{
|
|
|
|
`${merge(map("a", "b"), map("c", "d"))}`,
|
|
|
|
map[string]interface{}{"a": "b", "c": "d"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// merge with conflicts is ok, last in wins.
|
|
|
|
{
|
|
|
|
`${merge(map("a", "b", "c", "X"), map("c", "d"))}`,
|
|
|
|
map[string]interface{}{"a": "b", "c": "d"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// merge variadic
|
|
|
|
{
|
|
|
|
`${merge(map("a", "b"), map("c", "d"), map("e", "f"))}`,
|
|
|
|
map[string]interface{}{"a": "b", "c": "d", "e": "f"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// merge with variables
|
|
|
|
{
|
|
|
|
`${merge(var.maps[0], map("c", "d"))}`,
|
|
|
|
map[string]interface{}{"key1": "a", "key2": "b", "c": "d"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// only accept maps
|
|
|
|
{
|
|
|
|
`${merge(map("a", "b"), list("c", "d"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// merge maps of maps
|
|
|
|
{
|
|
|
|
`${merge(map("a", var.maps[0]), map("b", var.maps[1]))}`,
|
|
|
|
map[string]interface{}{
|
|
|
|
"b": map[string]interface{}{"key3": "d", "key4": "c"},
|
|
|
|
"a": map[string]interface{}{"key1": "a", "key2": "b"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// merge maps of lists
|
|
|
|
{
|
|
|
|
`${merge(map("a", list("b")), map("c", list("d", "e")))}`,
|
|
|
|
map[string]interface{}{"a": []interface{}{"b"}, "c": []interface{}{"d", "e"}},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// merge map of various kinds
|
|
|
|
{
|
|
|
|
`${merge(map("a", var.maps[0]), map("b", list("c", "d")))}`,
|
|
|
|
map[string]interface{}{"a": map[string]interface{}{"key1": "a", "key2": "b"}, "b": []interface{}{"c", "d"}},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.maps": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"key1": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "a",
|
|
|
|
},
|
|
|
|
"key2": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "b",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"key3": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "d",
|
|
|
|
},
|
|
|
|
"key4": {
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "c",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-03-27 03:21:48 +02:00
|
|
|
func TestInterpolateFuncDirname(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${dirname("/foo/bar/baz")}`,
|
|
|
|
"/foo/bar",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-06-15 13:24:33 +02:00
|
|
|
func TestInterpolateFuncDistinct(t *testing.T) {
|
2016-06-10 17:11:51 +02:00
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// 3 duplicates
|
|
|
|
{
|
2016-06-15 13:24:33 +02:00
|
|
|
`${distinct(concat(split(",", "user1,user2,user3"), split(",", "user1,user2,user3")))}`,
|
2016-06-10 17:11:51 +02:00
|
|
|
[]interface{}{"user1", "user2", "user3"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// 1 duplicate
|
|
|
|
{
|
2016-06-15 13:24:33 +02:00
|
|
|
`${distinct(concat(split(",", "user1,user2,user3"), split(",", "user1,user4")))}`,
|
2016-06-10 17:11:51 +02:00
|
|
|
[]interface{}{"user1", "user2", "user3", "user4"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// too many args
|
|
|
|
{
|
2016-06-15 13:24:33 +02:00
|
|
|
`${distinct(concat(split(",", "user1,user2,user3"), split(",", "user1,user4")), "foo")}`,
|
2016-06-10 17:11:51 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
// non-flat list is an error
|
|
|
|
{
|
|
|
|
`${distinct(list(list("a"), list("a")))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-06-10 17:11:51 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-21 19:04:49 +02:00
|
|
|
func TestInterpolateFuncMatchKeys(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// normal usage
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a", "b", "c"), list("ref1", "ref2", "ref3"), list("ref2"))}`,
|
|
|
|
[]interface{}{"b"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// normal usage 2, check the order
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a", "b", "c"), list("ref1", "ref2", "ref3"), list("ref2", "ref1"))}`,
|
|
|
|
[]interface{}{"a", "b"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// duplicate item in searchset
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a", "b", "c"), list("ref1", "ref2", "ref3"), list("ref2", "ref2"))}`,
|
|
|
|
[]interface{}{"b"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// no matches
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a", "b", "c"), list("ref1", "ref2", "ref3"), list("ref4"))}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// no matches 2
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a", "b", "c"), list("ref1", "ref2", "ref3"), list())}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// zero case
|
|
|
|
{
|
|
|
|
`${matchkeys(list(), list(), list("nope"))}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// complex values
|
|
|
|
{
|
|
|
|
`${matchkeys(list(list("a", "a")), list("a"), list("a"))}`,
|
|
|
|
[]interface{}{[]interface{}{"a", "a"}},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// errors
|
|
|
|
// different types
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a"), list(1), list("a"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// different types
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a"), list(list("a"), list("a")), list("a"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// lists of different length is an error
|
|
|
|
{
|
|
|
|
`${matchkeys(list("a"), list("a", "b"), list("a"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-07-23 03:35:36 +02:00
|
|
|
func TestInterpolateFuncFile(t *testing.T) {
|
|
|
|
tf, err := ioutil.TempFile("", "tf")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
path := tf.Name()
|
|
|
|
tf.Write([]byte("foo"))
|
|
|
|
tf.Close()
|
|
|
|
defer os.Remove(path)
|
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
fmt.Sprintf(`${file("%s")}`, path),
|
|
|
|
"foo",
|
|
|
|
false,
|
|
|
|
},
|
2014-07-23 03:35:36 +02:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Invalid path
|
|
|
|
{
|
|
|
|
`${file("/i/dont/exist")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2014-07-23 03:35:36 +02:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Too many args
|
|
|
|
{
|
|
|
|
`${file("foo", "bar")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2014-07-23 03:35:36 +02:00
|
|
|
},
|
2015-01-13 20:50:44 +01:00
|
|
|
})
|
2014-07-23 03:35:36 +02:00
|
|
|
}
|
2014-07-23 03:35:53 +02:00
|
|
|
|
2015-03-02 19:26:06 +01:00
|
|
|
func TestInterpolateFuncFormat(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${format("hello")}`,
|
|
|
|
"hello",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${format("hello %s", "world")}`,
|
|
|
|
"hello world",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${format("hello %d", 42)}`,
|
|
|
|
"hello 42",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${format("hello %05d", 42)}`,
|
|
|
|
"hello 00042",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${format("hello %05d", 12345)}`,
|
|
|
|
"hello 12345",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-05-06 05:34:40 +02:00
|
|
|
func TestInterpolateFuncFormatList(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// formatlist requires at least one list
|
|
|
|
{
|
|
|
|
`${formatlist("hello")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${formatlist("hello %s", "world")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// formatlist applies to each list element in turn
|
|
|
|
{
|
|
|
|
`${formatlist("<%s>", split(",", "A,B"))}`,
|
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
|
|
|
[]interface{}{"<A>", "<B>"},
|
2015-05-06 05:34:40 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
// formatlist repeats scalar elements
|
|
|
|
{
|
|
|
|
`${join(", ", formatlist("%s=%s", "x", split(",", "A,B,C")))}`,
|
|
|
|
"x=A, x=B, x=C",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// Multiple lists are walked in parallel
|
|
|
|
{
|
|
|
|
`${join(", ", formatlist("%s=%s", split(",", "A,B,C"), split(",", "1,2,3")))}`,
|
|
|
|
"A=1, B=2, C=3",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
// Mismatched list lengths generate an error
|
|
|
|
{
|
|
|
|
`${formatlist("%s=%2s", split(",", "A,B,C,D"), split(",", "1,2,3"))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2015-06-26 01:45:17 +02:00
|
|
|
// Works with lists of length 1 [GH-2240]
|
|
|
|
{
|
|
|
|
`${formatlist("%s.id", split(",", "demo-rest-elb"))}`,
|
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
|
|
|
[]interface{}{"demo-rest-elb.id"},
|
2015-06-26 01:45:17 +02:00
|
|
|
false,
|
|
|
|
},
|
2016-11-02 06:57:11 +01:00
|
|
|
// Works with empty lists [GH-7607]
|
|
|
|
{
|
|
|
|
`${formatlist("%s", var.emptylist)}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.emptylist": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{},
|
|
|
|
},
|
2015-05-06 05:34:40 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-07-12 21:55:19 +02:00
|
|
|
func TestInterpolateFuncIndex(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
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
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.list1": interfaceToVariableSwallowError([]string{"notfoo", "stillnotfoo", "bar"}),
|
|
|
|
"var.list2": interfaceToVariableSwallowError([]string{"foo"}),
|
|
|
|
"var.list3": interfaceToVariableSwallowError([]string{"foo", "spam", "bar", "eggs"}),
|
|
|
|
},
|
2015-07-12 21:55:19 +02:00
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${index("test", "")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
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
|
|
|
`${index(var.list1, "foo")}`,
|
2015-07-12 21:55:19 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
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
|
|
|
`${index(var.list2, "foo")}`,
|
2015-07-12 21:55:19 +02:00
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
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
|
|
|
`${index(var.list3, "bar")}`,
|
2015-07-12 21:55:19 +02:00
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-10-10 06:22:35 +02:00
|
|
|
func TestInterpolateFuncJoin(t *testing.T) {
|
2015-01-13 21:06:04 +01:00
|
|
|
testFunction(t, testFunctionConfig{
|
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
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.a_list": interfaceToVariableSwallowError([]string{"foo"}),
|
|
|
|
"var.a_longer_list": interfaceToVariableSwallowError([]string{"foo", "bar", "baz"}),
|
2016-07-27 19:47:44 +02:00
|
|
|
"var.list_of_lists": interfaceToVariableSwallowError([]interface{}{[]string{"foo"}, []string{"bar"}, []string{"baz"}}),
|
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
|
|
|
},
|
2015-01-13 21:06:04 +01:00
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${join(",")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2014-10-10 06:22:35 +02:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
{
|
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
|
|
|
`${join(",", var.a_list)}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"foo",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2015-01-13 20:50:44 +01:00
|
|
|
{
|
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
|
|
|
`${join(".", var.a_longer_list)}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"foo.bar.baz",
|
2015-01-13 20:50:44 +01:00
|
|
|
false,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
`${join(".", var.list_of_lists)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${join(".", list(list("nested")))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2014-10-10 06:22:35 +02:00
|
|
|
},
|
2015-01-13 20:50:44 +01:00
|
|
|
})
|
2014-10-10 06:22:35 +02:00
|
|
|
}
|
|
|
|
|
2016-03-29 03:02:06 +02:00
|
|
|
func TestInterpolateFuncJSONEncode(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"easy": ast.Variable{
|
|
|
|
Value: "test",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"hard": ast.Variable{
|
|
|
|
Value: " foo \\ \n \t \" bar ",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
2016-05-18 19:45:22 +02:00
|
|
|
"list": interfaceToVariableSwallowError([]string{"foo", "bar\tbaz"}),
|
|
|
|
// XXX can't use InterfaceToVariable as it converts empty slice into empty
|
|
|
|
// map.
|
|
|
|
"emptylist": ast.Variable{
|
|
|
|
Value: []ast.Variable{},
|
|
|
|
Type: ast.TypeList,
|
|
|
|
},
|
|
|
|
"map": interfaceToVariableSwallowError(map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"ba \n z": "q\\x",
|
|
|
|
}),
|
|
|
|
"emptymap": interfaceToVariableSwallowError(map[string]string{}),
|
|
|
|
|
|
|
|
// Not yet supported (but it would be nice)
|
|
|
|
"nestedlist": interfaceToVariableSwallowError([][]string{{"foo"}}),
|
|
|
|
"nestedmap": interfaceToVariableSwallowError(map[string][]string{"foo": {"bar"}}),
|
2016-03-29 03:02:06 +02:00
|
|
|
},
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${jsonencode("test")}`,
|
|
|
|
`"test"`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(easy)}`,
|
|
|
|
`"test"`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(hard)}`,
|
|
|
|
`" foo \\ \n \t \" bar "`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode("")}`,
|
|
|
|
`""`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-05-18 19:45:22 +02:00
|
|
|
{
|
|
|
|
`${jsonencode(list)}`,
|
|
|
|
`["foo","bar\tbaz"]`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(emptylist)}`,
|
|
|
|
`[]`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(map)}`,
|
|
|
|
`{"ba \n z":"q\\x","foo":"bar"}`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(emptymap)}`,
|
|
|
|
`{}`,
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(nestedlist)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${jsonencode(nestedmap)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-03-29 03:02:06 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-03-02 18:37:40 +01:00
|
|
|
func TestInterpolateFuncReplace(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// Regular search and replace
|
|
|
|
{
|
|
|
|
`${replace("hello", "hel", "bel")}`,
|
|
|
|
"bello",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Search string doesn't match
|
|
|
|
{
|
|
|
|
`${replace("hello", "nope", "bel")}`,
|
|
|
|
"hello",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Regular expression
|
|
|
|
{
|
|
|
|
`${replace("hello", "/l/", "L")}`,
|
|
|
|
"heLLo",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${replace("helo", "/(l)/", "$1$1")}`,
|
|
|
|
"hello",
|
|
|
|
false,
|
|
|
|
},
|
2015-03-02 18:44:45 +01:00
|
|
|
|
|
|
|
// Bad regexp
|
|
|
|
{
|
|
|
|
`${replace("helo", "/(l/", "$1$1")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2015-03-02 18:37:40 +01:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-04-12 16:17:26 +02:00
|
|
|
func TestInterpolateFuncLength(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// Raw strings
|
|
|
|
{
|
|
|
|
`${length("")}`,
|
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length("a")}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(" ")}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(" a ,")}`,
|
|
|
|
"4",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length("aaa")}`,
|
|
|
|
"3",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Lists
|
|
|
|
{
|
|
|
|
`${length(split(",", "a"))}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(split(",", "foo,"))}`,
|
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(split(",", ",foo,"))}`,
|
|
|
|
"3",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(split(",", "foo,bar"))}`,
|
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(split(".", "one.two.three.four.five"))}`,
|
|
|
|
"5",
|
|
|
|
false,
|
|
|
|
},
|
2015-10-25 19:55:21 +01:00
|
|
|
// Want length 0 if we split an empty string then compact
|
|
|
|
{
|
|
|
|
`${length(compact(split(",", "")))}`,
|
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
// Works for maps
|
|
|
|
{
|
|
|
|
`${length(map("k", "v"))}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${length(map("k1", "v1", "k2", "v2"))}`,
|
|
|
|
"2",
|
|
|
|
false,
|
|
|
|
},
|
2015-04-12 16:17:26 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-01-27 16:36:31 +01:00
|
|
|
func TestInterpolateFuncSignum(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${signum()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${signum("")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${signum(0)}`,
|
|
|
|
"0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${signum(15)}`,
|
|
|
|
"1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${signum(-29)}`,
|
|
|
|
"-1",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-02-13 22:20:02 +01:00
|
|
|
func TestInterpolateFuncSlice(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// Negative from index
|
|
|
|
{
|
|
|
|
`${slice(list("a"), -1, 0)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// From index > to index
|
|
|
|
{
|
|
|
|
`${slice(list("a", "b", "c"), 2, 1)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// To index too large
|
|
|
|
{
|
|
|
|
`${slice(var.list_of_strings, 1, 4)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
// Empty slice
|
|
|
|
{
|
|
|
|
`${slice(var.list_of_strings, 1, 1)}`,
|
|
|
|
[]interface{}{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${slice(var.list_of_strings, 1, 2)}`,
|
|
|
|
[]interface{}{"b"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${slice(var.list_of_strings, 0, length(var.list_of_strings) - 1)}`,
|
|
|
|
[]interface{}{"a", "b"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.list_of_strings": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "a",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "b",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "c",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-06-11 18:36:29 +02:00
|
|
|
func TestInterpolateFuncSort(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.strings": ast.Variable{
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{Type: ast.TypeString, Value: "c"},
|
|
|
|
{Type: ast.TypeString, Value: "a"},
|
|
|
|
{Type: ast.TypeString, Value: "b"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"var.notstrings": ast.Variable{
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{Type: ast.TypeList, Value: []ast.Variable{}},
|
|
|
|
{Type: ast.TypeString, Value: "b"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${sort(var.strings)}`,
|
|
|
|
[]interface{}{"a", "b", "c"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${sort(var.notstrings)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-01-28 22:59:16 +01:00
|
|
|
func TestInterpolateFuncSplit(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${split(",")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
2015-06-26 00:55:51 +02:00
|
|
|
{
|
|
|
|
`${split(",", "")}`,
|
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
|
|
|
[]interface{}{""},
|
2015-06-26 00:55:51 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2015-01-28 22:59:16 +01:00
|
|
|
{
|
|
|
|
`${split(",", "foo")}`,
|
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
|
|
|
[]interface{}{"foo"},
|
2015-01-28 22:59:16 +01:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2015-04-12 16:17:26 +02:00
|
|
|
{
|
|
|
|
`${split(",", ",,,")}`,
|
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
|
|
|
[]interface{}{"", "", "", ""},
|
2015-04-12 16:17:26 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${split(",", "foo,")}`,
|
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
|
|
|
[]interface{}{"foo", ""},
|
2015-04-12 16:17:26 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${split(",", ",foo,")}`,
|
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
|
|
|
[]interface{}{"", "foo", ""},
|
2015-04-12 16:17:26 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2015-01-28 22:59:16 +01:00
|
|
|
{
|
|
|
|
`${split(".", "foo.bar.baz")}`,
|
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
|
|
|
[]interface{}{"foo", "bar", "baz"},
|
2015-01-28 22:59:16 +01:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-07-21 22:12:43 +02:00
|
|
|
func TestInterpolateFuncLookup(t *testing.T) {
|
2015-01-13 21:06:04 +01:00
|
|
|
testFunction(t, testFunctionConfig{
|
2015-01-15 07:01:42 +01:00
|
|
|
Vars: map[string]ast.Variable{
|
2016-07-27 19:47:44 +02:00
|
|
|
"var.foo": {
|
2016-04-11 19:40:06 +02:00
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
2016-07-27 19:47:44 +02:00
|
|
|
"bar": {
|
2016-04-11 19:40:06 +02:00
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
2015-01-14 19:40:43 +01:00
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
"var.map_of_lists": ast.Variable{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"bar": {
|
|
|
|
Type: ast.TypeList,
|
|
|
|
Value: []ast.Variable{
|
|
|
|
{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-01-14 19:40:43 +01:00
|
|
|
},
|
2015-01-13 21:06:04 +01:00
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${lookup(var.foo, "bar")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"baz",
|
|
|
|
false,
|
2014-07-21 22:12:43 +02:00
|
|
|
},
|
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Invalid key
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${lookup(var.foo, "baz")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
nil,
|
|
|
|
true,
|
2014-07-21 22:12:43 +02:00
|
|
|
},
|
|
|
|
|
2016-05-26 02:25:15 +02:00
|
|
|
// Supplied default with valid key
|
|
|
|
{
|
|
|
|
`${lookup(var.foo, "bar", "")}`,
|
|
|
|
"baz",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Supplied default with invalid key
|
|
|
|
{
|
|
|
|
`${lookup(var.foo, "zip", "")}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Too many args
|
|
|
|
{
|
2016-05-26 02:25:15 +02:00
|
|
|
`${lookup(var.foo, "bar", "", "abc")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
nil,
|
|
|
|
true,
|
2014-07-21 22:12:43 +02:00
|
|
|
},
|
2016-05-26 02:25:15 +02:00
|
|
|
|
2016-07-27 19:47:44 +02:00
|
|
|
// Cannot lookup into map of lists
|
|
|
|
{
|
|
|
|
`${lookup(var.map_of_lists, "bar")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
2016-05-26 02:25:15 +02:00
|
|
|
// Non-empty default
|
|
|
|
{
|
|
|
|
`${lookup(var.foo, "zap", "xyz")}`,
|
|
|
|
"xyz",
|
|
|
|
false,
|
|
|
|
},
|
2014-07-21 22:12:43 +02:00
|
|
|
},
|
2015-01-13 21:06:04 +01:00
|
|
|
})
|
2014-07-21 22:12:43 +02:00
|
|
|
}
|
2014-11-07 19:23:02 +01:00
|
|
|
|
2015-06-02 23:48:38 +02:00
|
|
|
func TestInterpolateFuncKeys(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Vars: map[string]ast.Variable{
|
2016-04-11 19:40:06 +02:00
|
|
|
"var.foo": ast.Variable{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"bar": ast.Variable{
|
|
|
|
Value: "baz",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"qux": ast.Variable{
|
|
|
|
Value: "quack",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
},
|
2015-06-02 23:48:38 +02:00
|
|
|
},
|
|
|
|
"var.str": ast.Variable{
|
|
|
|
Value: "astring",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${keys(var.foo)}`,
|
|
|
|
[]interface{}{"bar", "qux"},
|
2015-06-02 23:48:38 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Invalid key
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${keys(var.not)}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Too many args
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${keys(var.foo, "bar")}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Not a map
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${keys(var.str)}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-06-29 20:16:12 +02:00
|
|
|
// Confirm that keys return in sorted order, and values return in the order of
|
|
|
|
// their sorted keys.
|
|
|
|
func TestInterpolateFuncKeyValOrder(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Vars: map[string]ast.Variable{
|
|
|
|
"var.foo": ast.Variable{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"D": ast.Variable{
|
|
|
|
Value: "2",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"C": ast.Variable{
|
|
|
|
Value: "Y",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"A": ast.Variable{
|
|
|
|
Value: "X",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"10": ast.Variable{
|
|
|
|
Value: "Z",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"1": ast.Variable{
|
|
|
|
Value: "4",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"3": ast.Variable{
|
|
|
|
Value: "W",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${keys(var.foo)}`,
|
|
|
|
[]interface{}{"1", "10", "3", "A", "C", "D"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${values(var.foo)}`,
|
|
|
|
[]interface{}{"4", "Z", "W", "X", "Y", "2"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-06-02 23:48:38 +02:00
|
|
|
func TestInterpolateFuncValues(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Vars: map[string]ast.Variable{
|
2016-04-11 19:40:06 +02:00
|
|
|
"var.foo": ast.Variable{
|
|
|
|
Type: ast.TypeMap,
|
|
|
|
Value: map[string]ast.Variable{
|
|
|
|
"bar": ast.Variable{
|
|
|
|
Value: "quack",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
"qux": ast.Variable{
|
|
|
|
Value: "baz",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
},
|
2015-06-02 23:48:38 +02:00
|
|
|
},
|
|
|
|
"var.str": ast.Variable{
|
|
|
|
Value: "astring",
|
|
|
|
Type: ast.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${values(var.foo)}`,
|
|
|
|
[]interface{}{"quack", "baz"},
|
2015-06-02 23:48:38 +02:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Invalid key
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${values(var.not)}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Too many args
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${values(var.foo, "bar")}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Not a map
|
|
|
|
{
|
2016-04-11 19:40:06 +02:00
|
|
|
`${values(var.str)}`,
|
2015-06-02 23:48:38 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
|
|
|
|
// Map of lists
|
|
|
|
{
|
|
|
|
`${values(map("one", list()))}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2015-06-02 23:48:38 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
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
|
|
|
func interfaceToVariableSwallowError(input interface{}) ast.Variable {
|
|
|
|
variable, _ := hil.InterfaceToVariable(input)
|
|
|
|
return variable
|
|
|
|
}
|
|
|
|
|
2014-11-07 19:23:02 +01:00
|
|
|
func TestInterpolateFuncElement(t *testing.T) {
|
2015-01-13 21:06:04 +01:00
|
|
|
testFunction(t, testFunctionConfig{
|
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
|
|
|
Vars: map[string]ast.Variable{
|
2016-07-27 19:47:44 +02:00
|
|
|
"var.a_list": interfaceToVariableSwallowError([]string{"foo", "baz"}),
|
|
|
|
"var.a_short_list": interfaceToVariableSwallowError([]string{"foo"}),
|
|
|
|
"var.empty_list": interfaceToVariableSwallowError([]interface{}{}),
|
|
|
|
"var.a_nested_list": interfaceToVariableSwallowError([]interface{}{[]string{"foo"}, []string{"baz"}}),
|
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
|
|
|
},
|
2015-01-13 21:06:04 +01:00
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
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
|
|
|
`${element(var.a_list, "1")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"baz",
|
|
|
|
false,
|
|
|
|
},
|
2014-11-07 19:23:02 +01:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
{
|
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
|
|
|
`${element(var.a_short_list, "0")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"foo",
|
|
|
|
false,
|
|
|
|
},
|
2014-11-07 19:23:02 +01:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Invalid index should wrap vs. out-of-bounds
|
|
|
|
{
|
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
|
|
|
`${element(var.a_list, "2")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
"foo",
|
|
|
|
false,
|
|
|
|
},
|
2014-11-07 19:23:02 +01:00
|
|
|
|
2016-02-22 23:47:17 +01:00
|
|
|
// Negative number should fail
|
|
|
|
{
|
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
|
|
|
`${element(var.a_short_list, "-1")}`,
|
2016-02-22 23:47:17 +01:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
2016-06-23 13:29:13 +02:00
|
|
|
// Empty list should fail
|
|
|
|
{
|
|
|
|
`${element(var.empty_list, 0)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
// Too many args
|
|
|
|
{
|
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
|
|
|
`${element(var.a_list, "0", "2")}`,
|
2015-01-13 21:06:04 +01:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2016-07-27 19:47:44 +02:00
|
|
|
|
|
|
|
// Only works on single-level lists
|
|
|
|
{
|
|
|
|
`${element(var.a_nested_list, "0")}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
2014-11-07 19:23:02 +01:00
|
|
|
},
|
2015-01-13 20:50:44 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-27 03:21:48 +02:00
|
|
|
func TestInterpolateFuncBasename(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${basename("/foo/bar/baz")}`,
|
|
|
|
"baz",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-09-25 09:23:36 +02:00
|
|
|
func TestInterpolateFuncBase64Encode(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// Regular base64 encoding
|
|
|
|
{
|
2015-10-04 00:12:51 +02:00
|
|
|
`${base64encode("abc123!?$*&()'-=@~")}`,
|
2015-09-25 09:23:36 +02:00
|
|
|
"YWJjMTIzIT8kKiYoKSctPUB+",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncBase64Decode(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
// Regular base64 decoding
|
|
|
|
{
|
2015-10-04 00:12:51 +02:00
|
|
|
`${base64decode("YWJjMTIzIT8kKiYoKSctPUB+")}`,
|
2015-09-25 09:23:36 +02:00
|
|
|
"abc123!?$*&()'-=@~",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Invalid base64 data decoding
|
|
|
|
{
|
2015-10-04 00:12:51 +02:00
|
|
|
`${base64decode("this-is-an-invalid-base64-data")}`,
|
2015-09-25 09:23:36 +02:00
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-10-20 03:49:51 +02:00
|
|
|
func TestInterpolateFuncLower(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${lower("HELLO")}`,
|
|
|
|
"hello",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${lower("")}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${lower()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolateFuncUpper(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${upper("hello")}`,
|
|
|
|
"HELLO",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${upper("")}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${upper()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-12-27 23:28:56 +01:00
|
|
|
func TestInterpolateFuncSha1(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${sha1("test")}`,
|
|
|
|
"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-01-17 00:54:04 +01:00
|
|
|
func TestInterpolateFuncSha256(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
2016-01-29 13:09:57 +01:00
|
|
|
{ // hexadecimal representation of sha256 sum
|
2016-01-17 00:54:04 +01:00
|
|
|
`${sha256("test")}`,
|
|
|
|
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-03 01:35:23 +02:00
|
|
|
func TestInterpolateFuncSha512(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${sha512("test")}`,
|
|
|
|
"ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-10-26 14:21:32 +02:00
|
|
|
func TestInterpolateFuncTitle(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${title("hello")}`,
|
|
|
|
"Hello",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${title("hello world")}`,
|
|
|
|
"Hello World",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${title("")}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
`${title()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-01-30 10:52:45 +01:00
|
|
|
func TestInterpolateFuncTrimSpace(t *testing.T) {
|
2016-01-30 00:28:04 +01:00
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
2016-01-30 10:52:45 +01:00
|
|
|
`${trimspace(" test ")}`,
|
2016-01-30 00:28:04 +01:00
|
|
|
"test",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:09:57 +01:00
|
|
|
func TestInterpolateFuncBase64Sha256(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${base64sha256("test")}`,
|
|
|
|
"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // This will differ because we're base64-encoding hex represantiation, not raw bytes
|
|
|
|
`${base64encode(sha256("test"))}`,
|
|
|
|
"OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTViMGYwMGEwOA==",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-03 01:35:23 +02:00
|
|
|
func TestInterpolateFuncBase64Sha512(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${base64sha512("test")}`,
|
|
|
|
"7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w==",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // This will differ because we're base64-encoding hex represantiation, not raw bytes
|
|
|
|
`${base64encode(sha512("test"))}`,
|
|
|
|
"ZWUyNmIwZGQ0YWY3ZTc0OWFhMWE4ZWUzYzEwYWU5OTIzZjYxODk4MDc3MmU0NzNmODgxOWE1ZDQ5NDBlMGRiMjdhYzE4NWY4YTBlMWQ1Zjg0Zjg4YmM4ODdmZDY3YjE0MzczMmMzMDRjYzVmYTlhZDhlNmY1N2Y1MDAyOGE4ZmY=",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-02-23 12:29:11 +01:00
|
|
|
func TestInterpolateFuncMd5(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${md5("tada")}`,
|
|
|
|
"ce47d07243bb6eaf5e1322c81baf9bbf",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Confirm that we're not trimming any whitespaces
|
|
|
|
`${md5(" tada ")}`,
|
|
|
|
"aadf191a583e53062de2d02c008141c4",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // We accept empty string too
|
|
|
|
`${md5("")}`,
|
|
|
|
"d41d8cd98f00b204e9800998ecf8427e",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-21 21:14:30 +01:00
|
|
|
func TestInterpolateFuncUUID(t *testing.T) {
|
|
|
|
results := make(map[string]bool)
|
|
|
|
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
ast, err := hil.Parse("${uuid()}")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-04-09 03:23:36 +02:00
|
|
|
result, err := hil.Eval(ast, langEvalConfig(nil))
|
2016-03-21 21:14:30 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-04-09 03:23:36 +02:00
|
|
|
if results[result.Value.(string)] {
|
|
|
|
t.Fatalf("Got unexpected duplicate uuid: %s", result.Value)
|
2016-03-21 21:14:30 +01:00
|
|
|
}
|
|
|
|
|
2016-04-09 03:23:36 +02:00
|
|
|
results[result.Value.(string)] = true
|
2016-03-21 21:14:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-01 20:51:01 +01:00
|
|
|
func TestInterpolateFuncTimestamp(t *testing.T) {
|
|
|
|
currentTime := time.Now().UTC()
|
|
|
|
ast, err := hil.Parse("${timestamp()}")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := hil.Eval(ast, langEvalConfig(nil))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
resultTime, err := time.Parse(time.RFC3339, result.Value.(string))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error parsing timestamp: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if resultTime.Sub(currentTime).Seconds() > 10.0 {
|
2017-03-20 18:15:27 +01:00
|
|
|
t.Fatalf("Timestamp Diff too large. Expected: %s\nReceived: %s", currentTime.Format(time.RFC3339), result.Value.(string))
|
2016-12-01 20:51:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
type testFunctionConfig struct {
|
|
|
|
Cases []testFunctionCase
|
2015-01-15 07:01:42 +01:00
|
|
|
Vars map[string]ast.Variable
|
2015-01-13 21:06:04 +01:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:50:44 +01:00
|
|
|
type testFunctionCase struct {
|
|
|
|
Input string
|
|
|
|
Result interface{}
|
|
|
|
Error bool
|
|
|
|
}
|
2014-11-07 19:23:02 +01:00
|
|
|
|
2015-01-13 21:06:04 +01:00
|
|
|
func testFunction(t *testing.T, config testFunctionConfig) {
|
|
|
|
for i, tc := range config.Cases {
|
2016-01-31 08:38:37 +01:00
|
|
|
ast, err := hil.Parse(tc.Input)
|
2015-01-13 20:50:44 +01:00
|
|
|
if err != nil {
|
2016-08-01 21:06:20 +02:00
|
|
|
t.Fatalf("Case #%d: input: %#v\nerr: %v", i, tc.Input, err)
|
2015-01-13 20:50:44 +01:00
|
|
|
}
|
|
|
|
|
2016-04-09 03:23:36 +02:00
|
|
|
result, err := hil.Eval(ast, langEvalConfig(config.Vars))
|
2015-10-08 14:48:04 +02:00
|
|
|
if err != nil != tc.Error {
|
2016-08-01 21:06:20 +02:00
|
|
|
t.Fatalf("Case #%d:\ninput: %#v\nerr: %v", i, tc.Input, err)
|
2014-11-07 19:23:02 +01:00
|
|
|
}
|
|
|
|
|
2016-04-09 03:23:36 +02:00
|
|
|
if !reflect.DeepEqual(result.Value, tc.Result) {
|
|
|
|
t.Fatalf("%d: bad output for input: %s\n\nOutput: %#v\nExpected: %#v",
|
|
|
|
i, tc.Input, result.Value, tc.Result)
|
2014-11-07 19:23:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-18 22:11:19 +01:00
|
|
|
|
|
|
|
func TestInterpolateFuncPathExpand(t *testing.T) {
|
|
|
|
homePath, err := homedir.Dir()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error getting home directory: %v", err)
|
|
|
|
}
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${pathexpand("~/test-file")}`,
|
|
|
|
filepath.Join(homePath, "test-file"),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pathexpand("~/another/test/file")}`,
|
|
|
|
filepath.Join(homePath, "another/test/file"),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pathexpand("/root/file")}`,
|
|
|
|
"/root/file",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pathexpand("/")}`,
|
|
|
|
"/",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${pathexpand()}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
2017-03-22 16:30:39 +01:00
|
|
|
|
|
|
|
func TestInterpolateFuncSubstr(t *testing.T) {
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
{
|
|
|
|
`${substr("foobar", 0, 0)}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${substr("foobar", 0, -1)}`,
|
|
|
|
"foobar",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${substr("foobar", 0, 3)}`,
|
|
|
|
"foo",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${substr("foobar", 3, 3)}`,
|
|
|
|
"bar",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${substr("foobar", -3, 3)}`,
|
|
|
|
"bar",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// empty string
|
|
|
|
{
|
|
|
|
`${substr("", 0, 0)}`,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
// invalid offset
|
|
|
|
{
|
|
|
|
`${substr("", 1, 0)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
// invalid length
|
|
|
|
{
|
|
|
|
`${substr("", 0, 1)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`${substr("", 0, -2)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
2017-05-22 12:02:32 +02:00
|
|
|
|
|
|
|
func TestInterpolateFuncBcrypt(t *testing.T) {
|
|
|
|
node, err := hil.Parse(`${bcrypt("test")}`)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := hil.Eval(node, langEvalConfig(nil))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
err = bcrypt.CompareHashAndPassword([]byte(result.Value.(string)), []byte("test"))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error comparing hash and password: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
testFunction(t, testFunctionConfig{
|
|
|
|
Cases: []testFunctionCase{
|
|
|
|
//Negative test for more than two parameters
|
|
|
|
{
|
|
|
|
`${bcrypt("test", 15, 12)}`,
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|