Merge pull request #11542 from rifelpet/tf-fn

Add support for arbitrary terraform functions
This commit is contained in:
Kubernetes Prow Robot 2021-05-21 06:30:53 -07:00 committed by GitHub
commit 06835e219d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 29 deletions

View File

@ -20,6 +20,7 @@ import (
"fmt"
"reflect"
"sort"
"strings"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
@ -103,11 +104,11 @@ func writeValue(body *hclwrite.Body, key string, value cty.Value) {
// key = res_type.res_name.res_prop
// key = file("${module.path}/foo")
func writeLiteral(body *hclwrite.Body, key string, literal *terraformWriter.Literal) {
if literal.FilePath != "" {
if literal.FnName != "" {
tokens := hclwrite.Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte(fmt.Sprintf("%v(%q)", literal.FileFn, literal.FilePath)),
Bytes: []byte(fmt.Sprintf("%v(%v)", literal.FnName, strings.Join(literal.FnArgs, ", "))),
},
}
body.SetAttributeRaw(key, tokens)
@ -193,8 +194,11 @@ func writeMap(body *hclwrite.Body, key string, values map[string]cty.Value) {
if literal, ok := refLiteral.Interface().(*terraformWriter.Literal); err == nil && ok {
// For maps of literals we currently only support file references
// If we ever need to support a map of strings to resource property references that can be added here
if literal.FilePath != "" {
tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenIdent, Bytes: []byte(fmt.Sprintf("%v(%q)", literal.FileFn, literal.FilePath))})
if literal.FnName != "" {
tokens = append(tokens, &hclwrite.Token{
Type: hclsyntax.TokenIdent,
Bytes: []byte(fmt.Sprintf("%v(%v)", literal.FnName, strings.Join(literal.FnArgs, ", "))),
})
} else if literal.Value != "" {
tokens = append(tokens, []*hclwrite.Token{
{Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}, SpacesBefore: 1},

View File

@ -133,7 +133,7 @@ func TestWriteLiteral(t *testing.T) {
},
{
name: "file",
literal: terraformWriter.LiteralFileExpression("${path.module}/foo", false),
literal: terraformWriter.LiteralFunctionExpression("file", []string{"\"${path.module}/foo\""}),
expected: `foo = file("${path.module}/foo")`,
},
}
@ -272,13 +272,15 @@ func TestWriteMapLiterals(t *testing.T) {
{
name: "literal values",
values: map[string]terraformWriter.Literal{
"key1": *terraformWriter.LiteralFileExpression("${module.path}/path/to/value1", false),
"key2": *terraformWriter.LiteralFileExpression("${module.path}/path/to/value2", true),
"key1": *terraformWriter.LiteralFunctionExpression("file", []string{"\"${module.path}/path/to/value1\""}),
"key2": *terraformWriter.LiteralFunctionExpression("filebase64", []string{"\"${module.path}/path/to/value2\""}),
"key3": *terraformWriter.LiteralFunctionExpression("cidrsubnet", []string{"\"172.16.0.0/12\"", "4", "2"}),
},
expected: `
metadata = {
"key1" = file("${module.path}/path/to/value1")
"key2" = filebase64("${module.path}/path/to/value2")
"key3" = cidrsubnet("172.16.0.0/12", 4, 2)
}
`,
},

View File

@ -20,17 +20,11 @@ import (
"encoding/json"
"fmt"
"sort"
"strings"
"k8s.io/klog/v2"
)
type fileFn string
const (
fileFnFile fileFn = "file"
fileFnFileBase64 fileFn = "filebase64"
)
// Literal represents a literal in terraform syntax
type Literal struct {
// Value is only used in JSON output via the TerraformJSON feature flag
@ -43,10 +37,12 @@ type Literal struct {
ResourceName string `cty:"resource_name"`
// ResourceProp represents the property of a resource in a literal reference
ResourceProp string `cty:"resource_prop"`
// FilePath represents the path for a file reference
FilePath string `cty:"file_path"`
// FileFn represents the function used to reference the file
FileFn fileFn `cty:"file_fn"`
// FnName represents the name of a terraform function.
FnName string `cty:"fn_name"`
// FnArgs contains string representations of arguments to the function call.
// Any string arguments must be quoted.
FnArgs []string `cty:"fn_arg"`
}
var _ json.Marshaler = &Literal{}
@ -55,15 +51,11 @@ func (l *Literal) MarshalJSON() ([]byte, error) {
return json.Marshal(&l.Value)
}
func LiteralFileExpression(modulePath string, base64 bool) *Literal {
fn := fileFnFile
if base64 {
fn = fileFnFileBase64
}
func LiteralFunctionExpression(functionName string, args []string) *Literal {
return &Literal{
Value: fmt.Sprintf("${%v(%q)}", fn, modulePath),
FilePath: modulePath,
FileFn: fn,
Value: fmt.Sprintf("${%v(%v)}", functionName, strings.Join(args, ", ")),
FnName: functionName,
FnArgs: args,
}
}

View File

@ -75,9 +75,12 @@ func (t *TerraformWriter) AddFileBytes(resourceType string, resourceName string,
p := path.Join("data", id)
t.Files[p] = data
modulePath := path.Join("${path.module}", p)
l := LiteralFileExpression(modulePath, base64)
return l, nil
modulePath := fmt.Sprintf("%q", path.Join("${path.module}", p))
fn := "file"
if base64 {
fn = "filebase64"
}
return LiteralFunctionExpression(fn, []string{modulePath}), nil
}
func (t *TerraformWriter) RenderResource(resourceType string, resourceName string, e interface{}) error {