Util functions for kyaml <-> kunstruct compatibility

This commit is contained in:
Phillip Wittrock
2020-03-23 11:19:35 -07:00
parent 7629a03dd6
commit d41df982c5
2 changed files with 137 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtersutil
import (
"encoding/json"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// ApplyToJSON applies the filter to the json objects.
func ApplyToJSON(filter kio.Filter, objs ...marshalerUnmarshaler) error {
var nodes []*yaml.RNode
for i := range objs {
node, err := getRNode(objs[i])
if err != nil {
return err
}
nodes = append(nodes, node)
l, err := filter.Filter([]*yaml.RNode{node})
if err != nil {
return err
}
err = setRNode(objs[i], l[0])
if err != nil {
return err
}
}
_, err := filter.Filter(nodes)
if err != nil {
return err
}
for i := range nodes {
err = setRNode(objs[i], nodes[i])
if err != nil {
return err
}
}
return nil
}
type marshalerUnmarshaler interface {
json.Unmarshaler
json.Marshaler
}
// getRNode converts k into an RNode
func getRNode(k json.Marshaler) (*yaml.RNode, error) {
j, err := k.MarshalJSON()
if err != nil {
return nil, err
}
return yaml.Parse(string(j))
}
// setRNode marshals node into k
func setRNode(k json.Unmarshaler, node *yaml.RNode) error {
s, err := node.String()
if err != nil {
return err
}
m := map[string]interface{}{}
if err := yaml.Unmarshal([]byte(s), &m); err != nil {
return err
}
b, err := json.Marshal(m)
if err != nil {
return err
}
return k.UnmarshalJSON(b)
}

View File

@@ -0,0 +1,60 @@
package filtersutil_test
import (
"bytes"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestApplyToJSON(t *testing.T) {
instance1 := bytes.NewBufferString(`{"kind": "Foo"}`)
instance2 := bytes.NewBufferString(`{"kind": "Bar"}`)
err := filtersutil.ApplyToJSON(
kio.FilterFunc(func(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
for i := range nodes {
set := yaml.SetField(
"foo", yaml.NewScalarRNode("bar"))
node := nodes[i]
err := node.PipeE(set)
if !assert.NoError(t, err) {
t.FailNow()
}
}
return nodes, nil
}), buffer{Buffer: instance1}, buffer{Buffer: instance2},
)
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Equal(t,
strings.TrimSpace(`{"foo":"bar","kind":"Foo"}`),
strings.TrimSpace(instance1.String())) {
t.FailNow()
}
if !assert.Equal(t,
strings.TrimSpace(`{"foo":"bar","kind":"Bar"}`),
strings.TrimSpace(instance2.String())) {
t.FailNow()
}
}
type buffer struct {
*bytes.Buffer
}
func (buff buffer) UnmarshalJSON(b []byte) error {
buff.Reset()
buff.Write(b)
return nil
}
func (buff buffer) MarshalJSON() ([]byte, error) {
return buff.Bytes(), nil
}