cmd/hcldec: make cty stdlib functions available to specs

In a few specific portions of the spec format it's convenient to have
access to some of the functions defined in the cty stdlib. Here we allow
them to be used when constructing the value for a "literal" spec and in
the result expression for a "transform" spec.
This commit is contained in:
Martin Atkins 2018-02-04 10:33:35 -08:00
parent 1ba92ee170
commit 6c3ae68a0e
3 changed files with 58 additions and 4 deletions

View File

@ -274,7 +274,8 @@ literal {
`literal` spec blocks accept the following argument:
* `value` (required) - The value to return.
* `value` (required) - The value to return. This attribute may be an expression
that uses [functions](#functions).
`literal` is a leaf spec type, so no nested spec blocks are permitted.
@ -330,6 +331,30 @@ transform {
spec. The variable `nested` is defined when evaluating this expression, with
the result value of the nested spec.
The `result` expression may use [functions](#functions).
## Functions
Certain expressions within a specification may use the following functions.
The documentation for each spec type above specifies where functions may
be used.
* `abs(number)` returns the absolute (positive) value of the given number.
* `coalesce(vals...)` returns the first non-null value given.
* `concat(lists...)` concatenates together all of the given lists to produce a new list.
* `hasindex(val, idx)` returns true if the expression `val[idx]` could succeed.
* `int(number)` returns the integer portion of the given number, rounding towards zero.
* `jsondecode(str)` interprets the given string as JSON and returns the resulting data structure.
* `jsonencode(val)` returns a JSON-serialized version of the given value.
* `length(collection)` returns the number of elements in the given collection (list, set, map, object, or tuple).
* `lower(string)` returns the given string with all uppercase letters converted to lowercase.
* `max(numbers...)` returns the greatest of the given numbers.
* `min(numbers...)` returns the smallest of the given numbers.
* `reverse(string)` returns the given string with all of the characters in reverse order.
* `strlen(string)` returns the number of characters in the given string.
* `substr(string, offset, length)` returns the requested substring of the given string.
* `upper(string)` returns the given string with all lowercase letters converted to uppercase.
## Type Expressions
Type expressions are used to describe the expected type of an attribute, as

View File

@ -9,6 +9,10 @@ import (
"github.com/zclconf/go-cty/cty"
)
var specCtx = &hcl.EvalContext{
Functions: specFuncs,
}
func loadSpecFile(filename string) (hcldec.Spec, hcl.Diagnostics) {
file, diags := parser.ParseHCLFile(filename)
if diags.HasErrors() {
@ -382,7 +386,7 @@ func decodeLiteralSpec(body hcl.Body) (hcldec.Spec, hcl.Diagnostics) {
}
var args content
diags := gohcl.DecodeBody(body, nil, &args)
diags := gohcl.DecodeBody(body, specCtx, &args)
if diags.HasErrors() {
return errSpec, diags
}
@ -455,8 +459,9 @@ func decodeTransformSpec(body hcl.Body) (hcldec.Spec, hcl.Diagnostics) {
}
spec := &hcldec.TransformExprSpec{
Expr: args.Result,
VarName: "nested",
Expr: args.Result,
VarName: "nested",
TransformCtx: specCtx,
}
nestedContent, nestedDiags := args.Nested.Content(specSchemaUnlabelled)

24
cmd/hcldec/spec_funcs.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"github.com/zclconf/go-cty/cty/function"
"github.com/zclconf/go-cty/cty/function/stdlib"
)
var specFuncs = map[string]function.Function{
"abs": stdlib.AbsoluteFunc,
"coalesce": stdlib.CoalesceFunc,
"concat": stdlib.ConcatFunc,
"hasindex": stdlib.HasIndexFunc,
"int": stdlib.IntFunc,
"jsondecode": stdlib.JSONDecodeFunc,
"jsonencode": stdlib.JSONEncodeFunc,
"length": stdlib.LengthFunc,
"lower": stdlib.LowerFunc,
"max": stdlib.MaxFunc,
"min": stdlib.MinFunc,
"reverse": stdlib.ReverseFunc,
"strlen": stdlib.StrlenFunc,
"substr": stdlib.SubstrFunc,
"upper": stdlib.UpperFunc,
}