terraform/config/interpolate_funcs.go

127 lines
3.5 KiB
Go
Raw Normal View History

2014-07-21 21:56:03 +02:00
package config
2014-07-21 22:12:43 +02:00
import (
2015-01-13 21:47:54 +01:00
"bytes"
2014-07-21 22:12:43 +02:00
"fmt"
"io/ioutil"
"strconv"
2014-07-21 22:12:43 +02:00
"strings"
"github.com/hashicorp/terraform/config/lang/ast"
2014-07-21 22:12:43 +02:00
)
2014-07-21 21:56:03 +02:00
// Funcs is the mapping of built-in functions for configuration.
2015-01-15 07:01:42 +01:00
var Funcs map[string]ast.Function
2014-07-21 21:56:03 +02:00
func init() {
2015-01-15 07:01:42 +01:00
Funcs = map[string]ast.Function{
2015-01-13 21:47:54 +01:00
"concat": interpolationFuncConcat(),
2015-01-13 21:06:04 +01:00
"file": interpolationFuncFile(),
"join": interpolationFuncJoin(),
"element": interpolationFuncElement(),
2014-07-21 21:56:03 +02:00
}
}
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{
2015-01-13 21:47:54 +01:00
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
var b bytes.Buffer
for _, v := range args {
b.WriteString(v.(string))
}
return b.String(), nil
},
}
}
// 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{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
data, err := ioutil.ReadFile(args[0].(string))
if err != nil {
return "", err
}
return string(data), nil
},
}
}
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{
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
var list []string
for _, arg := range args[1:] {
parts := strings.Split(arg.(string), InterpSplitDelim)
list = append(list, parts...)
}
return strings.Join(list, args[0].(string)), nil
},
2014-10-10 06:22:35 +02: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{
2015-01-13 21:06:04 +01:00
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
k := fmt.Sprintf("var.%s.%s", args[0].(string), args[1].(string))
v, ok := vs[k]
if !ok {
return "", fmt.Errorf(
"lookup in '%s' failed to find '%s'",
args[0].(string), args[1].(string))
}
2015-01-14 19:40:43 +01:00
if v.Type != ast.TypeString {
return "", fmt.Errorf(
"lookup in '%s' for '%s' has bad type %s",
args[0].(string), args[1].(string), v.Type)
}
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
}
// 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{
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
list := strings.Split(args[0].(string), InterpSplitDelim)
index, err := strconv.Atoi(args[1].(string))
if err != nil {
return "", fmt.Errorf(
"invalid number for index, got %s", args[1])
}
v := list[index%len(list)]
return v, nil
},
}
}