Browse Source

Merge pull request #1254 from marcincuber/feat/yaml

Adding toYaml fromYaml helper functions
paul-the-alien[bot] 3 years ago
parent
commit
e4fbc633a1
5 changed files with 81 additions and 4 deletions
  1. 2 0
      docs/guides-templating.md
  2. 1 1
      go.mod
  3. 3 0
      pkg/template/v2/template.go
  4. 27 3
      pkg/template/v2/template_test.go
  5. 48 0
      pkg/template/v2/yaml.go

+ 2 - 0
docs/guides-templating.md

@@ -93,6 +93,8 @@ In addition to that you can use over 200+ [sprig functions](http://masterminds.g
 
 | jwkPublicKeyPem | Takes an json-serialized JWK and returns an PEM block of type `PUBLIC KEY` that contains the public key. [See here](https://golang.org/pkg/crypto/x509/#MarshalPKIXPublicKey) for details. |
 | jwkPrivateKeyPem | Takes an json-serialized JWK as `string` and returns an PEM block of type `PRIVATE KEY` that contains the private key in PKCS #8 format. [See here](https://golang.org/pkg/crypto/x509/#MarshalPKCS8PrivateKey) for details. |
+| toYaml | Takes an interface, marshals it to yaml. It returns a string, even on marshal error (empty string). |
+| fromYaml | Function converts a YAML document into a map[string]interface{}. |
 
 ## Migrating from v1
 

+ 1 - 1
go.mod

@@ -101,6 +101,7 @@ require (
 	github.com/fluxcd/helm-controller/api v0.22.0
 	github.com/fluxcd/pkg/apis/meta v0.14.1
 	github.com/fluxcd/source-controller/api v0.24.1
+	sigs.k8s.io/yaml v1.3.0
 )
 
 require (
@@ -297,5 +298,4 @@ require (
 	sigs.k8s.io/kustomize/api v0.10.1 // indirect
 	sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
-	sigs.k8s.io/yaml v1.3.0 // indirect
 )

+ 3 - 0
pkg/template/v2/template.go

@@ -32,6 +32,9 @@ var tplFuncs = tpl.FuncMap{
 
 	"jwkPublicKeyPem":  jwkPublicKeyPem,
 	"jwkPrivateKeyPem": jwkPrivateKeyPem,
+
+	"toYaml":   toYAML,
+	"fromYaml": fromYAML,
 }
 
 // So other templating calls can use the same extra functions.

+ 27 - 3
pkg/template/v2/template_test.go

@@ -159,7 +159,7 @@ func TestExecute(t *testing.T) {
 			},
 		},
 		{
-			name: "fromJSON func",
+			name: "fromJson func",
 			tpl: map[string][]byte{
 				"foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo }}"),
 			},
@@ -171,7 +171,7 @@ func TestExecute(t *testing.T) {
 			},
 		},
 		{
-			name: "from & toJSON func",
+			name: "from & toJson func",
 			tpl: map[string][]byte{
 				"foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo | toJson }}"),
 			},
@@ -183,6 +183,30 @@ func TestExecute(t *testing.T) {
 			},
 		},
 		{
+			name: "fromJson & toYaml func",
+			tpl: map[string][]byte{
+				"foo": []byte("{{ $var := .secret | fromJson | toYaml }}{{ $var }}"),
+			},
+			data: map[string][]byte{
+				"secret": []byte(`{"foo": "bar"}`),
+			},
+			expetedData: map[string][]byte{
+				"foo": []byte(`foo: bar`),
+			},
+		},
+		{
+			name: "fromYaml & toJson func",
+			tpl: map[string][]byte{
+				"foo": []byte("{{ $var := .secret | fromYaml | toJson }}{{ $var }}"),
+			},
+			data: map[string][]byte{
+				"secret": []byte(`foo: bar`),
+			},
+			expetedData: map[string][]byte{
+				"foo": []byte(`{"foo":"bar"}`),
+			},
+		},
+		{
 			name: "use sprig functions",
 			tpl: map[string][]byte{
 				"foo": []byte(`{{ .path | ext }}`),
@@ -302,7 +326,7 @@ func TestExecute(t *testing.T) {
 			expErr: "unable to decode pkcs12",
 		},
 		{
-			name: "fromJSON error",
+			name: "fromJson error",
 			tpl: map[string][]byte{
 				"key": []byte(`{{ "{ # no json # }" | fromJson }}`),
 			},

+ 48 - 0
pkg/template/v2/yaml.go

@@ -0,0 +1,48 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package template
+
+import (
+	"strings"
+
+	"sigs.k8s.io/yaml"
+)
+
+// toYAML takes an interface, marshals it to yaml, and returns a string. It will
+// always return a string, even on marshal error (empty string).
+//
+// This is designed to be called from a template.
+func toYAML(v interface{}) string {
+	data, err := yaml.Marshal(v)
+	if err != nil {
+		// Swallow errors inside of a template.
+		return ""
+	}
+	return strings.TrimSuffix(string(data), "\n")
+}
+
+// fromYAML converts a YAML document into a map[string]interface{}.
+//
+// This is not a general-purpose YAML parser, and will not parse all valid
+// YAML documents. Additionally, because its intended use is within templates
+// it tolerates errors. It will insert the returned error message string into
+// m["Error"] in the returned map.
+func fromYAML(str string) map[string]interface{} {
+	m := map[string]interface{}{}
+
+	if err := yaml.Unmarshal([]byte(str), &m); err != nil {
+		m["Error"] = err.Error()
+	}
+	return m
+}