diff --git a/api/filters/filtersutil/filtersutil.go b/api/filters/filtersutil/filtersutil.go new file mode 100644 index 000000000..e238f7bc0 --- /dev/null +++ b/api/filters/filtersutil/filtersutil.go @@ -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) +} diff --git a/api/filters/filtersutil/filtersutil_test.go b/api/filters/filtersutil/filtersutil_test.go new file mode 100644 index 000000000..97471e25e --- /dev/null +++ b/api/filters/filtersutil/filtersutil_test.go @@ -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 +}