2014-07-21 21:56:03 +02:00
|
|
|
package config
|
|
|
|
|
2014-07-21 22:12:43 +02:00
|
|
|
import (
|
2016-02-23 12:29:11 +01:00
|
|
|
"crypto/md5"
|
2015-12-27 23:28:56 +01:00
|
|
|
"crypto/sha1"
|
2016-01-17 00:54:04 +01:00
|
|
|
"crypto/sha256"
|
2015-09-25 09:23:36 +02:00
|
|
|
"encoding/base64"
|
2015-12-27 23:28:56 +01:00
|
|
|
"encoding/hex"
|
2016-03-29 03:02:06 +02:00
|
|
|
"encoding/json"
|
2015-05-06 05:34:40 +02:00
|
|
|
"errors"
|
2014-07-21 22:12:43 +02:00
|
|
|
"fmt"
|
2014-07-23 03:35:36 +02:00
|
|
|
"io/ioutil"
|
2015-10-22 17:10:42 +02:00
|
|
|
"net"
|
2015-03-02 18:37:40 +01:00
|
|
|
"regexp"
|
2015-06-02 23:48:38 +02:00
|
|
|
"sort"
|
2014-11-07 19:23:02 +01:00
|
|
|
"strconv"
|
2014-07-21 22:12:43 +02:00
|
|
|
"strings"
|
2015-01-13 20:50:44 +01:00
|
|
|
|
2015-10-22 17:10:42 +02:00
|
|
|
"github.com/apparentlymart/go-cidr/cidr"
|
2016-03-21 21:14:30 +01:00
|
|
|
"github.com/hashicorp/go-uuid"
|
2016-04-11 19:40:06 +02:00
|
|
|
"github.com/hashicorp/hil"
|
2016-01-31 08:38:37 +01:00
|
|
|
"github.com/hashicorp/hil/ast"
|
2015-03-31 01:52:39 +02:00
|
|
|
"github.com/mitchellh/go-homedir"
|
2014-07-21 22:12:43 +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
|
|
|
// stringSliceToVariableValue converts a string slice into the value
|
|
|
|
// required to be returned from interpolation functions which return
|
|
|
|
// TypeList.
|
|
|
|
func stringSliceToVariableValue(values []string) []ast.Variable {
|
|
|
|
output := make([]ast.Variable, len(values))
|
|
|
|
for index, value := range values {
|
|
|
|
output[index] = ast.Variable{
|
|
|
|
Type: ast.TypeString,
|
|
|
|
Value: value,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
func listVariableValueToStringSlice(values []ast.Variable) ([]string, error) {
|
|
|
|
output := make([]string, len(values))
|
|
|
|
for index, value := range values {
|
|
|
|
if value.Type != ast.TypeString {
|
|
|
|
return []string{}, fmt.Errorf("list has non-string element (%T)", value.Type.String())
|
|
|
|
}
|
|
|
|
output[index] = value.Value.(string)
|
|
|
|
}
|
|
|
|
return output, nil
|
|
|
|
}
|
|
|
|
|
2014-07-21 21:56:03 +02:00
|
|
|
// Funcs is the mapping of built-in functions for configuration.
|
2016-01-15 22:28:47 +01:00
|
|
|
func Funcs() map[string]ast.Function {
|
|
|
|
return map[string]ast.Function{
|
2016-02-24 10:16:34 +01:00
|
|
|
"base64decode": interpolationFuncBase64Decode(),
|
|
|
|
"base64encode": interpolationFuncBase64Encode(),
|
2016-01-29 13:09:57 +01:00
|
|
|
"base64sha256": interpolationFuncBase64Sha256(),
|
2015-10-22 17:10:42 +02:00
|
|
|
"cidrhost": interpolationFuncCidrHost(),
|
|
|
|
"cidrnetmask": interpolationFuncCidrNetmask(),
|
|
|
|
"cidrsubnet": interpolationFuncCidrSubnet(),
|
2015-11-08 07:34:56 +01:00
|
|
|
"coalesce": interpolationFuncCoalesce(),
|
2015-10-11 00:17:25 +02:00
|
|
|
"compact": interpolationFuncCompact(),
|
|
|
|
"concat": interpolationFuncConcat(),
|
|
|
|
"element": interpolationFuncElement(),
|
|
|
|
"file": interpolationFuncFile(),
|
|
|
|
"format": interpolationFuncFormat(),
|
|
|
|
"formatlist": interpolationFuncFormatList(),
|
|
|
|
"index": interpolationFuncIndex(),
|
|
|
|
"join": interpolationFuncJoin(),
|
2016-03-29 03:02:06 +02:00
|
|
|
"jsonencode": interpolationFuncJSONEncode(),
|
2015-10-11 00:17:25 +02:00
|
|
|
"length": interpolationFuncLength(),
|
2015-10-20 03:49:51 +02:00
|
|
|
"lower": interpolationFuncLower(),
|
2016-02-23 12:29:11 +01:00
|
|
|
"md5": interpolationFuncMd5(),
|
2016-03-21 21:14:30 +01:00
|
|
|
"uuid": interpolationFuncUUID(),
|
2015-10-11 00:17:25 +02:00
|
|
|
"replace": interpolationFuncReplace(),
|
2015-12-27 23:28:56 +01:00
|
|
|
"sha1": interpolationFuncSha1(),
|
2016-01-17 00:54:04 +01:00
|
|
|
"sha256": interpolationFuncSha256(),
|
2016-02-24 10:16:34 +01:00
|
|
|
"signum": interpolationFuncSignum(),
|
2016-06-11 18:36:29 +02:00
|
|
|
"sort": interpolationFuncSort(),
|
2016-02-24 10:16:34 +01:00
|
|
|
"split": interpolationFuncSplit(),
|
2016-01-30 10:51:28 +01:00
|
|
|
"trimspace": interpolationFuncTrimSpace(),
|
2015-10-20 03:49:51 +02:00
|
|
|
"upper": interpolationFuncUpper(),
|
2014-07-21 21:56:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 11:08:58 +02:00
|
|
|
// interpolationFuncCompact strips a list of multi-variable values
|
|
|
|
// (e.g. as returned by "split") of any empty strings.
|
|
|
|
func interpolationFuncCompact() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeList},
|
|
|
|
ReturnType: ast.TypeList,
|
2015-09-16 11:08:58 +02:00
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
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
|
|
|
inputList := args[0].([]ast.Variable)
|
|
|
|
|
|
|
|
var outputList []string
|
|
|
|
for _, val := range inputList {
|
|
|
|
if strVal, ok := val.Value.(string); ok {
|
|
|
|
if strVal == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
outputList = append(outputList, strVal)
|
|
|
|
}
|
2015-09-16 11:08:58 +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
|
|
|
return stringSliceToVariableValue(outputList), nil
|
2015-09-16 11:08:58 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-22 17:10:42 +02:00
|
|
|
// interpolationFuncCidrHost implements the "cidrhost" function that
|
|
|
|
// fills in the host part of a CIDR range address to create a single
|
|
|
|
// host address
|
|
|
|
func interpolationFuncCidrHost() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{
|
|
|
|
ast.TypeString, // starting CIDR mask
|
|
|
|
ast.TypeInt, // host number to insert
|
|
|
|
},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
hostNum := args[1].(int)
|
|
|
|
_, network, err := net.ParseCIDR(args[0].(string))
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid CIDR expression: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ip, err := cidr.Host(network, hostNum)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ip.String(), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// interpolationFuncCidrNetmask implements the "cidrnetmask" function
|
|
|
|
// that returns the subnet mask in IP address notation.
|
|
|
|
func interpolationFuncCidrNetmask() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{
|
|
|
|
ast.TypeString, // CIDR mask
|
|
|
|
},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
_, network, err := net.ParseCIDR(args[0].(string))
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid CIDR expression: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return net.IP(network.Mask).String(), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// interpolationFuncCidrSubnet implements the "cidrsubnet" function that
|
|
|
|
// adds an additional subnet of the given length onto an existing
|
|
|
|
// IP block expressed in CIDR notation.
|
|
|
|
func interpolationFuncCidrSubnet() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{
|
|
|
|
ast.TypeString, // starting CIDR mask
|
|
|
|
ast.TypeInt, // number of bits to extend the prefix
|
|
|
|
ast.TypeInt, // network number to append to the prefix
|
|
|
|
},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
extraBits := args[1].(int)
|
|
|
|
subnetNum := args[2].(int)
|
|
|
|
_, network, err := net.ParseCIDR(args[0].(string))
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("invalid CIDR expression: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// For portability with 32-bit systems where the subnet number
|
|
|
|
// will be a 32-bit int, we only allow extension of 32 bits in
|
|
|
|
// one call even if we're running on a 64-bit machine.
|
|
|
|
// (Of course, this is significant only for IPv6.)
|
|
|
|
if extraBits > 32 {
|
|
|
|
return nil, fmt.Errorf("may not extend prefix by more than 32 bits")
|
|
|
|
}
|
|
|
|
|
|
|
|
newNetwork, err := cidr.Subnet(network, extraBits, subnetNum)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return newNetwork.String(), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-08 07:34:56 +01:00
|
|
|
// interpolationFuncCoalesce implements the "coalesce" function that
|
|
|
|
// returns the first non null / empty string from the provided input
|
|
|
|
func interpolationFuncCoalesce() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Variadic: true,
|
|
|
|
VariadicType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
if len(args) < 2 {
|
|
|
|
return nil, fmt.Errorf("must provide at least two arguments")
|
|
|
|
}
|
|
|
|
for _, arg := range args {
|
|
|
|
argument := arg.(string)
|
|
|
|
|
|
|
|
if argument != "" {
|
|
|
|
return argument, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "", nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-13 21:47:54 +01:00
|
|
|
// interpolationFuncConcat implements the "concat" function that
|
|
|
|
// concatenates multiple strings. This isn't actually necessary anymore
|
|
|
|
// since our language supports string concat natively, but for backwards
|
|
|
|
// compat we do this.
|
2015-01-15 07:01:42 +01:00
|
|
|
func interpolationFuncConcat() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeAny},
|
|
|
|
ReturnType: ast.TypeList,
|
2015-01-13 21:47:54 +01:00
|
|
|
Variadic: 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
|
|
|
VariadicType: ast.TypeAny,
|
2015-01-13 21:47:54 +01:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
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
|
|
|
var finalListElements []string
|
2015-05-03 16:53:33 +02:00
|
|
|
|
|
|
|
for _, arg := range 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
|
|
|
// Append strings for backward compatibility
|
|
|
|
if argument, ok := arg.(string); ok {
|
|
|
|
finalListElements = append(finalListElements, argument)
|
2015-05-03 16:53:33 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// Otherwise variables
|
|
|
|
if argument, ok := arg.([]ast.Variable); ok {
|
|
|
|
for _, element := range argument {
|
2016-06-12 20:21:47 +02:00
|
|
|
t := element.Type
|
|
|
|
switch t {
|
|
|
|
case ast.TypeString:
|
|
|
|
finalListElements = append(finalListElements, element.Value.(string))
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("concat() does not support lists of %s", t.Printable())
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
continue
|
2015-05-03 16:53:33 +02:00
|
|
|
}
|
|
|
|
|
2016-06-12 20:21:47 +02:00
|
|
|
return nil, fmt.Errorf("arguments to concat() must be a string or list of strings")
|
2015-05-03 16:53:33 +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
|
|
|
return stringSliceToVariableValue(finalListElements), nil
|
2015-01-13 21:47:54 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-23 03:35:36 +02:00
|
|
|
// interpolationFuncFile implements the "file" function that allows
|
|
|
|
// loading contents from a file.
|
2015-01-15 07:01:42 +01:00
|
|
|
func interpolationFuncFile() ast.Function {
|
|
|
|
return ast.Function{
|
2015-01-13 20:50:44 +01:00
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2015-03-31 01:52:39 +02:00
|
|
|
path, err := homedir.Expand(args[0].(string))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
data, err := ioutil.ReadFile(path)
|
2015-01-13 20:50:44 +01:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(data), nil
|
|
|
|
},
|
2014-07-23 03:35:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-06 05:29:50 +02:00
|
|
|
// interpolationFuncFormat implements the "format" function that does
|
|
|
|
// string formatting.
|
2015-03-02 19:26:06 +01:00
|
|
|
func interpolationFuncFormat() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
Variadic: true,
|
|
|
|
VariadicType: ast.TypeAny,
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
format := args[0].(string)
|
|
|
|
return fmt.Sprintf(format, args[1:]...), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-06 05:34:40 +02:00
|
|
|
// interpolationFuncFormatList implements the "formatlist" function that does
|
|
|
|
// string formatting on lists.
|
|
|
|
func interpolationFuncFormatList() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeAny},
|
2015-05-06 05:34:40 +02:00
|
|
|
Variadic: true,
|
|
|
|
VariadicType: ast.TypeAny,
|
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
|
|
|
ReturnType: ast.TypeList,
|
2015-05-06 05:34:40 +02:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
// Make a copy of the variadic part of args
|
|
|
|
// to avoid modifying the original.
|
|
|
|
varargs := make([]interface{}, len(args)-1)
|
|
|
|
copy(varargs, args[1:])
|
|
|
|
|
|
|
|
// Convert arguments that are lists into slices.
|
|
|
|
// Confirm along the way that all lists have the same length (n).
|
|
|
|
var n int
|
|
|
|
for i := 1; i < len(args); i++ {
|
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
|
|
|
s, ok := args[i].([]ast.Variable)
|
2015-05-06 05:34:40 +02:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
2015-06-26 00:55:51 +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
|
|
|
parts, err := listVariableValueToStringSlice(s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-06-26 00:55:51 +02:00
|
|
|
|
|
|
|
// otherwise the list is sent down to be indexed
|
2015-05-06 05:34:40 +02:00
|
|
|
varargs[i-1] = parts
|
2015-06-26 00:55:51 +02:00
|
|
|
|
|
|
|
// Check length
|
2015-05-06 05:34:40 +02:00
|
|
|
if n == 0 {
|
|
|
|
// first list we've seen
|
|
|
|
n = len(parts)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if n != len(parts) {
|
|
|
|
return nil, fmt.Errorf("format: mismatched list lengths: %d != %d", n, len(parts))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if n == 0 {
|
|
|
|
return nil, errors.New("no lists in arguments to formatlist")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the formatting.
|
|
|
|
format := args[0].(string)
|
|
|
|
|
|
|
|
// Generate a list of formatted strings.
|
|
|
|
list := make([]string, n)
|
|
|
|
fmtargs := make([]interface{}, len(varargs))
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
for j, arg := range varargs {
|
|
|
|
switch arg := arg.(type) {
|
|
|
|
default:
|
|
|
|
fmtargs[j] = arg
|
|
|
|
case []string:
|
|
|
|
fmtargs[j] = arg[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
list[i] = fmt.Sprintf(format, fmtargs...)
|
|
|
|
}
|
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
|
|
|
return stringSliceToVariableValue(list), nil
|
2015-05-06 05:34:40 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-12 21:55:19 +02:00
|
|
|
// interpolationFuncIndex implements the "index" function that allows one to
|
|
|
|
// find the index of a specific element in a list
|
|
|
|
func interpolationFuncIndex() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeList, ast.TypeString},
|
2015-07-12 21:55:19 +02:00
|
|
|
ReturnType: ast.TypeInt,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
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
|
|
|
haystack := args[0].([]ast.Variable)
|
2015-07-12 21:55:19 +02:00
|
|
|
needle := args[1].(string)
|
|
|
|
for index, element := range haystack {
|
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
|
|
|
if needle == element.Value {
|
2015-07-12 21:55:19 +02:00
|
|
|
return index, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("Could not find '%s' in '%s'", needle, haystack)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-10 06:22:35 +02:00
|
|
|
// interpolationFuncJoin implements the "join" function that allows
|
|
|
|
// multi-variable values to be joined by some character.
|
2015-01-15 07:01:42 +01:00
|
|
|
func interpolationFuncJoin() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
Variadic: true,
|
|
|
|
VariadicType: ast.TypeList,
|
|
|
|
ReturnType: ast.TypeString,
|
2015-01-13 20:50:44 +01:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
var list []string
|
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
|
|
|
|
|
|
|
if len(args) < 2 {
|
|
|
|
return nil, fmt.Errorf("not enough arguments to join()")
|
|
|
|
}
|
|
|
|
|
2015-01-13 20:50:44 +01:00
|
|
|
for _, arg := range args[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
|
|
|
if parts, ok := arg.(ast.Variable); ok {
|
|
|
|
for _, part := range parts.Value.([]ast.Variable) {
|
|
|
|
list = append(list, part.Value.(string))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if parts, ok := arg.([]ast.Variable); ok {
|
|
|
|
for _, part := range parts {
|
|
|
|
list = append(list, part.Value.(string))
|
|
|
|
}
|
|
|
|
}
|
2015-01-13 20:50:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(list, args[0].(string)), nil
|
|
|
|
},
|
2014-10-10 06:22:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-29 03:02:06 +02:00
|
|
|
// interpolationFuncJSONEncode implements the "jsonencode" function that encodes
|
2016-05-18 19:45:22 +02:00
|
|
|
// a string, list, or map as its JSON representation. For now, values in the
|
|
|
|
// list or map may only be strings.
|
2016-03-29 03:02:06 +02:00
|
|
|
func interpolationFuncJSONEncode() ast.Function {
|
|
|
|
return ast.Function{
|
2016-05-18 19:45:22 +02:00
|
|
|
ArgTypes: []ast.Type{ast.TypeAny},
|
2016-03-29 03:02:06 +02:00
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2016-05-18 19:45:22 +02:00
|
|
|
var toEncode interface{}
|
|
|
|
|
|
|
|
switch typedArg := args[0].(type) {
|
|
|
|
case string:
|
|
|
|
toEncode = typedArg
|
|
|
|
|
|
|
|
case []ast.Variable:
|
|
|
|
// We preallocate the list here. Note that it's important that in
|
|
|
|
// the length 0 case, we have an empty list rather than nil, as
|
|
|
|
// they encode differently.
|
|
|
|
// XXX It would be nice to support arbitrarily nested data here. Is
|
|
|
|
// there an inverse of hil.InterfaceToVariable?
|
|
|
|
strings := make([]string, len(typedArg))
|
|
|
|
|
|
|
|
for i, v := range typedArg {
|
|
|
|
if v.Type != ast.TypeString {
|
|
|
|
return "", fmt.Errorf("list elements must be strings")
|
|
|
|
}
|
|
|
|
strings[i] = v.Value.(string)
|
|
|
|
}
|
|
|
|
toEncode = strings
|
|
|
|
|
|
|
|
case map[string]ast.Variable:
|
|
|
|
// XXX It would be nice to support arbitrarily nested data here. Is
|
|
|
|
// there an inverse of hil.InterfaceToVariable?
|
|
|
|
stringMap := make(map[string]string)
|
|
|
|
for k, v := range typedArg {
|
|
|
|
if v.Type != ast.TypeString {
|
|
|
|
return "", fmt.Errorf("map values must be strings")
|
|
|
|
}
|
|
|
|
stringMap[k] = v.Value.(string)
|
|
|
|
}
|
|
|
|
toEncode = stringMap
|
|
|
|
|
|
|
|
default:
|
|
|
|
return "", fmt.Errorf("unknown type for JSON encoding: %T", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
jEnc, err := json.Marshal(toEncode)
|
2016-03-29 03:02:06 +02:00
|
|
|
if err != nil {
|
2016-05-18 19:45:22 +02:00
|
|
|
return "", fmt.Errorf("failed to encode JSON data '%s'", toEncode)
|
2016-03-29 03:02:06 +02:00
|
|
|
}
|
|
|
|
return string(jEnc), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-02 18:37:40 +01:00
|
|
|
// interpolationFuncReplace implements the "replace" function that does
|
|
|
|
// string replacement.
|
|
|
|
func interpolationFuncReplace() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString, ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
search := args[1].(string)
|
|
|
|
replace := args[2].(string)
|
|
|
|
|
|
|
|
// We search/replace using a regexp if the string is surrounded
|
|
|
|
// in forward slashes.
|
2015-03-02 18:46:46 +01:00
|
|
|
if len(search) > 1 && search[0] == '/' && search[len(search)-1] == '/' {
|
2015-03-02 18:37:40 +01:00
|
|
|
re, err := regexp.Compile(search[1 : len(search)-1])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return re.ReplaceAllString(s, replace), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Replace(s, search, replace, -1), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-12 16:17:26 +02:00
|
|
|
func interpolationFuncLength() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeAny},
|
2015-04-12 16:17:26 +02:00
|
|
|
ReturnType: ast.TypeInt,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
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
|
|
|
subject := args[0]
|
2015-04-12 16:17:26 +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
|
|
|
switch typedSubject := subject.(type) {
|
|
|
|
case string:
|
|
|
|
return len(typedSubject), nil
|
|
|
|
case []ast.Variable:
|
|
|
|
return len(typedSubject), nil
|
2015-04-12 16:17:26 +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
|
|
|
|
|
|
|
return 0, fmt.Errorf("arguments to length() must be a string or list")
|
2015-04-12 16:17:26 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 16:36:31 +01:00
|
|
|
func interpolationFuncSignum() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeInt},
|
|
|
|
ReturnType: ast.TypeInt,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
num := args[0].(int)
|
|
|
|
switch {
|
|
|
|
case num < 0:
|
|
|
|
return -1, nil
|
|
|
|
case num > 0:
|
|
|
|
return +1, nil
|
|
|
|
default:
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-11 18:36:29 +02:00
|
|
|
// interpolationFuncSort sorts a list of a strings lexographically
|
|
|
|
func interpolationFuncSort() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeList},
|
|
|
|
ReturnType: ast.TypeList,
|
|
|
|
Variadic: false,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
inputList := args[0].([]ast.Variable)
|
|
|
|
|
|
|
|
// Ensure that all the list members are strings and
|
|
|
|
// create a string slice from them
|
|
|
|
members := make([]string, len(inputList))
|
|
|
|
for i, val := range inputList {
|
|
|
|
if val.Type != ast.TypeString {
|
|
|
|
return nil, fmt.Errorf(
|
|
|
|
"sort() may only be used with lists of strings - %s at index %d",
|
|
|
|
val.Type.String(), i)
|
|
|
|
}
|
|
|
|
|
|
|
|
members[i] = val.Value.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(members)
|
|
|
|
return stringSliceToVariableValue(members), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 22:59:16 +01:00
|
|
|
// interpolationFuncSplit implements the "split" function that allows
|
|
|
|
// strings to split into multi-variable values
|
|
|
|
func interpolationFuncSplit() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
|
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
|
|
|
ReturnType: ast.TypeList,
|
2015-01-28 22:59:16 +01:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2015-06-10 18:29:44 +02:00
|
|
|
sep := args[0].(string)
|
|
|
|
s := args[1].(string)
|
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
|
|
|
elements := strings.Split(s, sep)
|
|
|
|
return stringSliceToVariableValue(elements), nil
|
2015-01-28 22:59:16 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-21 21:56:03 +02:00
|
|
|
// interpolationFuncLookup implements the "lookup" function that allows
|
|
|
|
// dynamic lookups of map types within a Terraform configuration.
|
2015-01-15 07:01:42 +01:00
|
|
|
func interpolationFuncLookup(vs map[string]ast.Variable) ast.Function {
|
|
|
|
return ast.Function{
|
2016-05-26 02:25:15 +02:00
|
|
|
ArgTypes: []ast.Type{ast.TypeMap, ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Variadic: true,
|
|
|
|
VariadicType: ast.TypeString,
|
2015-01-13 21:06:04 +01:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2016-05-26 02:25:15 +02:00
|
|
|
defaultValue := ""
|
|
|
|
defaultValueSet := false
|
|
|
|
if len(args) > 2 {
|
|
|
|
defaultValue = args[2].(string)
|
|
|
|
defaultValueSet = true
|
|
|
|
}
|
|
|
|
if len(args) > 3 {
|
|
|
|
return "", fmt.Errorf("lookup() takes no more than three arguments")
|
|
|
|
}
|
2016-04-11 19:40:06 +02:00
|
|
|
index := args[1].(string)
|
|
|
|
mapVar := args[0].(map[string]ast.Variable)
|
|
|
|
|
|
|
|
v, ok := mapVar[index]
|
2015-01-13 21:06:04 +01:00
|
|
|
if !ok {
|
2016-05-26 02:25:15 +02:00
|
|
|
if defaultValueSet {
|
|
|
|
return defaultValue, nil
|
|
|
|
} else {
|
|
|
|
return "", fmt.Errorf(
|
|
|
|
"lookup failed to find '%s'",
|
|
|
|
args[1].(string))
|
|
|
|
}
|
2015-01-13 21:06:04 +01:00
|
|
|
}
|
2015-01-14 19:40:43 +01:00
|
|
|
if v.Type != ast.TypeString {
|
|
|
|
return "", fmt.Errorf(
|
2016-04-11 19:40:06 +02:00
|
|
|
"lookup for '%s' has bad type %s",
|
|
|
|
args[1].(string), v.Type)
|
2015-01-14 19:40:43 +01:00
|
|
|
}
|
2014-07-21 22:12:43 +02:00
|
|
|
|
2015-01-14 19:40:43 +01:00
|
|
|
return v.Value.(string), nil
|
2015-01-13 21:06:04 +01:00
|
|
|
},
|
2014-07-21 22:12:43 +02:00
|
|
|
}
|
2014-07-21 21:56:03 +02:00
|
|
|
}
|
2014-11-07 19:23:02 +01:00
|
|
|
|
|
|
|
// interpolationFuncElement implements the "element" function that allows
|
|
|
|
// a specific index to be looked up in a multi-variable value. Note that this will
|
|
|
|
// wrap if the index is larger than the number of elements in the multi-variable value.
|
2015-01-15 07:01:42 +01:00
|
|
|
func interpolationFuncElement() ast.Function {
|
|
|
|
return ast.Function{
|
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
|
|
|
ArgTypes: []ast.Type{ast.TypeList, ast.TypeString},
|
2015-01-13 20:50:44 +01:00
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
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
|
|
|
list := args[0].([]ast.Variable)
|
2015-01-13 20:50:44 +01:00
|
|
|
|
|
|
|
index, err := strconv.Atoi(args[1].(string))
|
2016-02-22 23:47:17 +01:00
|
|
|
if err != nil || index < 0 {
|
2015-01-13 20:50:44 +01:00
|
|
|
return "", fmt.Errorf(
|
|
|
|
"invalid number for index, got %s", args[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
|
|
|
resolvedIndex := index % len(list)
|
|
|
|
|
|
|
|
v := list[resolvedIndex].Value
|
2015-01-13 20:50:44 +01:00
|
|
|
return v, nil
|
|
|
|
},
|
2014-11-07 19:23:02 +01:00
|
|
|
}
|
|
|
|
}
|
2015-06-02 23:48:38 +02:00
|
|
|
|
|
|
|
// interpolationFuncKeys implements the "keys" function that yields a list of
|
|
|
|
// keys of map types within a Terraform configuration.
|
|
|
|
func interpolationFuncKeys(vs map[string]ast.Variable) ast.Function {
|
|
|
|
return ast.Function{
|
2016-04-11 19:40:06 +02:00
|
|
|
ArgTypes: []ast.Type{ast.TypeMap},
|
|
|
|
ReturnType: ast.TypeList,
|
2015-06-02 23:48:38 +02:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2016-04-11 19:40:06 +02:00
|
|
|
mapVar := args[0].(map[string]ast.Variable)
|
|
|
|
keys := make([]string, 0)
|
2015-06-02 23:48:38 +02:00
|
|
|
|
2016-04-11 19:40:06 +02:00
|
|
|
for k, _ := range mapVar {
|
|
|
|
keys = append(keys, k)
|
2015-06-02 23:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
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
|
|
|
//Keys are guaranteed to be strings
|
|
|
|
return stringSliceToVariableValue(keys), nil
|
2015-06-02 23:48:38 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// interpolationFuncValues implements the "values" function that yields a list of
|
|
|
|
// keys of map types within a Terraform configuration.
|
|
|
|
func interpolationFuncValues(vs map[string]ast.Variable) ast.Function {
|
|
|
|
return ast.Function{
|
2016-04-11 19:40:06 +02:00
|
|
|
ArgTypes: []ast.Type{ast.TypeMap},
|
|
|
|
ReturnType: ast.TypeList,
|
2015-06-02 23:48:38 +02:00
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2016-04-11 19:40:06 +02:00
|
|
|
mapVar := args[0].(map[string]ast.Variable)
|
|
|
|
keys := make([]string, 0)
|
2015-06-02 23:48:38 +02:00
|
|
|
|
2016-04-11 19:40:06 +02:00
|
|
|
for k, _ := range mapVar {
|
|
|
|
keys = append(keys, k)
|
2015-06-02 23:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
2016-04-11 19:40:06 +02:00
|
|
|
values := make([]string, len(keys))
|
|
|
|
for index, key := range keys {
|
|
|
|
if value, ok := mapVar[key].Value.(string); ok {
|
|
|
|
values[index] = value
|
|
|
|
} else {
|
|
|
|
return "", fmt.Errorf("values(): %q has element with bad type %s",
|
|
|
|
key, mapVar[key].Type)
|
2015-06-02 23:48:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-11 19:40:06 +02:00
|
|
|
variable, err := hil.InterfaceToVariable(values)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return variable.Value, nil
|
2015-06-02 23:48:38 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2015-09-25 09:23:36 +02:00
|
|
|
|
2015-10-04 00:12:51 +02:00
|
|
|
// interpolationFuncBase64Encode implements the "base64encode" function that
|
|
|
|
// allows Base64 encoding.
|
2015-09-25 09:23:36 +02:00
|
|
|
func interpolationFuncBase64Encode() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
return base64.StdEncoding.EncodeToString([]byte(s)), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-04 00:12:51 +02:00
|
|
|
// interpolationFuncBase64Decode implements the "base64decode" function that
|
|
|
|
// allows Base64 decoding.
|
2015-09-25 09:23:36 +02:00
|
|
|
func interpolationFuncBase64Decode() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
sDec, err := base64.StdEncoding.DecodeString(s)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed to decode base64 data '%s'", s)
|
|
|
|
}
|
|
|
|
return string(sDec), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2015-10-20 03:49:51 +02:00
|
|
|
|
|
|
|
// interpolationFuncLower implements the "lower" function that does
|
|
|
|
// string lower casing.
|
|
|
|
func interpolationFuncLower() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
toLower := args[0].(string)
|
|
|
|
return strings.ToLower(toLower), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-23 12:29:11 +01:00
|
|
|
func interpolationFuncMd5() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
h := md5.New()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
hash := hex.EncodeToString(h.Sum(nil))
|
|
|
|
return hash, nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-20 03:49:51 +02:00
|
|
|
// interpolationFuncUpper implements the "upper" function that does
|
|
|
|
// string upper casing.
|
|
|
|
func interpolationFuncUpper() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
toUpper := args[0].(string)
|
|
|
|
return strings.ToUpper(toUpper), nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2015-12-27 23:28:56 +01:00
|
|
|
|
|
|
|
func interpolationFuncSha1() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
h := sha1.New()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
hash := hex.EncodeToString(h.Sum(nil))
|
|
|
|
return hash, nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-01-17 00:54:04 +01:00
|
|
|
|
2016-01-29 13:09:57 +01:00
|
|
|
// hexadecimal representation of sha256 sum
|
2016-01-17 00:54:04 +01:00
|
|
|
func interpolationFuncSha256() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
h := sha256.New()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
hash := hex.EncodeToString(h.Sum(nil))
|
|
|
|
return hash, nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-01-30 00:28:04 +01:00
|
|
|
|
2016-01-30 10:51:28 +01:00
|
|
|
func interpolationFuncTrimSpace() ast.Function {
|
2016-01-30 00:28:04 +01:00
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
2016-01-30 10:51:28 +01:00
|
|
|
trimSpace := args[0].(string)
|
|
|
|
return strings.TrimSpace(trimSpace), nil
|
2016-01-30 00:28:04 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-01-29 13:09:57 +01:00
|
|
|
|
|
|
|
func interpolationFuncBase64Sha256() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{ast.TypeString},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
s := args[0].(string)
|
|
|
|
h := sha256.New()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
shaSum := h.Sum(nil)
|
|
|
|
encoded := base64.StdEncoding.EncodeToString(shaSum[:])
|
|
|
|
return encoded, nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-03-21 21:14:30 +01:00
|
|
|
|
|
|
|
func interpolationFuncUUID() ast.Function {
|
|
|
|
return ast.Function{
|
|
|
|
ArgTypes: []ast.Type{},
|
|
|
|
ReturnType: ast.TypeString,
|
|
|
|
Callback: func(args []interface{}) (interface{}, error) {
|
|
|
|
return uuid.GenerateUUID()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|