Skip to content

Commit

Permalink
Feature/add yaml conversion functions (#1)
Browse files Browse the repository at this point in the history
* feat: add yaml to/from functions

In the same vein of Masterminds#223, add YAML conversion functions. Fixes Masterminds#358.

* chore: bump yaml version to v3

---------

Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
  • Loading branch information
27149chen and blakepettersson committed May 16, 2023
1 parent 581758e commit 2b2845f
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 15 deletions.
29 changes: 29 additions & 0 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sprig
import (
"bytes"
"encoding/json"
"gopkg.in/yaml.v3"
"math/rand"
"reflect"
"strings"
Expand Down Expand Up @@ -153,6 +154,34 @@ func mustToRawJson(v interface{}) (string, error) {
return strings.TrimSuffix(buf.String(), "\n"), nil
}

// fromYaml decodes YAML into a structured value, ignoring errors.
func fromYaml(v string) interface{} {
output, _ := mustFromYaml(v)
return output
}

// mustFromYaml decodes YAML into a structured value, returning errors.
func mustFromYaml(v string) (interface{}, error) {
var output interface{}
err := yaml.Unmarshal([]byte(v), &output)
return output, err
}

// toYaml encodes an item into a YAML string
func toYaml(v interface{}) string {
output, _ := mustToYaml(v)
return string(output)
}

// toYaml encodes an item into a YAML string, returning errors
func mustToYaml(v interface{}) (string, error) {
output, err := yaml.Marshal(v)
if err != nil {
return "", err
}
return string(output), nil
}

// ternary returns the first value if the last value is true, otherwise returns the second value.
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
if v {
Expand Down
29 changes: 29 additions & 0 deletions defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,35 @@ func TestToJson(t *testing.T) {
}
}

func TestFromYaml(t *testing.T) {
dict := map[string]interface{}{"Input": `"foo": 55`}

tpl := `{{.Input | fromYaml}}`
expected := `map[foo:55]`
if err := runtv(tpl, expected, dict); err != nil {
t.Error(err)
}

tpl = `{{(.Input | fromYaml).foo}}`
expected = `55`
if err := runtv(tpl, expected, dict); err != nil {
t.Error(err)
}
}

func TestToYaml(t *testing.T) {
dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}}

tpl := `{{.Top | toYaml}}`
expected := `bool: true
number: 42
string: test
`
if err := runtv(tpl, expected, dict); err != nil {
t.Error(err)
}
}

func TestToPrettyJson(t *testing.T) {
dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}}
tpl := `{{.Top | toPrettyJson}}`
Expand Down
20 changes: 20 additions & 0 deletions docs/defaults.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ toRawJson .Item

The above returns unescaped JSON string representation of `.Item`.

## fromYaml, mustFromYaml

`fromYaml` decodes a YAML document into a structure. If the input cannot be decoded as YAML the function will return an empty string.
`mustFromYaml` will return an error in case the YAML is invalid.

```
fromYaml "foo: 55"
```

## toYaml, mustToYaml

The `toYaml` function encodes an item into a YAML string. If the item cannot be converted to YAML the function will return an empty string.
`mustToYaml` will return an error in case the item cannot be encoded in YAML.

```
toYaml .Item
```

The above returns YAML string representation of `.Item`.

## ternary

The `ternary` function takes two values, and a test value. If the test value is
Expand Down
33 changes: 18 additions & 15 deletions functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import (
//
// Use this to pass the functions into the template engine:
//
// tpl := template.New("foo").Funcs(sprig.FuncMap()))
//
// tpl := template.New("foo").Funcs(sprig.FuncMap()))
func FuncMap() template.FuncMap {
return HtmlFuncMap()
}
Expand Down Expand Up @@ -251,6 +250,10 @@ var genericMap = map[string]interface{}{
"mustToJson": mustToJson,
"mustToPrettyJson": mustToPrettyJson,
"mustToRawJson": mustToRawJson,
"fromYaml": fromYaml,
"toYaml": toYaml,
"mustFromYaml": mustFromYaml,
"mustToYaml": mustToYaml,
"ternary": ternary,
"deepCopy": deepCopy,
"mustDeepCopy": mustDeepCopy,
Expand Down Expand Up @@ -336,20 +339,20 @@ var genericMap = map[string]interface{}{
"mustChunk": mustChunk,

// Crypto:
"bcrypt": bcrypt,
"htpasswd": htpasswd,
"genPrivateKey": generatePrivateKey,
"derivePassword": derivePassword,
"buildCustomCert": buildCustomCertificate,
"genCA": generateCertificateAuthority,
"genCAWithKey": generateCertificateAuthorityWithPEMKey,
"genSelfSignedCert": generateSelfSignedCertificate,
"bcrypt": bcrypt,
"htpasswd": htpasswd,
"genPrivateKey": generatePrivateKey,
"derivePassword": derivePassword,
"buildCustomCert": buildCustomCertificate,
"genCA": generateCertificateAuthority,
"genCAWithKey": generateCertificateAuthorityWithPEMKey,
"genSelfSignedCert": generateSelfSignedCertificate,
"genSelfSignedCertWithKey": generateSelfSignedCertificateWithPEMKey,
"genSignedCert": generateSignedCertificate,
"genSignedCertWithKey": generateSignedCertificateWithPEMKey,
"encryptAES": encryptAES,
"decryptAES": decryptAES,
"randBytes": randBytes,
"genSignedCert": generateSignedCertificate,
"genSignedCertWithKey": generateSignedCertificateWithPEMKey,
"encryptAES": encryptAES,
"decryptAES": decryptAES,
"randBytes": randBytes,

// UUIDs:
"uuidv4": uuidv4,
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ require (
github.com/spf13/cast v1.3.1
github.com/stretchr/testify v1.5.1
golang.org/x/crypto v0.3.0
gopkg.in/yaml.v3 v3.0.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 comments on commit 2b2845f

Please sign in to comment.