From 1b7171ac9e3f2b09ed8e1718a8e1610918105d8b Mon Sep 17 00:00:00 2001 From: Jingfang Liu Date: Tue, 31 Jul 2018 10:58:14 -0700 Subject: [PATCH] Add glob support in edit add resource --- pkg/commands/addresource.go | 37 +++++++++++++++++++-------- pkg/commands/addresource_test.go | 18 ++++++------- pkg/fs/fakefs.go | 32 +++++++++++------------ pkg/fs/fakefs_test.go | 18 +++++++++++++ pkg/fs/fs.go | 2 +- pkg/fs/realfs.go | 25 ++++-------------- pkg/fs/realfs_test.go | 18 ++++++------- pkg/internal/loadertest/fakeloader.go | 5 ---- pkg/loader/fileloader.go | 10 -------- pkg/loader/loader.go | 2 -- 10 files changed, 84 insertions(+), 83 deletions(-) diff --git a/pkg/commands/addresource.go b/pkg/commands/addresource.go index 638ee8ca1..ae6e99c5c 100644 --- a/pkg/commands/addresource.go +++ b/pkg/commands/addresource.go @@ -18,7 +18,7 @@ package commands import ( "errors" - "fmt" + "log" "github.com/spf13/cobra" @@ -27,7 +27,7 @@ import ( ) type addResourceOptions struct { - resourceFilePath string + resourceFilePaths []string } // newCmdAddResource adds the name of a file containing a resource to the kustomization file. @@ -56,10 +56,10 @@ func newCmdAddResource(fsys fs.FileSystem) *cobra.Command { // Validate validates addResource command. func (o *addResourceOptions) Validate(args []string) error { - if len(args) != 1 { + if len(args) == 0 { return errors.New("must specify a resource file") } - o.resourceFilePath = args[0] + o.resourceFilePaths = args return nil } @@ -70,9 +70,24 @@ func (o *addResourceOptions) Complete(cmd *cobra.Command, args []string) error { // RunAddResource runs addResource command (do real work). func (o *addResourceOptions) RunAddResource(fsys fs.FileSystem) error { - if !fsys.Exists(o.resourceFilePath) { - return errors.New(o.resourceFilePath + " does not exist") + var resources []string + + for _, pattern := range o.resourceFilePaths { + files, err := fsys.Glob(pattern) + if err != nil { + return err + } + if len(files) == 0 { + log.Printf("%s has no match", pattern) + continue + } + resources = append(resources, files...) } + + if len(resources) == 0 { + return nil + } + mf, err := newKustomizationFile(constants.KustomizationFileName, fsys) if err != nil { return err @@ -83,11 +98,13 @@ func (o *addResourceOptions) RunAddResource(fsys fs.FileSystem) error { return err } - if stringInSlice(o.resourceFilePath, m.Resources) { - return fmt.Errorf("resource %s already in kustomization file", o.resourceFilePath) + for _, resource := range resources { + if stringInSlice(resource, m.Resources) { + log.Printf("resource %s already in kustomization file", resource) + continue + } + m.Resources = append(m.Resources, resource) } - m.Resources = append(m.Resources, o.resourceFilePath) - return mf.write(m) } diff --git a/pkg/commands/addresource_test.go b/pkg/commands/addresource_test.go index 6b8890d5d..91d503a39 100644 --- a/pkg/commands/addresource_test.go +++ b/pkg/commands/addresource_test.go @@ -17,9 +17,8 @@ limitations under the License. package commands import ( - "testing" - "strings" + "testing" "github.com/kubernetes-sigs/kustomize/pkg/constants" "github.com/kubernetes-sigs/kustomize/pkg/fs" @@ -52,10 +51,11 @@ secretGenerator: [] func TestAddResourceHappyPath(t *testing.T) { fakeFS := fs.MakeFakeFS() fakeFS.WriteFile(resourceFileName, []byte(resourceFileContent)) + fakeFS.WriteFile(resourceFileName+"another", []byte(resourceFileContent)) fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent)) cmd := newCmdAddResource(fakeFS) - args := []string{resourceFileName} + args := []string{resourceFileName + "*"} err := cmd.RunE(cmd, args) if err != nil { t.Errorf("unexpected cmd error: %v", err) @@ -67,6 +67,9 @@ func TestAddResourceHappyPath(t *testing.T) { if !strings.Contains(string(content), resourceFileName) { t.Errorf("expected resource name in kustomization") } + if !strings.Contains(string(content), resourceFileName+"another") { + t.Errorf("expected resource name in kustomization") + } } func TestAddResourceAlreadyThere(t *testing.T) { @@ -81,13 +84,10 @@ func TestAddResourceAlreadyThere(t *testing.T) { t.Fatalf("unexpected cmd error: %v", err) } - // adding an existing resource should return an error + // adding an existing resource doesn't return an error err = cmd.RunE(cmd, args) - if err == nil { - t.Errorf("expected already there problem") - } - if err.Error() != "resource "+resourceFileName+" already in kustomization file" { - t.Errorf("unexpected error %v", err) + if err != nil { + t.Errorf("unexpected cmd error :%v", err) } } diff --git a/pkg/fs/fakefs.go b/pkg/fs/fakefs.go index cea0decf4..045d94c17 100644 --- a/pkg/fs/fakefs.go +++ b/pkg/fs/fakefs.go @@ -18,6 +18,8 @@ package fs import ( "fmt" + "path/filepath" + "sort" ) var _ FileSystem = &FakeFS{} @@ -60,6 +62,18 @@ func (fs *FakeFS) Exists(name string) bool { return found } +// Glob returns the list of matching files +func (fs *FakeFS) Glob(pattern string) ([]string, error) { + var result []string + for p := range fs.m { + if fs.pathMatch(p, pattern) { + result = append(result, p) + } + } + sort.Strings(result) + return result, nil +} + // IsDir returns true if the file exists and is a directory. func (fs *FakeFS) IsDir(name string) bool { f, found := fs.m[name] @@ -77,18 +91,6 @@ func (fs *FakeFS) ReadFile(name string) ([]byte, error) { return nil, fmt.Errorf("cannot read file %q", name) } -// ReadFiles looks through all files in the fake filesystem -// and find the matching files and then read content from all of them -func (fs *FakeFS) ReadFiles(name string) (map[string][]byte, error) { - result := map[string][]byte{} - for p, f := range fs.m { - if fs.pathMatch(p, name) { - result[p] = f.content - } - } - return result, nil -} - // WriteFile always succeeds and does nothing. func (fs *FakeFS) WriteFile(name string, c []byte) error { ff := &FakeFile{} @@ -98,8 +100,6 @@ func (fs *FakeFS) WriteFile(name string, c []byte) error { } func (fs *FakeFS) pathMatch(path, pattern string) bool { - if path == pattern { - return true - } - return false + match, _ := filepath.Match(pattern, path) + return match } diff --git a/pkg/fs/fakefs_test.go b/pkg/fs/fakefs_test.go index 7477e5cd3..709d9df06 100644 --- a/pkg/fs/fakefs_test.go +++ b/pkg/fs/fakefs_test.go @@ -18,6 +18,7 @@ package fs import ( "bytes" + "reflect" "testing" ) @@ -90,3 +91,20 @@ func TestWriteFile(t *testing.T) { t.Fatalf("incorrect content: %v", content) } } + +func TestGlob(t *testing.T) { + x := MakeFakeFS() + x.Create("dir/foo") + x.Create("dir/bar") + files, err := x.Glob("dir/*") + if err != nil { + t.Fatalf("expected no error") + } + expected := []string{ + "dir/bar", + "dir/foo", + } + if !reflect.DeepEqual(files, expected) { + t.Fatalf("incorrect files found by glob: %v", files) + } +} diff --git a/pkg/fs/fs.go b/pkg/fs/fs.go index 42e2e6fdc..ecb064834 100644 --- a/pkg/fs/fs.go +++ b/pkg/fs/fs.go @@ -29,8 +29,8 @@ type FileSystem interface { Open(name string) (File, error) IsDir(name string) bool Exists(name string) bool + Glob(pattern string) ([]string, error) ReadFile(name string) ([]byte, error) - ReadFiles(name string) (map[string][]byte, error) WriteFile(name string, data []byte) error } diff --git a/pkg/fs/realfs.go b/pkg/fs/realfs.go index fa3409b84..42b72b676 100644 --- a/pkg/fs/realfs.go +++ b/pkg/fs/realfs.go @@ -49,6 +49,11 @@ func (realFS) Exists(name string) bool { return err == nil } +// Glob returns the list of matching files +func (realFS) Glob(pattern string) ([]string, error) { + return filepath.Glob(pattern) +} + // IsDir delegates to os.Stat and FileInfo.IsDir func (realFS) IsDir(name string) bool { info, err := os.Stat(name) @@ -61,26 +66,6 @@ func (realFS) IsDir(name string) bool { // ReadFile delegates to ioutil.ReadFile. func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } -// ReadFiles use glob to find the matching files and then read content from all of them -func (realFS) ReadFiles(name string) (map[string][]byte, error) { - files, err := filepath.Glob(name) - if err != nil || len(files) == 0 { - return nil, err - } - - output := map[string][]byte{} - for _, file := range files { - bytes, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - if bytes != nil { - output[file] = bytes - } - } - return output, nil -} - // WriteFile delegates to ioutil.WriteFile with read/write permissions. func (realFS) WriteFile(name string, c []byte) error { return ioutil.WriteFile(name, c, 0666) diff --git a/pkg/fs/realfs_test.go b/pkg/fs/realfs_test.go index afe64c8c9..c1bf8a734 100644 --- a/pkg/fs/realfs_test.go +++ b/pkg/fs/realfs_test.go @@ -55,17 +55,15 @@ func TestReadFilesRealFS(t *testing.T) { t.Fatalf("unexpected error %s", err) } - expected := map[string][]byte{ - path.Join(testDir, "foo"): []byte(`foo`), - path.Join(testDir, "bar"): []byte(`bar`), - } - - content, err := x.ReadFiles("kustomize_testing_dir/*") - if !reflect.DeepEqual(content, expected) { - t.Fatalf("actual: %+v doesn't match expected: %+v", content, expected) - + files, err := x.Glob(path.Join("testDir", "*")) + expected := []string{ + path.Join(testDir, "bar"), + path.Join(testDir, "foo"), } if err != nil { - t.Fatalf("unexpected error %s", err) + t.Fatalf("expected no error") + } + if reflect.DeepEqual(files, expected) { + t.Fatalf("incorrect files found by glob: %v", files) } } diff --git a/pkg/internal/loadertest/fakeloader.go b/pkg/internal/loadertest/fakeloader.go index 4cdce780a..793c3e2e3 100644 --- a/pkg/internal/loadertest/fakeloader.go +++ b/pkg/internal/loadertest/fakeloader.go @@ -63,8 +63,3 @@ func (f FakeLoader) New(newRoot string) (loader.Loader, error) { func (f FakeLoader) Load(location string) ([]byte, error) { return f.delegate.Load(location) } - -// GlobLoad performs load from a given location. -func (f FakeLoader) GlobLoad(location string) (map[string][]byte, error) { - return f.delegate.GlobLoad(location) -} diff --git a/pkg/loader/fileloader.go b/pkg/loader/fileloader.go index 6b047dadd..2d614305e 100644 --- a/pkg/loader/fileloader.go +++ b/pkg/loader/fileloader.go @@ -109,13 +109,3 @@ func (l *fileLoader) Load(location string) ([]byte, error) { } return l.fSys.ReadFile(fullLocation) } - -// GlobLoad returns the map from path to bytes from reading a glob path. -// Implements the Loader interface. -func (l *fileLoader) GlobLoad(location string) (map[string][]byte, error) { - fullLocation, err := l.fullLocation(l.root, location) - if err != nil { - return nil, err - } - return l.fSys.ReadFiles(fullLocation) -} diff --git a/pkg/loader/loader.go b/pkg/loader/loader.go index 545f6988b..2db035089 100644 --- a/pkg/loader/loader.go +++ b/pkg/loader/loader.go @@ -25,6 +25,4 @@ type Loader interface { New(newRoot string) (Loader, error) // Load returns the bytes read from the location or an error. Load(location string) ([]byte, error) - // GlobLoad returns the bytes read from a glob path or an error. - GlobLoad(location string) (map[string][]byte, error) }