// Copyright 2019 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 package kio_test import ( "fmt" "io/ioutil" "os" "path/filepath" "testing" "sigs.k8s.io/kustomize/kyaml/testutil" "github.com/stretchr/testify/assert" . "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" ) // TestLocalPackageWriter_Write tests: // - ReaderAnnotations are cleared when writing the Resources func TestLocalPackageWriter_Write(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) w := LocalPackageWriter{PackagePath: d} err := w.Write([]*yaml.RNode{node2, node1, node3}) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } b, err := ioutil.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml")) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } assert.Equal(t, `a: b #first --- c: d # second `, string(b)) b, err = ioutil.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml")) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } assert.Equal(t, `e: f g: h: - i # has a list - j `, string(b)) } // TestLocalPackageWriter_Write_keepReaderAnnotations tests: // - ReaderAnnotations are kept when writing the Resources func TestLocalPackageWriter_Write_keepReaderAnnotations(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) w := LocalPackageWriter{PackagePath: d, KeepReaderAnnotations: true} err := w.Write([]*yaml.RNode{node2, node1, node3}) if !assert.NoError(t, err) { return } b, err := ioutil.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml")) if !assert.NoError(t, err) { return } assert.Equal(t, `a: b #first metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/a_test.yaml" --- c: d # second metadata: annotations: config.kubernetes.io/index: 1 config.kubernetes.io/path: "a/b/a_test.yaml" `, string(b)) b, err = ioutil.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml")) if !assert.NoError(t, err) { return } assert.Equal(t, `e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/b_test.yaml" `, string(b)) } // TestLocalPackageWriter_Write_clearAnnotations tests: // - ClearAnnotations are removed from Resources func TestLocalPackageWriter_Write_clearAnnotations(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) w := LocalPackageWriter{PackagePath: d, ClearAnnotations: []string{"config.kubernetes.io/mode"}} err := w.Write([]*yaml.RNode{node2, node1, node3}) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } b, err := ioutil.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml")) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } assert.Equal(t, `a: b #first --- c: d # second `, string(b)) b, err = ioutil.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml")) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } assert.Equal(t, `e: f g: h: - i # has a list - j `, string(b)) } // TestLocalPackageWriter_Write_failRelativePath tests: // - If a relative path above the package is defined, write fails func TestLocalPackageWriter_Write_failRelativePath(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) node4, err := yaml.Parse(`e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/../../../b_test.yaml" `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } w := LocalPackageWriter{PackagePath: d} err = w.Write([]*yaml.RNode{node2, node1, node3, node4}) if assert.Error(t, err) { assert.Contains(t, err.Error(), "resource must be written under package") } } // TestLocalPackageWriter_Write_invalidIndex tests: // - If a non-int index is given, fail func TestLocalPackageWriter_Write_invalidIndex(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) node4, err := yaml.Parse(`e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/index: a config.kubernetes.io/path: "a/b/b_test.yaml" # use a different path, should still collide `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } w := LocalPackageWriter{PackagePath: d} err = w.Write([]*yaml.RNode{node2, node1, node3, node4}) if assert.Error(t, err) { assert.Contains(t, err.Error(), "unable to parse config.kubernetes.io/index") } } // TestLocalPackageWriter_Write_absPath tests: // - If config.kubernetes.io/path is absolute, fail func TestLocalPackageWriter_Write_absPath(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) d = filepath.ToSlash(d) n4 := fmt.Sprintf(`e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/index: a config.kubernetes.io/path: "%s/a/b/b_test.yaml" # use a different path, should still collide `, d) node4, err := yaml.Parse(n4) testutil.AssertNoError(t, err, n4) w := LocalPackageWriter{PackagePath: d} err = w.Write([]*yaml.RNode{node2, node1, node3, node4}) testutil.AssertErrorContains(t, err, "package paths may not be absolute paths") } // TestLocalPackageWriter_Write_missingPath tests: // - If config.kubernetes.io/path or index are missing, then default them func TestLocalPackageWriter_Write_missingAnnotations(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) node4String := `e: f g: h: - i # has a list - j kind: Foo metadata: name: bar ` node4, err := yaml.Parse(node4String) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } w := LocalPackageWriter{PackagePath: d} err = w.Write([]*yaml.RNode{node2, node1, node3, node4}) if !assert.NoError(t, err) { t.FailNow() } b, err := ioutil.ReadFile(filepath.Join(d, "foo_bar.yaml")) if !assert.NoError(t, err) { t.FailNow() } if !assert.Equal(t, node4String, string(b)) { t.FailNow() } } // TestLocalPackageWriter_Write_pathIsDir tests: // - If config.kubernetes.io/path is a directory, fail func TestLocalPackageWriter_Write_pathIsDir(t *testing.T) { d, node1, node2, node3 := getWriterInputs(t) defer os.RemoveAll(d) node4, err := yaml.Parse(`e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/path: a/ config.kubernetes.io/index: 0 `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } w := LocalPackageWriter{PackagePath: d} err = w.Write([]*yaml.RNode{node2, node1, node3, node4}) if assert.Error(t, err) { assert.Contains(t, err.Error(), "config.kubernetes.io/path cannot be a directory") } } func getWriterInputs(t *testing.T) (string, *yaml.RNode, *yaml.RNode, *yaml.RNode) { node1, err := yaml.Parse(`a: b #first metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/a_test.yaml" `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } node2, err := yaml.Parse(`c: d # second metadata: annotations: config.kubernetes.io/index: 1 config.kubernetes.io/path: "a/b/a_test.yaml" `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } node3, err := yaml.Parse(`e: f g: h: - i # has a list - j metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/b_test.yaml" `) if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } d, err := ioutil.TempDir("", "kyaml-test") if !assert.NoError(t, err) { assert.FailNow(t, err.Error()) } if !assert.NoError(t, os.MkdirAll(filepath.Join(d, "a"), 0700)) { assert.FailNow(t, "") } return d, node1, node2, node3 }