lang: yamldecode and yamlencode functions
These follow the same principle as jsondecode and jsonencode, but use YAML instead of JSON. YAML has a much more complex information model than JSON, so we can only support a subset of it during decoding, but hopefully the subset supported here is a useful one. Because there are many different ways to _generate_ YAML, the yamlencode function is forced to make some decisions, and those decisions are likely to affect compatibility with other real-world YAML parsers. Although the format here is intended to be generic and compatible, we may find that there are problems with it that'll we'll want to adjust for in a future release, so yamlencode is therefore marked as experimental for now until the underlying library is ready to commit to ongoing byte-for-byte compatibility in serialization. The main use-case here is met by yamldecode, which will allow reading in files written in YAML format by humans for use in Terraform modules, in situations where a higher-level input format than direct Terraform language declarations is helpful.
This commit is contained in:
parent
3eb379f4d4
commit
382e1ca821
|
@ -3,6 +3,7 @@ package lang
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
ctyyaml "github.com/zclconf/go-cty-yaml"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/function"
|
||||
"github.com/zclconf/go-cty/cty/function/stdlib"
|
||||
|
@ -116,6 +117,8 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
"urlencode": funcs.URLEncodeFunc,
|
||||
"uuid": funcs.UUIDFunc,
|
||||
"values": funcs.ValuesFunc,
|
||||
"yamldecode": ctyyaml.YAMLDecodeFunc,
|
||||
"yamlencode": ctyyaml.YAMLEncodeFunc,
|
||||
"zipmap": funcs.ZipmapFunc,
|
||||
}
|
||||
|
||||
|
|
|
@ -787,6 +787,29 @@ func TestFunctions(t *testing.T) {
|
|||
},
|
||||
},
|
||||
|
||||
"yamldecode": {
|
||||
{
|
||||
`yamldecode("true")`,
|
||||
cty.True,
|
||||
},
|
||||
},
|
||||
|
||||
"yamlencode": {
|
||||
{
|
||||
`yamlencode(["foo", "bar", true])`,
|
||||
cty.StringVal("- \"foo\"\n- \"bar\"\n- true\n"),
|
||||
},
|
||||
{
|
||||
`yamlencode({a = "b", c = "d"})`,
|
||||
cty.StringVal("\"a\": \"b\"\n\"c\": \"d\"\n"),
|
||||
},
|
||||
{
|
||||
`yamlencode(true)`,
|
||||
// the ... here is an "end of document" marker, produced for implied primitive types only
|
||||
cty.StringVal("true\n...\n"),
|
||||
},
|
||||
},
|
||||
|
||||
"zipmap": {
|
||||
{
|
||||
`zipmap(["hello", "bar"], ["world", "baz"])`,
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "yamldecode - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-encoding-yamldecode"
|
||||
description: |-
|
||||
The yamldecode function decodes a YAML string into a representation of its
|
||||
value.
|
||||
---
|
||||
|
||||
# `yamldecode` Function
|
||||
|
||||
-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and
|
||||
earlier, see
|
||||
[0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html).
|
||||
|
||||
`yamldecode` parses a string as a subset of YAML, and produces a representation
|
||||
of its value.
|
||||
|
||||
This function supports a subset of [YAML 1.2](https://yaml.org/spec/1.2/spec.html),
|
||||
as described below.
|
||||
|
||||
This function maps YAML values to
|
||||
[Terraform language values](../expressions.html#types-and-values)
|
||||
in the following way:
|
||||
|
||||
| YAML type | Terraform type |
|
||||
| ------------- | ------------------------------------------------------------------ |
|
||||
| `!!str` | `string` |
|
||||
| `!!float` | `number` |
|
||||
| `!!int` | `number` |
|
||||
| `!!bool` | `bool` |
|
||||
| `!!map` | `object(...)` with attribute types determined per this table |
|
||||
| `!!seq` | `tuple(...)` with element types determined per this table |
|
||||
| `!!null` | The Terraform language `null` value |
|
||||
| `!!timestamp` | `string` in [RFC 3339](https://tools.ietf.org/html/rfc3339) format |
|
||||
| `!!binary` | `string` containing base64-encoded representation |
|
||||
|
||||
The Terraform language automatic type conversion rules mean that you don't
|
||||
usually need to worry about exactly what type is produced for a given value,
|
||||
and can just use the result in an intuitive way.
|
||||
|
||||
Note though that the mapping above is ambiguous -- several different source
|
||||
types map to the same target type -- and so round-tripping through `yamldecode`
|
||||
and then `yamlencode` cannot produce an identical result.
|
||||
|
||||
YAML is a complex language and it supports a number of possibilities that the
|
||||
Terraform language's type system cannot represent. Therefore this YAML decoder
|
||||
supports only a subset of YAML 1.2, with restrictions including the following:
|
||||
|
||||
- Although aliases to earlier anchors are supported, cyclic data structures
|
||||
(where a reference to a collection appears inside that collection) are not.
|
||||
If `yamldecode` detects such a structure then it will return an error.
|
||||
|
||||
- Only the type tags shown in the above table (or equivalent alternative
|
||||
representations of those same tags) are supported. Any other tags will
|
||||
result in an error.
|
||||
|
||||
- Only one YAML document is permitted. If multiple documents are present in
|
||||
the given string then this function will return an error.
|
||||
|
||||
## Examples
|
||||
|
||||
```
|
||||
> yamldecode("{\"hello\": \"world\"}")
|
||||
{
|
||||
"hello" = "world"
|
||||
}
|
||||
|
||||
> yamldecode("true")
|
||||
true
|
||||
|
||||
> yamldecode("{a: &foo [1, 2, 3], b: *foo}")
|
||||
{
|
||||
"a" = [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
"b" = [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
}
|
||||
|
||||
> yamldecode("{a: &foo [1, *foo, 3]}")
|
||||
|
||||
Error: Error in function call
|
||||
|
||||
Call to function "yamldecode" failed: cannot refer to anchor "foo" from inside
|
||||
its own definition.
|
||||
|
||||
> yamldecode("{a: !not-supported foo}")
|
||||
|
||||
Error: Error in function call
|
||||
|
||||
Call to function "yamldecode" failed: unsupported tag "!not-supported".
|
||||
```
|
||||
|
||||
## Related Functions
|
||||
|
||||
- [`jsondecode`](./jsondecode.html) is a similar operation using JSON instead
|
||||
of YAML.
|
||||
- [`yamlencode`](./yamlencode.html) performs the opposite operation, _encoding_
|
||||
a value as YAML.
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "yamlencode - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-encoding-yamlencode"
|
||||
description: |-
|
||||
The yamlencode function encodes a given value as a YAML string.
|
||||
---
|
||||
|
||||
# `yamlencode` Function
|
||||
|
||||
-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and
|
||||
earlier, see
|
||||
[0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html).
|
||||
|
||||
`yamlencode` encodes a given value to a string using
|
||||
[YAML 1.2](https://yaml.org/spec/1.2/spec.html) block syntax.
|
||||
|
||||
~> **Warning:** This function is currently **experimental** and its exact
|
||||
result format may change in future versions of Terraform, based on feedback.
|
||||
Do not use `yamldecode` to construct a value for any resource argument where
|
||||
changes to the result would be disruptive. To get a consistent string
|
||||
representation of a value use [`jsonencode`](./jsonencode.html) instead; its
|
||||
results are also valid YAML because YAML is a JSON superset.
|
||||
|
||||
<!--
|
||||
The condition for removing the above warning is that the underlying
|
||||
go-cty-yaml module makes a stable release with a commitment to guarantee
|
||||
that the representation of particular input will not change without a
|
||||
major release. It is not making that commitment at the time of writing to
|
||||
allow for responding to user feedback about its output format, since YAML
|
||||
is a very flexible format and its initial decisions may prove to be
|
||||
sub-optimal when generating YAML intended for specific external consumers.
|
||||
-->
|
||||
|
||||
This function maps
|
||||
[Terraform language values](../expressions.html#types-and-values)
|
||||
to YAML tags in the following way:
|
||||
|
||||
| Terraform type | YAML type |
|
||||
| -------------- | -------------------- |
|
||||
| `string` | `!!str` |
|
||||
| `number` | `!!float` or `!!int` |
|
||||
| `bool` | `!!bool` |
|
||||
| `list(...)` | `!!seq` |
|
||||
| `set(...)` | `!!seq` |
|
||||
| `tuple(...)` | `!!seq` |
|
||||
| `map(...)` | `!!map` |
|
||||
| `object(...)` | `!!map` |
|
||||
| Null value | `!!null` |
|
||||
|
||||
`yamlencode` uses the implied syntaxes for all of the above types, so it does
|
||||
not generate explicit YAML tags.
|
||||
|
||||
Because the YAML format cannot fully represent all of the Terraform language
|
||||
types, passing the `yamlencode` result to `yamldecode` will not produce an
|
||||
identical value, but the Terraform language automatic type conversion rules
|
||||
mean that this is rarely a problem in practice.
|
||||
|
||||
## Examples
|
||||
|
||||
```
|
||||
> yamlencode({"a":"b", "c":"d"})
|
||||
"a": "b"
|
||||
"c": "d"
|
||||
|
||||
> yamlencode({"foo":[1, 2, 3], "bar": "baz"})
|
||||
"bar": "baz"
|
||||
"foo":
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
> yamlencode({"foo":[1, {"a":"b","c":"d"}, 3], "bar": "baz"})
|
||||
"bar": "baz"
|
||||
"foo":
|
||||
- 1
|
||||
- "a": "b"
|
||||
"c": "d"
|
||||
- 3
|
||||
```
|
||||
|
||||
`yamlencode` always uses YAML's "block style" for mappings and sequences, unless
|
||||
the mapping or sequence is empty. To generate flow-style YAML, use
|
||||
[`jsonencode`](./jsonencode.html) instead: YAML flow-style is a superset
|
||||
of JSON syntax.
|
||||
|
||||
## Related Functions
|
||||
|
||||
- [`jsonencode`](./jsonencode.html) is a similar operation using JSON instead
|
||||
of YAML.
|
||||
- [`yamldecode`](./yamldecode.html) performs the opposite operation, _decoding_
|
||||
a YAML string to obtain its represented value.
|
|
@ -257,6 +257,14 @@
|
|||
<a href="/docs/configuration/functions/urlencode.html">urlencode</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/docs/configuration/functions/yamldecode.html">yamldecode</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/docs/configuration/functions/yamlencode.html">yamlencode</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
Loading…
Reference in New Issue