mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-07-17 17:52:12 +00:00
kyaml: initial support for yaml and resource manipulation
This commit is contained in:
128
kyaml/copyutil/copyutil.go
Normal file
128
kyaml/copyutil/copyutil.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// The copyutil package contains libraries for copying directories of configuration.
|
||||
package copyutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
)
|
||||
|
||||
// CopyDir copies a src directory to a dst directory. CopyDir skips copying the .git directory from the src.
|
||||
func CopyDir(src string, dst string) error {
|
||||
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// don't copy the .git dir
|
||||
if path != src {
|
||||
rel := strings.TrimPrefix(path, src)
|
||||
if strings.HasPrefix(rel, string(filepath.Separator)+".git") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// path is an absolute path, rather than a path relative to src.
|
||||
// e.g. if src is /path/to/package, then path might be /path/to/package/and/sub/dir
|
||||
// we need the path relative to src `and/sub/dir` when we are copying the files to dest.
|
||||
copyTo := strings.TrimPrefix(path, src)
|
||||
|
||||
// make directories that don't exist
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(filepath.Join(dst, copyTo), info.Mode())
|
||||
}
|
||||
|
||||
// copy file by reading and writing it
|
||||
b, err := ioutil.ReadFile(filepath.Join(src, copyTo))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(dst, copyTo), b, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Diff returns a list of files that differ between the source and destination.
|
||||
//
|
||||
// Diff is guaranteed to return a non-empty set if any files differ, but
|
||||
// this set is not guaranteed to contain all differing files.
|
||||
func Diff(sourceDir, destDir string) (sets.String, error) {
|
||||
// get set of filenames in the package source
|
||||
upstreamFiles := sets.String{}
|
||||
err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// skip git repo if it exists
|
||||
if strings.Contains(path, ".git") {
|
||||
return nil
|
||||
}
|
||||
|
||||
upstreamFiles.Insert(strings.TrimPrefix(strings.TrimPrefix(path, sourceDir), string(filepath.Separator)))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return sets.String{}, err
|
||||
}
|
||||
|
||||
// get set of filenames in the cloned package
|
||||
localFiles := sets.String{}
|
||||
err = filepath.Walk(destDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// skip git repo if it exists
|
||||
if strings.Contains(path, ".git") {
|
||||
return nil
|
||||
}
|
||||
|
||||
localFiles.Insert(strings.TrimPrefix(strings.TrimPrefix(path, destDir), string(filepath.Separator)))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return sets.String{}, err
|
||||
}
|
||||
|
||||
// verify the source and cloned packages have the same set of filenames
|
||||
diff := upstreamFiles.SymmetricDifference(localFiles)
|
||||
|
||||
// verify file contents match
|
||||
for _, f := range upstreamFiles.Intersection(localFiles).List() {
|
||||
fi, err := os.Stat(filepath.Join(destDir, f))
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
if fi.Mode().IsDir() {
|
||||
// already checked that this directory exists in the local files
|
||||
continue
|
||||
}
|
||||
|
||||
// compare upstreamFiles
|
||||
b1, err := ioutil.ReadFile(filepath.Join(destDir, f))
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
b2, err := ioutil.ReadFile(filepath.Join(sourceDir, f))
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
if !bytes.Equal(b1, b2) {
|
||||
diff.Insert(f)
|
||||
}
|
||||
}
|
||||
|
||||
// return the differing files
|
||||
return diff, nil
|
||||
}
|
||||
199
kyaml/copyutil/copyutil_test.go
Normal file
199
kyaml/copyutil/copyutil_test.go
Normal file
@@ -0,0 +1,199 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package copyutil_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
. "sigs.k8s.io/kustomize/kyaml/copyutil"
|
||||
)
|
||||
|
||||
// TestDiff_identical verifies identical directories return an empty set
|
||||
func TestDiff_identical(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, diff.List())
|
||||
}
|
||||
|
||||
// TestDiff_additionalSourceFiles verifies if there are additional files
|
||||
// in the source, the diff will contain them
|
||||
func TestDiff_additionalSourceFiles(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a2"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, diff.List(), []string{"a2"})
|
||||
}
|
||||
|
||||
// TestDiff_additionalDestFiles verifies if there are additional files
|
||||
// in the dest, the diff will contain them
|
||||
func TestDiff_additionalDestFiles(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a2"), 0700)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, diff.List(), []string{"a2"})
|
||||
|
||||
}
|
||||
|
||||
// TestDiff_srcDestContentsDiffer verifies if the file contents
|
||||
// differ between the source and destination, the diff
|
||||
// contains the differing files
|
||||
func TestDiff_srcDestContentsDiffer(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, "a1", "f.yaml"), []byte(`b`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, diff.List(), []string{"a1/f.yaml"})
|
||||
}
|
||||
|
||||
// TestDiff_srcDestContentsDifferInDirs verifies if identical files
|
||||
// exist in different directories, they are included in the diff
|
||||
func TestDiff_srcDestContentsDifferInDirs(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "b1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, "b1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, diff.List(), []string{
|
||||
"a1", "a1/f.yaml", "b1/f.yaml", "b1"})
|
||||
}
|
||||
|
||||
// TestDiff_skipGitSrc verifies that .git directories in the source
|
||||
// are not looked at
|
||||
func TestDiff_skipGitSrc(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// git should be ignored
|
||||
err = os.Mkdir(filepath.Join(s, ".git"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, ".git", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, diff.List())
|
||||
}
|
||||
|
||||
// TestDiff_skipGitDest verifies that .git directories in the destination
|
||||
// are not looked at
|
||||
func TestDiff_skipGitDest(t *testing.T) {
|
||||
s, err := ioutil.TempDir("", "copyutilsrc")
|
||||
assert.NoError(t, err)
|
||||
d, err := ioutil.TempDir("", "copyutildest")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(s, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(s, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.Mkdir(filepath.Join(d, "a1"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, "a1", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// git should be ignored
|
||||
err = os.Mkdir(filepath.Join(d, ".git"), 0700)
|
||||
assert.NoError(t, err)
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join(d, ".git", "f.yaml"), []byte(`a`), 0600)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff, err := Diff(s, d)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, diff.List())
|
||||
}
|
||||
Reference in New Issue
Block a user