From 9a94bcb85441f3dc3b2538a26459a4c98e0c35cb Mon Sep 17 00:00:00 2001 From: Jeffrey Regan Date: Tue, 1 Oct 2019 10:38:00 -0700 Subject: [PATCH] Improve fs package and doc in prep to officially go public --- internal/loadertest/fakeloader.go | 2 +- .../configmapfactory_test.go | 8 +- .../configmapandsecret/secretfactory_test.go | 2 +- pkg/fs/confirmeddir.go | 24 ++---- pkg/fs/confirmeddir_test.go | 25 ++---- pkg/fs/fakefile.go | 69 --------------- pkg/fs/fakefileinfo.go | 47 ----------- pkg/fs/fileinfo.go | 34 ++++++++ pkg/fs/fileinmemory.go | 56 +++++++++++++ pkg/fs/fileondisk.go | 27 ++++++ pkg/fs/fs.go | 49 ++++++----- pkg/fs/{fakefs.go => fsinmemory.go} | 83 ++++++++----------- pkg/fs/{fakefs_test.go => fsinmemory_test.go} | 33 +++----- pkg/fs/{realfs.go => fsondisk.go} | 63 ++++++-------- pkg/fs/{realfs_test.go => fsondisk_test.go} | 20 +---- pkg/fs/realfile.go | 40 --------- pkg/fs/rpath.go | 12 +++ pkg/loader/fileloader_test.go | 14 ++-- pkg/loader/kv_test.go | 4 +- pkg/loader/loadrestrictions_test.go | 4 +- pkg/resmap/factory_test.go | 2 +- pkg/target/plugindir_test.go | 2 +- 22 files changed, 256 insertions(+), 364 deletions(-) delete mode 100644 pkg/fs/fakefile.go delete mode 100644 pkg/fs/fakefileinfo.go create mode 100644 pkg/fs/fileinfo.go create mode 100644 pkg/fs/fileinmemory.go create mode 100644 pkg/fs/fileondisk.go rename pkg/fs/{fakefs.go => fsinmemory.go} (67%) rename pkg/fs/{fakefs_test.go => fsinmemory_test.go} (80%) rename pkg/fs/{realfs.go => fsondisk.go} (52%) rename pkg/fs/{realfs_test.go => fsondisk_test.go} (84%) delete mode 100644 pkg/fs/realfile.go create mode 100644 pkg/fs/rpath.go diff --git a/internal/loadertest/fakeloader.go b/internal/loadertest/fakeloader.go index 317ff7e3b..75516ba36 100644 --- a/internal/loadertest/fakeloader.go +++ b/internal/loadertest/fakeloader.go @@ -33,7 +33,7 @@ func NewFakeLoader(initialDir string) FakeLoader { func NewFakeLoaderWithRestrictor( lr loader.LoadRestrictorFunc, initialDir string) FakeLoader { // Create fake filesystem and inject it into initial Loader. - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.Mkdir(initialDir) ldr, err := loader.NewLoader( lr, validators.MakeFakeValidator(), initialDir, fSys) diff --git a/k8sdeps/configmapandsecret/configmapfactory_test.go b/k8sdeps/configmapandsecret/configmapfactory_test.go index b8d705190..fe75fa3ca 100644 --- a/k8sdeps/configmapandsecret/configmapfactory_test.go +++ b/k8sdeps/configmapandsecret/configmapfactory_test.go @@ -131,15 +131,15 @@ func TestConstructConfigMap(t *testing.T) { }, } - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.WriteFile( - fSys.RPath("configmap", "app.env"), + fs.RPath("configmap", "app.env"), []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n")) fSys.WriteFile( - fSys.RPath("configmap", "app-init.ini"), + fs.RPath("configmap", "app-init.ini"), []byte("FOO=bar\nBAR=baz\n")) fSys.WriteFile( - fSys.RPath("configmap", "app.bin"), + fs.RPath("configmap", "app.bin"), []byte{0xff, 0xfd}) ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) for _, tc := range testCases { diff --git a/k8sdeps/configmapandsecret/secretfactory_test.go b/k8sdeps/configmapandsecret/secretfactory_test.go index d10e7552d..81b6ffe74 100644 --- a/k8sdeps/configmapandsecret/secretfactory_test.go +++ b/k8sdeps/configmapandsecret/secretfactory_test.go @@ -123,7 +123,7 @@ func TestConstructSecret(t *testing.T) { }, } - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.WriteFile("/secret/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n")) fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n")) ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) diff --git a/pkg/fs/confirmeddir.go b/pkg/fs/confirmeddir.go index 5d12bf077..bb656882a 100644 --- a/pkg/fs/confirmeddir.go +++ b/pkg/fs/confirmeddir.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -27,7 +14,7 @@ import ( type ConfirmedDir string // NewTmpConfirmedDir returns a temporary dir, else error. -// The directory is cleaned, no symlinks, etc. so its +// The directory is cleaned, no symlinks, etc. so it's // returned as a ConfirmedDir. func NewTmpConfirmedDir() (ConfirmedDir, error) { n, err := ioutil.TempDir("", "kustomize-") @@ -36,13 +23,12 @@ func NewTmpConfirmedDir() (ConfirmedDir, error) { } // In MacOs `ioutil.TempDir` creates a directory - // with root in the `/var` folder, which is in turn a symlinked path - // to `/private/var`. + // with root in the `/var` folder, which is in turn + // a symlinked path to `/private/var`. // Function `filepath.EvalSymlinks`is used to // resolve the real absolute path. deLinked, err := filepath.EvalSymlinks(n) return ConfirmedDir(deLinked), err - } // HasPrefix returns true if the directory argument diff --git a/pkg/fs/confirmeddir_test.go b/pkg/fs/confirmeddir_test.go index 7b603f733..2b386eee4 100644 --- a/pkg/fs/confirmeddir_test.go +++ b/pkg/fs/confirmeddir_test.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -22,7 +9,7 @@ import ( ) func TestJoin(t *testing.T) { - fSys := MakeFakeFS() + fSys := MakeFsInMemory() err := fSys.Mkdir("/foo") if err != nil { t.Fatalf("unexpected err: %v", err) @@ -40,7 +27,7 @@ func TestJoin(t *testing.T) { } func TestHasPrefix_Slash(t *testing.T) { - d, f, err := MakeFakeFS().CleanedAbs("/") + d, f, err := MakeFsInMemory().CleanedAbs("/") if err != nil { t.Fatalf("unexpected err: %v", err) } @@ -56,7 +43,7 @@ func TestHasPrefix_Slash(t *testing.T) { } func TestHasPrefix_SlashFoo(t *testing.T) { - fSys := MakeFakeFS() + fSys := MakeFsInMemory() err := fSys.Mkdir("/foo") if err != nil { t.Fatalf("unexpected err: %v", err) @@ -77,7 +64,7 @@ func TestHasPrefix_SlashFoo(t *testing.T) { } func TestHasPrefix_SlashFooBar(t *testing.T) { - fSys := MakeFakeFS() + fSys := MakeFsInMemory() err := fSys.MkdirAll("/foo/bar") if err != nil { t.Fatalf("unexpected err: %v", err) diff --git a/pkg/fs/fakefile.go b/pkg/fs/fakefile.go deleted file mode 100644 index 64bc55685..000000000 --- a/pkg/fs/fakefile.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fs - -import ( - "bytes" - "os" -) - -var _ File = &FakeFile{} - -// FakeFile implements File in-memory for tests. -type FakeFile struct { - name string - content []byte - dir bool - open bool -} - -// makeDir makes a fake directory. -func makeDir(name string) *FakeFile { - return &FakeFile{name: name, dir: true} -} - -// Close marks the fake file closed. -func (f *FakeFile) Close() error { - f.open = false - return nil -} - -// Read never fails, and doesn't mutate p. -func (f *FakeFile) Read(p []byte) (n int, err error) { - return len(p), nil -} - -// Write saves the contents of the argument to memory. -func (f *FakeFile) Write(p []byte) (n int, err error) { - f.content = p - return len(p), nil -} - -// ContentMatches returns true if v matches fake file's content. -func (f *FakeFile) ContentMatches(v []byte) bool { - return bytes.Equal(v, f.content) -} - -// GetContent the content of a fake file. -func (f *FakeFile) GetContent() []byte { - return f.content -} - -// Stat returns nil. -func (f *FakeFile) Stat() (os.FileInfo, error) { - return nil, nil -} diff --git a/pkg/fs/fakefileinfo.go b/pkg/fs/fakefileinfo.go deleted file mode 100644 index 6ccca9150..000000000 --- a/pkg/fs/fakefileinfo.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fs - -import ( - "os" - "time" -) - -var _ os.FileInfo = &Fakefileinfo{} - -// Fakefileinfo implements Fakefileinfo using a fake in-memory filesystem. -type Fakefileinfo struct { - *FakeFile -} - -// Name returns the name of the file -func (fi *Fakefileinfo) Name() string { return fi.name } - -// Size returns the size of the file -func (fi *Fakefileinfo) Size() int64 { return int64(len(fi.content)) } - -// Mode returns the file mode -func (fi *Fakefileinfo) Mode() os.FileMode { return 0777 } - -// ModTime returns the modification time -func (fi *Fakefileinfo) ModTime() time.Time { return time.Time{} } - -// IsDir returns if it is a directory -func (fi *Fakefileinfo) IsDir() bool { return fi.dir } - -// Sys should return underlying data source, but it now returns nil -func (fi *Fakefileinfo) Sys() interface{} { return nil } diff --git a/pkg/fs/fileinfo.go b/pkg/fs/fileinfo.go new file mode 100644 index 000000000..8e271eb38 --- /dev/null +++ b/pkg/fs/fileinfo.go @@ -0,0 +1,34 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package fs + +import ( + "os" + "time" +) + +var _ os.FileInfo = &fileInfo{} + +// fileInfo implements os.FileInfo for a fileInMemory instance. +type fileInfo struct { + *fileInMemory +} + +// Name returns the name of the file +func (fi *fileInfo) Name() string { return fi.name } + +// Size returns the size of the file +func (fi *fileInfo) Size() int64 { return int64(len(fi.content)) } + +// Mode returns the file mode +func (fi *fileInfo) Mode() os.FileMode { return 0777 } + +// ModTime returns the modification time +func (fi *fileInfo) ModTime() time.Time { return time.Time{} } + +// IsDir returns if it is a directory +func (fi *fileInfo) IsDir() bool { return fi.dir } + +// Sys should return underlying data source, but it now returns nil +func (fi *fileInfo) Sys() interface{} { return nil } diff --git a/pkg/fs/fileinmemory.go b/pkg/fs/fileinmemory.go new file mode 100644 index 000000000..ddde5783f --- /dev/null +++ b/pkg/fs/fileinmemory.go @@ -0,0 +1,56 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package fs + +import ( + "bytes" + "os" +) + +var _ File = &fileInMemory{} + +// fileInMemory implements File in-memory for tests. +type fileInMemory struct { + name string + content []byte + dir bool + open bool +} + +// makeDir makes a fake directory. +func makeDir(name string) *fileInMemory { + return &fileInMemory{name: name, dir: true} +} + +// Close marks the fake file closed. +func (f *fileInMemory) Close() error { + f.open = false + return nil +} + +// Read never fails, and doesn't mutate p. +func (f *fileInMemory) Read(p []byte) (n int, err error) { + return len(p), nil +} + +// Write saves the contents of the argument to memory. +func (f *fileInMemory) Write(p []byte) (n int, err error) { + f.content = p + return len(p), nil +} + +// ContentMatches returns true if v matches fake file's content. +func (f *fileInMemory) ContentMatches(v []byte) bool { + return bytes.Equal(v, f.content) +} + +// GetContent the content of a fake file. +func (f *fileInMemory) GetContent() []byte { + return f.content +} + +// Stat returns nil. +func (f *fileInMemory) Stat() (os.FileInfo, error) { + return nil, nil +} diff --git a/pkg/fs/fileondisk.go b/pkg/fs/fileondisk.go new file mode 100644 index 000000000..fc5cd5b90 --- /dev/null +++ b/pkg/fs/fileondisk.go @@ -0,0 +1,27 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package fs + +import ( + "os" +) + +var _ File = &fileOnDisk{} + +// fileOnDisk implements File using the local filesystem. +type fileOnDisk struct { + file *os.File +} + +// Close closes a file. +func (f *fileOnDisk) Close() error { return f.file.Close() } + +// Read reads a file's content. +func (f *fileOnDisk) Read(p []byte) (n int, err error) { return f.file.Read(p) } + +// Write writes bytes to a file +func (f *fileOnDisk) Write(p []byte) (n int, err error) { return f.file.Write(p) } + +// Stat returns an interface which has all the information regarding the file. +func (f *fileOnDisk) Stat() (os.FileInfo, error) { return f.file.Stat() } diff --git a/pkg/fs/fs.go b/pkg/fs/fs.go index f66037057..9fad00052 100644 --- a/pkg/fs/fs.go +++ b/pkg/fs/fs.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 // Package fs provides a file system abstraction layer. package fs @@ -25,17 +12,33 @@ import ( // FileSystem groups basic os filesystem methods. type FileSystem interface { + // Create a file. Create(name string) (File, error) - Mkdir(name string) error - MkdirAll(name string) error - RemoveAll(name string) error - Open(name string) (File, error) - IsDir(name string) bool + // MkDir makes a directory. + Mkdir(path string) error + // MkDir makes a directory path, creating intervening directories. + MkdirAll(path string) error + // RemoveAll removes path and any children it contains. + RemoveAll(path string) error + // Open opens the named file for reading. + Open(path string) (File, error) + // IsDir returns true if the path is a directory. + IsDir(path string) bool + // CleanedAbs converts the given path into a + // directory and a file name, where the directory + // is represented as a ConfirmedDir and all that implies. + // If the entire path is a directory, the file component + // is an empty string. CleanedAbs(path string) (ConfirmedDir, string, error) - Exists(name string) bool + // Exists is true if the path exists in the file system. + Exists(path string) bool + // Glob returns the list of matching files Glob(pattern string) ([]string, error) - ReadFile(name string) ([]byte, error) - WriteFile(name string, data []byte) error + // ReadFile returns the contents of the file at the given path. + ReadFile(path string) ([]byte, error) + // WriteFile writes the data to a file at the given path. + WriteFile(path string, data []byte) error + // Walk walks the file system with the given WalkFunc. Walk(path string, walkFn filepath.WalkFunc) error } diff --git a/pkg/fs/fakefs.go b/pkg/fs/fsinmemory.go similarity index 67% rename from pkg/fs/fakefs.go rename to pkg/fs/fsinmemory.go index 1c607ee3b..28e6021af 100644 --- a/pkg/fs/fakefs.go +++ b/pkg/fs/fsinmemory.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -26,16 +13,17 @@ import ( "sigs.k8s.io/kustomize/v3/pkg/pgmconfig" ) -var _ FileSystem = &fakeFs{} +var _ FileSystem = &fsInMemory{} -// fakeFs implements FileSystem using a fake in-memory filesystem. -type fakeFs struct { - m map[string]*FakeFile +// fsInMemory implements FileSystem using a in-memory filesystem +// primarily for use in tests. +type fsInMemory struct { + m map[string]*fileInMemory } -// MakeFakeFS returns an instance of fakeFs with no files in it. -func MakeFakeFS() *fakeFs { - result := &fakeFs{m: map[string]*FakeFile{}} +// MakeFsInMemory returns an instance of fsInMemory with no files in it. +func MakeFsInMemory() FileSystem { + result := &fsInMemory{m: map[string]*fileInMemory{}} result.Mkdir(separator) return result } @@ -66,32 +54,27 @@ secretGenerator: [] ) // Create assures a fake file appears in the in-memory file system. -func (fs *fakeFs) Create(name string) (File, error) { - f := &FakeFile{} +func (fs *fsInMemory) Create(name string) (File, error) { + f := &fileInMemory{} f.open = true fs.m[name] = f return fs.m[name], nil } -// RPath returns a rooted path, e.g. "/hey/foo" as opposed to "hey/foo". -func (fs *fakeFs) RPath(elem ...string) string { - return separator + filepath.Join(elem...) -} - // Mkdir assures a fake directory appears in the in-memory file system. -func (fs *fakeFs) Mkdir(name string) error { +func (fs *fsInMemory) Mkdir(name string) error { fs.m[name] = makeDir(name) return nil } // MkdirAll delegates to Mkdir -func (fs *fakeFs) MkdirAll(name string) error { +func (fs *fsInMemory) MkdirAll(name string) error { return fs.Mkdir(name) } // RemoveAll presumably does rm -r on a path. // There's no error. -func (fs *fakeFs) RemoveAll(name string) error { +func (fs *fsInMemory) RemoveAll(name string) error { var toRemove []string for k := range fs.m { if strings.HasPrefix(k, name) { @@ -105,7 +88,7 @@ func (fs *fakeFs) RemoveAll(name string) error { } // Open returns a fake file in the open state. -func (fs *fakeFs) Open(name string) (File, error) { +func (fs *fsInMemory) Open(name string) (File, error) { if _, found := fs.m[name]; !found { return nil, fmt.Errorf("file %q cannot be opened", name) } @@ -113,7 +96,7 @@ func (fs *fakeFs) Open(name string) (File, error) { } // CleanedAbs cannot fail. -func (fs *fakeFs) CleanedAbs(path string) (ConfirmedDir, string, error) { +func (fs *fsInMemory) CleanedAbs(path string) (ConfirmedDir, string, error) { if fs.IsDir(path) { return ConfirmedDir(path), "", nil } @@ -125,13 +108,13 @@ func (fs *fakeFs) CleanedAbs(path string) (ConfirmedDir, string, error) { } // Exists returns true if file is known. -func (fs *fakeFs) Exists(name string) bool { +func (fs *fsInMemory) Exists(name string) bool { _, found := fs.m[name] return found } // Glob returns the list of matching files -func (fs *fakeFs) Glob(pattern string) ([]string, error) { +func (fs *fsInMemory) Glob(pattern string) ([]string, error) { var result []string for p := range fs.m { if fs.pathMatch(p, pattern) { @@ -143,7 +126,7 @@ func (fs *fakeFs) Glob(pattern string) ([]string, error) { } // IsDir returns true if the file exists and is a directory. -func (fs *fakeFs) IsDir(name string) bool { +func (fs *fsInMemory) IsDir(name string) bool { f, found := fs.m[name] if found && f.dir { return true @@ -160,37 +143,37 @@ func (fs *fakeFs) IsDir(name string) bool { } // ReadFile always returns an empty bytes and error depending on content of m. -func (fs *fakeFs) ReadFile(name string) ([]byte, error) { +func (fs *fsInMemory) ReadFile(name string) ([]byte, error) { if ff, found := fs.m[name]; found { return ff.content, nil } return nil, fmt.Errorf("cannot read file %q", name) } -func (fs *fakeFs) ReadTestKustomization() ([]byte, error) { +func (fs *fsInMemory) ReadTestKustomization() ([]byte, error) { return fs.ReadFile(pgmconfig.KustomizationFileNames[0]) } // WriteFile always succeeds and does nothing. -func (fs *fakeFs) WriteFile(name string, c []byte) error { - ff := &FakeFile{} +func (fs *fsInMemory) WriteFile(name string, c []byte) error { + ff := &fileInMemory{} ff.Write(c) fs.m[name] = ff return nil } // WriteTestKustomization writes a standard test file. -func (fs *fakeFs) WriteTestKustomization() { +func (fs *fsInMemory) WriteTestKustomization() { fs.WriteTestKustomizationWith([]byte(kustomizationContent)) } // WriteTestKustomizationWith writes a standard test file. -func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) { +func (fs *fsInMemory) WriteTestKustomizationWith(bytes []byte) { fs.WriteFile(pgmconfig.KustomizationFileNames[0], bytes) } // Walk implements filepath.Walk using the fake filesystem. -func (fs *fakeFs) Walk(path string, walkFn filepath.WalkFunc) error { +func (fs *fsInMemory) Walk(path string, walkFn filepath.WalkFunc) error { info, err := fs.lstat(path) if err != nil { err = walkFn(path, info, err) @@ -203,20 +186,20 @@ func (fs *fakeFs) Walk(path string, walkFn filepath.WalkFunc) error { return err } -func (fs *fakeFs) pathMatch(path, pattern string) bool { +func (fs *fsInMemory) pathMatch(path, pattern string) bool { match, _ := filepath.Match(pattern, path) return match } -func (fs *fakeFs) lstat(path string) (*Fakefileinfo, error) { +func (fs *fsInMemory) lstat(path string) (*fileInfo, error) { f, found := fs.m[path] if !found { return nil, os.ErrNotExist } - return &Fakefileinfo{f}, nil + return &fileInfo{f}, nil } -func (fs *fakeFs) join(elem ...string) string { +func (fs *fsInMemory) join(elem ...string) string { for i, e := range elem { if e != "" { return strings.Replace( @@ -226,7 +209,7 @@ func (fs *fakeFs) join(elem ...string) string { return "" } -func (fs *fakeFs) readDirNames(path string) []string { +func (fs *fsInMemory) readDirNames(path string) []string { var names []string if !strings.HasSuffix(path, separator) { path += separator @@ -247,7 +230,7 @@ func (fs *fakeFs) readDirNames(path string) []string { return names } -func (fs *fakeFs) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { +func (fs *fsInMemory) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { if !info.IsDir() { return walkFn(path, info, nil) } diff --git a/pkg/fs/fakefs_test.go b/pkg/fs/fsinmemory_test.go similarity index 80% rename from pkg/fs/fakefs_test.go rename to pkg/fs/fsinmemory_test.go index d45cd81e7..4665880dc 100644 --- a/pkg/fs/fakefs_test.go +++ b/pkg/fs/fsinmemory_test.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -23,7 +10,7 @@ import ( ) func TestExists(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() if x.Exists("foo") { t.Fatalf("expected no foo") } @@ -34,7 +21,7 @@ func TestExists(t *testing.T) { } func TestIsDir(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() expectedName := "my-dir" err := x.Mkdir(expectedName) if err != nil { @@ -59,7 +46,7 @@ func shouldNotExist(t *testing.T, fs FileSystem, name string) { } func TestRemoveAll(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() x.WriteFile("/foo/project/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused")) x.WriteFile("/foo/apple/subdir/file.yaml", []byte("Unused")) @@ -76,7 +63,7 @@ func TestRemoveAll(t *testing.T) { } func TestIsDirDeeper(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() x.WriteFile("/foo/project/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused")) if !x.IsDir("/") { @@ -97,7 +84,7 @@ func TestIsDirDeeper(t *testing.T) { } func TestCreate(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() f, err := x.Create("foo") if f == nil { t.Fatalf("expected file") @@ -109,7 +96,7 @@ func TestCreate(t *testing.T) { } func TestReadFile(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() f, err := x.Create("foo") if f == nil { t.Fatalf("expected file") @@ -127,7 +114,7 @@ func TestReadFile(t *testing.T) { } func TestWriteFile(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() c := []byte("heybuddy") err := x.WriteFile("foo", c) if err != nil { @@ -143,7 +130,7 @@ func TestWriteFile(t *testing.T) { } func TestGlob(t *testing.T) { - x := MakeFakeFS() + x := MakeFsInMemory() x.Create("dir/foo") x.Create("dir/bar") files, err := x.Glob("dir/*") diff --git a/pkg/fs/realfs.go b/pkg/fs/fsondisk.go similarity index 52% rename from pkg/fs/realfs.go rename to pkg/fs/fsondisk.go index 0fce64f3a..da787a4c0 100644 --- a/pkg/fs/realfs.go +++ b/pkg/fs/fsondisk.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -24,43 +11,43 @@ import ( "path/filepath" ) -var _ FileSystem = realFS{} +var _ FileSystem = fsOnDisk{} -// realFS implements FileSystem using the local filesystem. -type realFS struct{} +// fsOnDisk implements FileSystem using the local filesystem. +type fsOnDisk struct{} -// MakeRealFS makes an instance of realFS. -func MakeRealFS() FileSystem { - return realFS{} +// MakeFsOnDisk makes an instance of fsOnDisk. +func MakeFsOnDisk() FileSystem { + return fsOnDisk{} } // Create delegates to os.Create. -func (realFS) Create(name string) (File, error) { return os.Create(name) } +func (fsOnDisk) Create(name string) (File, error) { return os.Create(name) } // Mkdir delegates to os.Mkdir. -func (realFS) Mkdir(name string) error { +func (fsOnDisk) Mkdir(name string) error { return os.Mkdir(name, 0777|os.ModeDir) } // MkdirAll delegates to os.MkdirAll. -func (realFS) MkdirAll(name string) error { +func (fsOnDisk) MkdirAll(name string) error { return os.MkdirAll(name, 0777|os.ModeDir) } // RemoveAll delegates to os.RemoveAll. -func (realFS) RemoveAll(name string) error { +func (fsOnDisk) RemoveAll(name string) error { return os.RemoveAll(name) } // Open delegates to os.Open. -func (realFS) Open(name string) (File, error) { return os.Open(name) } +func (fsOnDisk) Open(name string) (File, error) { return os.Open(name) } -// CleanedAbs returns a cleaned, absolute path -// with no symbolic links split into directory -// and file components. If the entire path is -// a directory, the file component is an empty -// string. -func (x realFS) CleanedAbs( +// CleanedAbs converts the given path into a +// directory and a file name, where the directory +// is represented as a ConfirmedDir and all that implies. +// If the entire path is a directory, the file component +// is an empty string. +func (x fsOnDisk) CleanedAbs( path string) (ConfirmedDir, string, error) { absRoot, err := filepath.Abs(path) if err != nil { @@ -94,18 +81,18 @@ func (x realFS) CleanedAbs( } // Exists returns true if os.Stat succeeds. -func (realFS) Exists(name string) bool { +func (fsOnDisk) Exists(name string) bool { _, err := os.Stat(name) return err == nil } // Glob returns the list of matching files -func (realFS) Glob(pattern string) ([]string, error) { +func (fsOnDisk) Glob(pattern string) ([]string, error) { return filepath.Glob(pattern) } // IsDir delegates to os.Stat and FileInfo.IsDir -func (realFS) IsDir(name string) bool { +func (fsOnDisk) IsDir(name string) bool { info, err := os.Stat(name) if err != nil { return false @@ -114,14 +101,14 @@ func (realFS) IsDir(name string) bool { } // ReadFile delegates to ioutil.ReadFile. -func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } +func (fsOnDisk) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } // WriteFile delegates to ioutil.WriteFile with read/write permissions. -func (realFS) WriteFile(name string, c []byte) error { +func (fsOnDisk) WriteFile(name string, c []byte) error { return ioutil.WriteFile(name, c, 0666) } // Walk delegates to filepath.Walk. -func (realFS) Walk(path string, walkFn filepath.WalkFunc) error { +func (fsOnDisk) Walk(path string, walkFn filepath.WalkFunc) error { return filepath.Walk(path, walkFn) } diff --git a/pkg/fs/realfs_test.go b/pkg/fs/fsondisk_test.go similarity index 84% rename from pkg/fs/realfs_test.go rename to pkg/fs/fsondisk_test.go index 6e07f2fe3..91efebfcc 100644 --- a/pkg/fs/realfs_test.go +++ b/pkg/fs/fsondisk_test.go @@ -1,18 +1,5 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 package fs @@ -26,7 +13,7 @@ import ( ) func makeTestDir(t *testing.T) (FileSystem, string) { - x := MakeRealFS() + x := MakeFsOnDisk() td, err := ioutil.TempDir("", "kustomize_testing_dir") if err != nil { t.Fatalf("unexpected error %s", err) @@ -100,7 +87,6 @@ func TestCleanedAbs_3(t *testing.T) { if f != "foo" { t.Fatalf("unexpected f=%s", f) } - } func TestCleanedAbs_4(t *testing.T) { diff --git a/pkg/fs/realfile.go b/pkg/fs/realfile.go deleted file mode 100644 index 5bfec55ab..000000000 --- a/pkg/fs/realfile.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fs - -import ( - "os" -) - -var _ File = &realFile{} - -// realFile implements File using the local filesystem. -type realFile struct { - file *os.File -} - -// Close closes a file. -func (f *realFile) Close() error { return f.file.Close() } - -// Read reads a file's content. -func (f *realFile) Read(p []byte) (n int, err error) { return f.file.Read(p) } - -// Write writes bytes to a file -func (f *realFile) Write(p []byte) (n int, err error) { return f.file.Write(p) } - -// Stat returns an interface which has all the information regarding the file. -func (f *realFile) Stat() (os.FileInfo, error) { return f.file.Stat() } diff --git a/pkg/fs/rpath.go b/pkg/fs/rpath.go new file mode 100644 index 000000000..641d55d80 --- /dev/null +++ b/pkg/fs/rpath.go @@ -0,0 +1,12 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package fs + +import "path/filepath" + +// RPath returns a rooted path, e.g. "/hey/foo" as +// opposed to "hey/foo". +func RPath(elem ...string) string { + return separator + filepath.Join(elem...) +} diff --git a/pkg/loader/fileloader_test.go b/pkg/loader/fileloader_test.go index 7b829025c..ccd7d1666 100644 --- a/pkg/loader/fileloader_test.go +++ b/pkg/loader/fileloader_test.go @@ -57,7 +57,7 @@ var testCases = []testData{ } func MakeFakeFs(td []testData) fs.FileSystem { - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() for _, x := range td { fSys.WriteFile("/"+x.path, []byte(x.expectedContent)) } @@ -230,7 +230,7 @@ func commonSetupForLoaderRestrictionTest() (string, fs.FileSystem, error) { if err != nil { return "", nil, err } - fSys := fs.MakeRealFS() + fSys := fs.MakeFsOnDisk() fSys.Mkdir(filepath.Join(dir, "base")) fSys.WriteFile( @@ -385,7 +385,7 @@ func TestNewLoaderAtGitClone(t *testing.T) { pathInRepo := "foo/base" url := rootUrl + "/" + pathInRepo coRoot := "/tmp" - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.MkdirAll(coRoot) fSys.MkdirAll(coRoot + "/" + pathInRepo) fSys.WriteFile( @@ -432,7 +432,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) { // Define an overlay-base structure in the file system. topDir := "/whatever" cloneRoot := topDir + "/someClone" - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.MkdirAll(topDir + "/highBase") fSys.MkdirAll(cloneRoot + "/foo/base") fSys.MkdirAll(cloneRoot + "/foo/overlay") @@ -508,7 +508,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) { func TestLocalLoaderReferencingGitBase(t *testing.T) { topDir := "/whatever" cloneRoot := topDir + "/someClone" - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.MkdirAll(topDir) fSys.MkdirAll(cloneRoot + "/foo/base") @@ -534,7 +534,7 @@ func TestLocalLoaderReferencingGitBase(t *testing.T) { func TestRepoDirectCycleDetection(t *testing.T) { topDir := "/cycles" cloneRoot := topDir + "/someClone" - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.MkdirAll(topDir) fSys.MkdirAll(cloneRoot) @@ -563,7 +563,7 @@ func TestRepoDirectCycleDetection(t *testing.T) { func TestRepoIndirectCycleDetection(t *testing.T) { topDir := "/cycles" cloneRoot := topDir + "/someClone" - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.MkdirAll(topDir) fSys.MkdirAll(cloneRoot) diff --git a/pkg/loader/kv_test.go b/pkg/loader/kv_test.go index 9ee2a8978..6f2df70e9 100644 --- a/pkg/loader/kv_test.go +++ b/pkg/loader/kv_test.go @@ -46,7 +46,7 @@ func TestKeyValuesFromLines(t *testing.T) { } l := NewFileLoaderAtRoot( - validators.MakeFakeValidator(), fs.MakeFakeFS()) + validators.MakeFakeValidator(), fs.MakeFsInMemory()) for _, test := range tests { pairs, err := l.keyValuesFromLines([]byte(test.content)) if test.expectedErr && err == nil { @@ -76,7 +76,7 @@ func TestKeyValuesFromFileSources(t *testing.T) { }, } - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar")) l := NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) for _, tc := range tests { diff --git a/pkg/loader/loadrestrictions_test.go b/pkg/loader/loadrestrictions_test.go index 58ed0583e..9795ef958 100644 --- a/pkg/loader/loadrestrictions_test.go +++ b/pkg/loader/loadrestrictions_test.go @@ -24,7 +24,7 @@ import ( ) func TestRestrictionNone(t *testing.T) { - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() root := fs.ConfirmedDir("irrelevant") path := "whatever" p, err := RestrictionNone(fSys, root, path) @@ -37,7 +37,7 @@ func TestRestrictionNone(t *testing.T) { } func TestRestrictionRootOnly(t *testing.T) { - fSys := fs.MakeFakeFS() + fSys := fs.MakeFsInMemory() root := fs.ConfirmedDir("/tmp/foo") path := "/tmp/foo/whatever/beans" diff --git a/pkg/resmap/factory_test.go b/pkg/resmap/factory_test.go index 67c147128..4f04d0295 100644 --- a/pkg/resmap/factory_test.go +++ b/pkg/resmap/factory_test.go @@ -234,7 +234,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { Type: ifc.SecretTypeOpaque, }, } - fakeFs := fs.MakeFakeFS() + fakeFs := fs.MakeFsInMemory() fakeFs.Mkdir(".") actual, err := rmF.NewResMapFromSecretArgs( loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fakeFs), nil, secrets) diff --git a/pkg/target/plugindir_test.go b/pkg/target/plugindir_test.go index e804b5b76..a3044b560 100644 --- a/pkg/target/plugindir_test.go +++ b/pkg/target/plugindir_test.go @@ -39,7 +39,7 @@ func TestPluginDir(t *testing.T) { } defer os.RemoveAll(dir) - fSys := fs.MakeRealFS() + fSys := fs.MakeFsOnDisk() err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(` generators: - config.yaml