Sink: Force JSON encoding for .json files

This commit is contained in:
Mattias Öhrn
2021-05-31 08:00:26 +02:00
parent d9435bd1b1
commit fa3e829eb6
2 changed files with 55 additions and 10 deletions

View File

@@ -6,7 +6,7 @@ package kio
import (
"encoding/json"
"io"
"path/filepath"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -56,8 +56,23 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error {
}
encoder := yaml.NewEncoder(w.Writer)
// keep
hasJSONPathExt := make([]bool, len(nodes))
defer encoder.Close()
for i := range nodes {
// Check if the output file is a JSON file so we can force JSON encoding in that case.
// YAML flow style encoding may not be compatible because of newlines introduced by the
// YAML marshaller in long double quoted string values. These newlines are insignificant
// when interpreted as YAML but invalid when interpreted as JSON.
if path, _, _ := kioutil.GetFileAnnotations(nodes[i]); path != "" {
filename := filepath.Base(path)
for _, glob := range JSONMatch {
if match, _ := filepath.Match(glob, filename); match {
hasJSONPathExt[i] = true
break
}
}
}
// clean resources by removing annotations set by the Reader
if !w.KeepReaderAnnotations {
_, err := nodes[i].Pipe(yaml.ClearAnnotation(kioutil.IndexAnnotation))
@@ -84,7 +99,7 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error {
// don't wrap the elements
if w.WrappingKind == "" {
for i := range nodes {
if err := w.encode(encoder, nodes[i].Document()); err != nil {
if err := w.encode(encoder, hasJSONPathExt[i], nodes[i].Document()); err != nil {
return err
}
}
@@ -118,20 +133,24 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error {
for i := range nodes {
items.Content = append(items.Content, nodes[i].YNode())
}
err := w.encode(encoder, doc)
err := w.encode(encoder, false, doc)
yaml.UndoSerializationHacksOnNodes(nodes)
return err
}
// encode encodes the input document node to appropriate node format
func (w ByteWriter) encode(encoder *yaml.Encoder, doc *yaml.Node) error {
func (w ByteWriter) encode(encoder *yaml.Encoder, forceJSON bool, doc *yaml.Node) error {
rNode := &yaml.RNode{}
rNode.SetYNode(doc)
str, err := rNode.String()
if err != nil {
return errors.Wrap(err)
useJSONEncoder := forceJSON
if !forceJSON {
str, err := rNode.String()
if err != nil {
return errors.Wrap(err)
}
useJSONEncoder = json.Valid([]byte(str))
}
if json.Valid([]byte(str)) {
if useJSONEncoder {
je := json.NewEncoder(w.Writer)
je.SetIndent("", " ")
return errors.Wrap(je.Encode(rNode))

View File

@@ -26,7 +26,7 @@ func TestByteWriter(t *testing.T) {
testCases := []testCase{
//
//
// Test Case
//
{
name: "wrap_resource_list",
@@ -60,7 +60,7 @@ functionConfig:
},
//
//
// Test Case
//
{
name: "multiple_items",
@@ -189,6 +189,32 @@ metadata:
config.kubernetes.io/path: "a/b/a_test.yaml"
`,
},
//
// Test Case
//
{
name: "encode_valid_json",
items: []string{
`{
"a": "a long string that would certainly see a newline introduced by the YAML marshaller abcd123",
"metadata": {
"annotations": {
"config.kubernetes.io/path": "test.json"
}
}
}`,
},
expectedOutput: `{
"a": "a long string that would certainly see a newline introduced by the YAML marshaller abcd123",
"metadata": {
"annotations": {
"config.kubernetes.io/path": "test.json"
}
}
}`,
},
}
for i := range testCases {