diff --git a/cmd/config/internal/commands/e2e/e2e_test.go b/cmd/config/internal/commands/e2e/e2e_test.go index f62ea336c..962134c99 100644 --- a/cmd/config/internal/commands/e2e/e2e_test.go +++ b/cmd/config/internal/commands/e2e/e2e_test.go @@ -30,6 +30,7 @@ func TestRunE2e(t *testing.T) { expectedErr string skipIfFalseEnv string }{ + { name: "exec_function_no_args", args: func(d string) []string { @@ -63,6 +64,36 @@ metadata: }, }, + { + name: "exec_function_no_args_json", + args: func(d string) []string { + return []string{ + "--enable-exec", "--exec-path", filepath.Join(d, "e2econtainerconfig"), + } + }, + files: func(d string) map[string]string { + return map[string]string{ + "deployment.json": ` +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "foo" + } +} +`, + } + }, + expectedFiles: func(d string) map[string]string { + return map[string]string{ + "deployment.json": ` +{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "foo", annotations: { + a-string-value: '', a-int-value: '0', a-bool-value: 'false'}}} +`, + } + }, + }, + { name: "exec_function_args", args: func(d string) []string { @@ -468,7 +499,6 @@ def run(r, fc): resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"] resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"] resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"] - run(ctx.resource_list["items"], ctx.resource_list["functionConfig"]) `, "config.yaml": ` @@ -545,7 +575,6 @@ def run(r, fc): resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"] resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"] resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"] - run(ctx.resource_list["items"], ctx.resource_list["functionConfig"]) `, "deployment.yaml": ` diff --git a/cmd/config/internal/commands/sink_test.go b/cmd/config/internal/commands/sink_test.go index 9fc4d869c..67d364d62 100644 --- a/cmd/config/internal/commands/sink_test.go +++ b/cmd/config/internal/commands/sink_test.go @@ -136,6 +136,51 @@ spec: } } +func TestSinkCommandJSON(t *testing.T) { + d, err := ioutil.TempDir("", "kustomize-source-test") + if !assert.NoError(t, err) { + t.FailNow() + } + defer os.RemoveAll(d) + + r := commands.GetSinkRunner("") + r.Command.SetIn(bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", + "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', + config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}} +`)) + r.Command.SetArgs([]string{d}) + if !assert.NoError(t, r.Command.Execute()) { + t.FailNow() + } + + actual, err := ioutil.ReadFile(filepath.Join(d, "f1.json")) + if !assert.NoError(t, err) { + t.FailNow() + } + expected := `{ + "kind": "Deployment", + "metadata": { + "annotations": { + "app": "nginx2" + }, + "labels": { + "app": "nginx2" + }, + "name": "foo" + }, + "spec": { + "replicas": 1 + } +} +` + if !assert.Equal(t, expected, string(actual)) { + t.FailNow() + } +} + func TestSinkCommand_Stdout(t *testing.T) { d, err := ioutil.TempDir("", "kustomize-source-test") if !assert.NoError(t, err) { @@ -249,3 +294,49 @@ spec: t.FailNow() } } + +func TestSinkCommandJSON_Stdout(t *testing.T) { + d, err := ioutil.TempDir("", "kustomize-source-test") + if !assert.NoError(t, err) { + t.FailNow() + } + defer os.RemoveAll(d) + + // fmt the files + out := &bytes.Buffer{} + r := commands.GetSinkRunner("") + r.Command.SetIn(bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", + "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', + config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}} +`)) + + r.Command.SetOut(out) + r.Command.SetArgs([]string{}) + if !assert.NoError(t, r.Command.Execute()) { + t.FailNow() + } + + expected := `{ + "kind": "Deployment", + "metadata": { + "annotations": { + "app": "nginx2" + }, + "labels": { + "app": "nginx2" + }, + "name": "foo" + }, + "spec": { + "replicas": 1 + } +} +` + if !assert.Equal(t, expected, out.String()) { + println(out.String()) + t.FailNow() + } +} diff --git a/cmd/config/internal/commands/source.go b/cmd/config/internal/commands/source.go index 27382bb2f..7873956ce 100644 --- a/cmd/config/internal/commands/source.go +++ b/cmd/config/internal/commands/source.go @@ -71,7 +71,7 @@ func (r *SourceRunner) runE(c *cobra.Command, args []string) error { var inputs []kio.Reader for _, a := range args { - inputs = append(inputs, kio.LocalPackageReader{PackagePath: a}) + inputs = append(inputs, kio.LocalPackageReader{PackagePath: a, MatchFilesGlob: kio.MatchAll}) } if len(inputs) == 0 { inputs = []kio.Reader{&kio.ByteReader{Reader: c.InOrStdin()}} diff --git a/cmd/config/internal/commands/source_test.go b/cmd/config/internal/commands/source_test.go index 141541143..717b22c4a 100644 --- a/cmd/config/internal/commands/source_test.go +++ b/cmd/config/internal/commands/source_test.go @@ -135,6 +135,77 @@ items: } } +func TestSourceCommandJSON(t *testing.T) { + d, err := ioutil.TempDir("", "kustomize-source-test") + if !assert.NoError(t, err) { + return + } + defer os.RemoveAll(d) + + err = ioutil.WriteFile(filepath.Join(d, "f1.json"), []byte(` +{ + "kind": "Deployment", + "metadata": { + "labels": { + "app": "nginx2" + }, + "name": "foo", + "annotations": { + "app": "nginx2" + } + }, + "spec": { + "replicas": 1 + } +} +`), 0600) + if !assert.NoError(t, err) { + return + } + err = ioutil.WriteFile(filepath.Join(d, "f2.json"), []byte(` +{ + "apiVersion": "v1", + "kind": "Abstraction", + "metadata": { + "name": "foo", + "annotations": { + "config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n", + "config.kubernetes.io/local-config": "true" + } + }, + "spec": { + "replicas": 3 + } +} +`), 0600) + if !assert.NoError(t, err) { + return + } + + // fmt the files + b := &bytes.Buffer{} + r := commands.GetSourceRunner("") + r.Command.SetArgs([]string{d}) + r.Command.SetOut(b) + if !assert.NoError(t, r.Command.Execute()) { + return + } + + if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", + "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json'}}, + "spec": {"replicas": 1}} +- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": { + "config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n", + "config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0', + config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}} +`, b.String()) { + return + } +} + func TestSourceCommand_Stdin(t *testing.T) { d, err := ioutil.TempDir("", "kustomize-source-test") if !assert.NoError(t, err) { @@ -198,3 +269,48 @@ items: return } } + +func TestSourceCommandJSON_Stdin(t *testing.T) { + d, err := ioutil.TempDir("", "kustomize-source-test") + if !assert.NoError(t, err) { + return + } + defer os.RemoveAll(d) + + in := bytes.NewBufferString(` +{ + "kind": "Deployment", + "metadata": { + "labels": { + "app": "nginx2" + }, + "name": "foo", + "annotations": { + "app": "nginx2" + } + }, + "spec": { + "replicas": 1 + } +} +`) + + out := &bytes.Buffer{} + r := commands.GetSourceRunner("") + r.Command.SetArgs([]string{}) + r.Command.SetIn(in) + r.Command.SetOut(out) + if !assert.NoError(t, r.Command.Execute()) { + return + } + + if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", + "annotations": {"app": "nginx2", config.kubernetes.io/index: '0'}}, "spec": { + "replicas": 1}} +`, out.String()) { + return + } +} diff --git a/kyaml/kio/byteio_writer.go b/kyaml/kio/byteio_writer.go index 1d03cfb1d..c6fe96db4 100644 --- a/kyaml/kio/byteio_writer.go +++ b/kyaml/kio/byteio_writer.go @@ -4,6 +4,7 @@ package kio import ( + "encoding/json" "io" "sigs.k8s.io/kustomize/kyaml/errors" @@ -90,9 +91,8 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error { // don't wrap the elements if w.WrappingKind == "" { for i := range nodes { - err := encoder.Encode(nodes[i].Document()) - if err != nil { - return errors.Wrap(err) + if err := w.encode(encoder, nodes[i].Document()); err != nil { + return err } } return nil @@ -125,7 +125,23 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error { for i := range nodes { items.Content = append(items.Content, nodes[i].YNode()) } - err := errors.Wrap(encoder.Encode(doc)) + err := w.encode(encoder, 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 { + rNode := &yaml.RNode{} + rNode.SetYNode(doc) + str, err := rNode.String() + if err != nil { + return errors.Wrap(err) + } + if json.Valid([]byte(str)) { + je := json.NewEncoder(w.Writer) + je.SetIndent("", " ") + return errors.Wrap(je.Encode(rNode)) + } + return encoder.Encode(doc) +} diff --git a/kyaml/kio/filters/testyaml/testyaml.go b/kyaml/kio/filters/testyaml/testyaml.go index 555d95da0..4052e5ffb 100644 --- a/kyaml/kio/filters/testyaml/testyaml.go +++ b/kyaml/kio/filters/testyaml/testyaml.go @@ -56,6 +56,16 @@ status2: - 2 `) -var FormattedJSON1 = []byte(`{"apiVersion": "example.com/v1beta1", "kind": "MyType", "spec": "a", "status": {"conditions": [ - 3, 1, 2]}} +var FormattedJSON1 = []byte(`{ + "apiVersion": "example.com/v1beta1", + "kind": "MyType", + "spec": "a", + "status": { + "conditions": [ + 3, + 1, + 2 + ] + } +} `) diff --git a/kyaml/kio/pkgio_reader.go b/kyaml/kio/pkgio_reader.go index 854c8d392..d0f4c0ee6 100644 --- a/kyaml/kio/pkgio_reader.go +++ b/kyaml/kio/pkgio_reader.go @@ -167,6 +167,8 @@ type LocalPackageReader struct { var _ Reader = LocalPackageReader{} var DefaultMatch = []string{"*.yaml", "*.yml"} +var JSONMatch = []string{"*.json"} +var MatchAll = append(DefaultMatch, JSONMatch...) // Read reads the Resources. func (r LocalPackageReader) Read() ([]*yaml.RNode, error) { @@ -238,6 +240,7 @@ func (r *LocalPackageReader) readFile(path string, _ os.FileInfo) ([]*yaml.RNode return nil, err } defer f.Close() + rr := &ByteReader{ DisableUnwrapping: true, Reader: f, diff --git a/kyaml/runfn/runfn.go b/kyaml/runfn/runfn.go index 8564f343d..b6a5ce166 100644 --- a/kyaml/runfn/runfn.go +++ b/kyaml/runfn/runfn.go @@ -110,7 +110,7 @@ func (r RunFns) getNodesAndFilters() ( // the same one for reading must be used for writing if deleting Resources var outputPkg *kio.LocalPackageReadWriter if r.Path != "" { - outputPkg = &kio.LocalPackageReadWriter{PackagePath: r.Path} + outputPkg = &kio.LocalPackageReadWriter{PackagePath: r.Path, MatchFilesGlob: kio.MatchAll} } if r.Input == nil { diff --git a/kyaml/yaml/types.go b/kyaml/yaml/types.go index d74cb8471..862a0ecc8 100644 --- a/kyaml/yaml/types.go +++ b/kyaml/yaml/types.go @@ -497,7 +497,6 @@ func String(node *yaml.Node, opts ...string) (string, error) { if node == nil { return "", nil } - DoSerializationHacks(node) optsSet := sets.String{} optsSet.Insert(opts...) if optsSet.Has(Flow) { @@ -516,7 +515,6 @@ func String(node *yaml.Node, opts ...string) (string, error) { if optsSet.Has(Trim) { val = strings.TrimSpace(val) } - UndoSerializationHacks(node) return val, errors.Wrap(err) }