Improve fs package and doc in prep to officially go public

This commit is contained in:
Jeffrey Regan
2019-10-01 10:38:00 -07:00
parent 07634ef098
commit 9a94bcb854
22 changed files with 256 additions and 364 deletions

View File

@@ -33,7 +33,7 @@ func NewFakeLoader(initialDir string) FakeLoader {
func NewFakeLoaderWithRestrictor( func NewFakeLoaderWithRestrictor(
lr loader.LoadRestrictorFunc, initialDir string) FakeLoader { lr loader.LoadRestrictorFunc, initialDir string) FakeLoader {
// Create fake filesystem and inject it into initial Loader. // Create fake filesystem and inject it into initial Loader.
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.Mkdir(initialDir) fSys.Mkdir(initialDir)
ldr, err := loader.NewLoader( ldr, err := loader.NewLoader(
lr, validators.MakeFakeValidator(), initialDir, fSys) lr, validators.MakeFakeValidator(), initialDir, fSys)

View File

@@ -131,15 +131,15 @@ func TestConstructConfigMap(t *testing.T) {
}, },
} }
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.WriteFile( fSys.WriteFile(
fSys.RPath("configmap", "app.env"), fs.RPath("configmap", "app.env"),
[]byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n")) []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile( fSys.WriteFile(
fSys.RPath("configmap", "app-init.ini"), fs.RPath("configmap", "app-init.ini"),
[]byte("FOO=bar\nBAR=baz\n")) []byte("FOO=bar\nBAR=baz\n"))
fSys.WriteFile( fSys.WriteFile(
fSys.RPath("configmap", "app.bin"), fs.RPath("configmap", "app.bin"),
[]byte{0xff, 0xfd}) []byte{0xff, 0xfd})
ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys)
for _, tc := range testCases { for _, tc := range testCases {

View File

@@ -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.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n")) fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys)

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -27,7 +14,7 @@ import (
type ConfirmedDir string type ConfirmedDir string
// NewTmpConfirmedDir returns a temporary dir, else error. // 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. // returned as a ConfirmedDir.
func NewTmpConfirmedDir() (ConfirmedDir, error) { func NewTmpConfirmedDir() (ConfirmedDir, error) {
n, err := ioutil.TempDir("", "kustomize-") n, err := ioutil.TempDir("", "kustomize-")
@@ -36,13 +23,12 @@ func NewTmpConfirmedDir() (ConfirmedDir, error) {
} }
// In MacOs `ioutil.TempDir` creates a directory // In MacOs `ioutil.TempDir` creates a directory
// with root in the `/var` folder, which is in turn a symlinked path // with root in the `/var` folder, which is in turn
// to `/private/var`. // a symlinked path to `/private/var`.
// Function `filepath.EvalSymlinks`is used to // Function `filepath.EvalSymlinks`is used to
// resolve the real absolute path. // resolve the real absolute path.
deLinked, err := filepath.EvalSymlinks(n) deLinked, err := filepath.EvalSymlinks(n)
return ConfirmedDir(deLinked), err return ConfirmedDir(deLinked), err
} }
// HasPrefix returns true if the directory argument // HasPrefix returns true if the directory argument

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -22,7 +9,7 @@ import (
) )
func TestJoin(t *testing.T) { func TestJoin(t *testing.T) {
fSys := MakeFakeFS() fSys := MakeFsInMemory()
err := fSys.Mkdir("/foo") err := fSys.Mkdir("/foo")
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) t.Fatalf("unexpected err: %v", err)
@@ -40,7 +27,7 @@ func TestJoin(t *testing.T) {
} }
func TestHasPrefix_Slash(t *testing.T) { func TestHasPrefix_Slash(t *testing.T) {
d, f, err := MakeFakeFS().CleanedAbs("/") d, f, err := MakeFsInMemory().CleanedAbs("/")
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) t.Fatalf("unexpected err: %v", err)
} }
@@ -56,7 +43,7 @@ func TestHasPrefix_Slash(t *testing.T) {
} }
func TestHasPrefix_SlashFoo(t *testing.T) { func TestHasPrefix_SlashFoo(t *testing.T) {
fSys := MakeFakeFS() fSys := MakeFsInMemory()
err := fSys.Mkdir("/foo") err := fSys.Mkdir("/foo")
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) t.Fatalf("unexpected err: %v", err)
@@ -77,7 +64,7 @@ func TestHasPrefix_SlashFoo(t *testing.T) {
} }
func TestHasPrefix_SlashFooBar(t *testing.T) { func TestHasPrefix_SlashFooBar(t *testing.T) {
fSys := MakeFakeFS() fSys := MakeFsInMemory()
err := fSys.MkdirAll("/foo/bar") err := fSys.MkdirAll("/foo/bar")
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) t.Fatalf("unexpected err: %v", err)

View File

@@ -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
}

View File

@@ -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 }

34
pkg/fs/fileinfo.go Normal file
View File

@@ -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 }

56
pkg/fs/fileinmemory.go Normal file
View File

@@ -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
}

27
pkg/fs/fileondisk.go Normal file
View File

@@ -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() }

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 provides a file system abstraction layer. // Package fs provides a file system abstraction layer.
package fs package fs
@@ -25,17 +12,33 @@ import (
// FileSystem groups basic os filesystem methods. // FileSystem groups basic os filesystem methods.
type FileSystem interface { type FileSystem interface {
// Create a file.
Create(name string) (File, error) Create(name string) (File, error)
Mkdir(name string) error // MkDir makes a directory.
MkdirAll(name string) error Mkdir(path string) error
RemoveAll(name string) error // MkDir makes a directory path, creating intervening directories.
Open(name string) (File, error) MkdirAll(path string) error
IsDir(name string) bool // 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) 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) Glob(pattern string) ([]string, error)
ReadFile(name string) ([]byte, error) // ReadFile returns the contents of the file at the given path.
WriteFile(name string, data []byte) error 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 Walk(path string, walkFn filepath.WalkFunc) error
} }

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -26,16 +13,17 @@ import (
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig" "sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
) )
var _ FileSystem = &fakeFs{} var _ FileSystem = &fsInMemory{}
// fakeFs implements FileSystem using a fake in-memory filesystem. // fsInMemory implements FileSystem using a in-memory filesystem
type fakeFs struct { // primarily for use in tests.
m map[string]*FakeFile type fsInMemory struct {
m map[string]*fileInMemory
} }
// MakeFakeFS returns an instance of fakeFs with no files in it. // MakeFsInMemory returns an instance of fsInMemory with no files in it.
func MakeFakeFS() *fakeFs { func MakeFsInMemory() FileSystem {
result := &fakeFs{m: map[string]*FakeFile{}} result := &fsInMemory{m: map[string]*fileInMemory{}}
result.Mkdir(separator) result.Mkdir(separator)
return result return result
} }
@@ -66,32 +54,27 @@ secretGenerator: []
) )
// Create assures a fake file appears in the in-memory file system. // Create assures a fake file appears in the in-memory file system.
func (fs *fakeFs) Create(name string) (File, error) { func (fs *fsInMemory) Create(name string) (File, error) {
f := &FakeFile{} f := &fileInMemory{}
f.open = true f.open = true
fs.m[name] = f fs.m[name] = f
return fs.m[name], nil 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. // 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) fs.m[name] = makeDir(name)
return nil return nil
} }
// MkdirAll delegates to Mkdir // MkdirAll delegates to Mkdir
func (fs *fakeFs) MkdirAll(name string) error { func (fs *fsInMemory) MkdirAll(name string) error {
return fs.Mkdir(name) return fs.Mkdir(name)
} }
// RemoveAll presumably does rm -r on a path. // RemoveAll presumably does rm -r on a path.
// There's no error. // There's no error.
func (fs *fakeFs) RemoveAll(name string) error { func (fs *fsInMemory) RemoveAll(name string) error {
var toRemove []string var toRemove []string
for k := range fs.m { for k := range fs.m {
if strings.HasPrefix(k, name) { 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. // 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 { if _, found := fs.m[name]; !found {
return nil, fmt.Errorf("file %q cannot be opened", name) 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. // 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) { if fs.IsDir(path) {
return ConfirmedDir(path), "", nil return ConfirmedDir(path), "", nil
} }
@@ -125,13 +108,13 @@ func (fs *fakeFs) CleanedAbs(path string) (ConfirmedDir, string, error) {
} }
// Exists returns true if file is known. // 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] _, found := fs.m[name]
return found return found
} }
// Glob returns the list of matching files // 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 var result []string
for p := range fs.m { for p := range fs.m {
if fs.pathMatch(p, pattern) { 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. // 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] f, found := fs.m[name]
if found && f.dir { if found && f.dir {
return true 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. // 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 { if ff, found := fs.m[name]; found {
return ff.content, nil return ff.content, nil
} }
return nil, fmt.Errorf("cannot read file %q", name) 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]) return fs.ReadFile(pgmconfig.KustomizationFileNames[0])
} }
// WriteFile always succeeds and does nothing. // WriteFile always succeeds and does nothing.
func (fs *fakeFs) WriteFile(name string, c []byte) error { func (fs *fsInMemory) WriteFile(name string, c []byte) error {
ff := &FakeFile{} ff := &fileInMemory{}
ff.Write(c) ff.Write(c)
fs.m[name] = ff fs.m[name] = ff
return nil return nil
} }
// WriteTestKustomization writes a standard test file. // WriteTestKustomization writes a standard test file.
func (fs *fakeFs) WriteTestKustomization() { func (fs *fsInMemory) WriteTestKustomization() {
fs.WriteTestKustomizationWith([]byte(kustomizationContent)) fs.WriteTestKustomizationWith([]byte(kustomizationContent))
} }
// WriteTestKustomizationWith writes a standard test file. // WriteTestKustomizationWith writes a standard test file.
func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) { func (fs *fsInMemory) WriteTestKustomizationWith(bytes []byte) {
fs.WriteFile(pgmconfig.KustomizationFileNames[0], bytes) fs.WriteFile(pgmconfig.KustomizationFileNames[0], bytes)
} }
// Walk implements filepath.Walk using the fake filesystem. // 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) info, err := fs.lstat(path)
if err != nil { if err != nil {
err = walkFn(path, info, err) err = walkFn(path, info, err)
@@ -203,20 +186,20 @@ func (fs *fakeFs) Walk(path string, walkFn filepath.WalkFunc) error {
return err return err
} }
func (fs *fakeFs) pathMatch(path, pattern string) bool { func (fs *fsInMemory) pathMatch(path, pattern string) bool {
match, _ := filepath.Match(pattern, path) match, _ := filepath.Match(pattern, path)
return match return match
} }
func (fs *fakeFs) lstat(path string) (*Fakefileinfo, error) { func (fs *fsInMemory) lstat(path string) (*fileInfo, error) {
f, found := fs.m[path] f, found := fs.m[path]
if !found { if !found {
return nil, os.ErrNotExist 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 { for i, e := range elem {
if e != "" { if e != "" {
return strings.Replace( return strings.Replace(
@@ -226,7 +209,7 @@ func (fs *fakeFs) join(elem ...string) string {
return "" return ""
} }
func (fs *fakeFs) readDirNames(path string) []string { func (fs *fsInMemory) readDirNames(path string) []string {
var names []string var names []string
if !strings.HasSuffix(path, separator) { if !strings.HasSuffix(path, separator) {
path += separator path += separator
@@ -247,7 +230,7 @@ func (fs *fakeFs) readDirNames(path string) []string {
return names 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() { if !info.IsDir() {
return walkFn(path, info, nil) return walkFn(path, info, nil)
} }

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -23,7 +10,7 @@ import (
) )
func TestExists(t *testing.T) { func TestExists(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
if x.Exists("foo") { if x.Exists("foo") {
t.Fatalf("expected no foo") t.Fatalf("expected no foo")
} }
@@ -34,7 +21,7 @@ func TestExists(t *testing.T) {
} }
func TestIsDir(t *testing.T) { func TestIsDir(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
expectedName := "my-dir" expectedName := "my-dir"
err := x.Mkdir(expectedName) err := x.Mkdir(expectedName)
if err != nil { if err != nil {
@@ -59,7 +46,7 @@ func shouldNotExist(t *testing.T, fs FileSystem, name string) {
} }
func TestRemoveAll(t *testing.T) { func TestRemoveAll(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
x.WriteFile("/foo/project/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/file.yaml", []byte("Unused"))
x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
x.WriteFile("/foo/apple/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) { func TestIsDirDeeper(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
x.WriteFile("/foo/project/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/file.yaml", []byte("Unused"))
x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused")) x.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
if !x.IsDir("/") { if !x.IsDir("/") {
@@ -97,7 +84,7 @@ func TestIsDirDeeper(t *testing.T) {
} }
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
f, err := x.Create("foo") f, err := x.Create("foo")
if f == nil { if f == nil {
t.Fatalf("expected file") t.Fatalf("expected file")
@@ -109,7 +96,7 @@ func TestCreate(t *testing.T) {
} }
func TestReadFile(t *testing.T) { func TestReadFile(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
f, err := x.Create("foo") f, err := x.Create("foo")
if f == nil { if f == nil {
t.Fatalf("expected file") t.Fatalf("expected file")
@@ -127,7 +114,7 @@ func TestReadFile(t *testing.T) {
} }
func TestWriteFile(t *testing.T) { func TestWriteFile(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
c := []byte("heybuddy") c := []byte("heybuddy")
err := x.WriteFile("foo", c) err := x.WriteFile("foo", c)
if err != nil { if err != nil {
@@ -143,7 +130,7 @@ func TestWriteFile(t *testing.T) {
} }
func TestGlob(t *testing.T) { func TestGlob(t *testing.T) {
x := MakeFakeFS() x := MakeFsInMemory()
x.Create("dir/foo") x.Create("dir/foo")
x.Create("dir/bar") x.Create("dir/bar")
files, err := x.Glob("dir/*") files, err := x.Glob("dir/*")

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -24,43 +11,43 @@ import (
"path/filepath" "path/filepath"
) )
var _ FileSystem = realFS{} var _ FileSystem = fsOnDisk{}
// realFS implements FileSystem using the local filesystem. // fsOnDisk implements FileSystem using the local filesystem.
type realFS struct{} type fsOnDisk struct{}
// MakeRealFS makes an instance of realFS. // MakeFsOnDisk makes an instance of fsOnDisk.
func MakeRealFS() FileSystem { func MakeFsOnDisk() FileSystem {
return realFS{} return fsOnDisk{}
} }
// Create delegates to os.Create. // 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. // Mkdir delegates to os.Mkdir.
func (realFS) Mkdir(name string) error { func (fsOnDisk) Mkdir(name string) error {
return os.Mkdir(name, 0777|os.ModeDir) return os.Mkdir(name, 0777|os.ModeDir)
} }
// MkdirAll delegates to os.MkdirAll. // MkdirAll delegates to os.MkdirAll.
func (realFS) MkdirAll(name string) error { func (fsOnDisk) MkdirAll(name string) error {
return os.MkdirAll(name, 0777|os.ModeDir) return os.MkdirAll(name, 0777|os.ModeDir)
} }
// RemoveAll delegates to os.RemoveAll. // RemoveAll delegates to os.RemoveAll.
func (realFS) RemoveAll(name string) error { func (fsOnDisk) RemoveAll(name string) error {
return os.RemoveAll(name) return os.RemoveAll(name)
} }
// Open delegates to os.Open. // 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 // CleanedAbs converts the given path into a
// with no symbolic links split into directory // directory and a file name, where the directory
// and file components. If the entire path is // is represented as a ConfirmedDir and all that implies.
// a directory, the file component is an empty // If the entire path is a directory, the file component
// string. // is an empty string.
func (x realFS) CleanedAbs( func (x fsOnDisk) CleanedAbs(
path string) (ConfirmedDir, string, error) { path string) (ConfirmedDir, string, error) {
absRoot, err := filepath.Abs(path) absRoot, err := filepath.Abs(path)
if err != nil { if err != nil {
@@ -94,18 +81,18 @@ func (x realFS) CleanedAbs(
} }
// Exists returns true if os.Stat succeeds. // Exists returns true if os.Stat succeeds.
func (realFS) Exists(name string) bool { func (fsOnDisk) Exists(name string) bool {
_, err := os.Stat(name) _, err := os.Stat(name)
return err == nil return err == nil
} }
// Glob returns the list of matching files // 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) return filepath.Glob(pattern)
} }
// IsDir delegates to os.Stat and FileInfo.IsDir // 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) info, err := os.Stat(name)
if err != nil { if err != nil {
return false return false
@@ -114,14 +101,14 @@ func (realFS) IsDir(name string) bool {
} }
// ReadFile delegates to ioutil.ReadFile. // 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. // 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) return ioutil.WriteFile(name, c, 0666)
} }
// Walk delegates to filepath.Walk. // 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) return filepath.Walk(path, walkFn)
} }

View File

@@ -1,18 +1,5 @@
/* // Copyright 2019 The Kubernetes Authors.
Copyright 2018 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0
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 package fs
@@ -26,7 +13,7 @@ import (
) )
func makeTestDir(t *testing.T) (FileSystem, string) { func makeTestDir(t *testing.T) (FileSystem, string) {
x := MakeRealFS() x := MakeFsOnDisk()
td, err := ioutil.TempDir("", "kustomize_testing_dir") td, err := ioutil.TempDir("", "kustomize_testing_dir")
if err != nil { if err != nil {
t.Fatalf("unexpected error %s", err) t.Fatalf("unexpected error %s", err)
@@ -100,7 +87,6 @@ func TestCleanedAbs_3(t *testing.T) {
if f != "foo" { if f != "foo" {
t.Fatalf("unexpected f=%s", f) t.Fatalf("unexpected f=%s", f)
} }
} }
func TestCleanedAbs_4(t *testing.T) { func TestCleanedAbs_4(t *testing.T) {

View File

@@ -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() }

12
pkg/fs/rpath.go Normal file
View File

@@ -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...)
}

View File

@@ -57,7 +57,7 @@ var testCases = []testData{
} }
func MakeFakeFs(td []testData) fs.FileSystem { func MakeFakeFs(td []testData) fs.FileSystem {
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
for _, x := range td { for _, x := range td {
fSys.WriteFile("/"+x.path, []byte(x.expectedContent)) fSys.WriteFile("/"+x.path, []byte(x.expectedContent))
} }
@@ -230,7 +230,7 @@ func commonSetupForLoaderRestrictionTest() (string, fs.FileSystem, error) {
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
fSys := fs.MakeRealFS() fSys := fs.MakeFsOnDisk()
fSys.Mkdir(filepath.Join(dir, "base")) fSys.Mkdir(filepath.Join(dir, "base"))
fSys.WriteFile( fSys.WriteFile(
@@ -385,7 +385,7 @@ func TestNewLoaderAtGitClone(t *testing.T) {
pathInRepo := "foo/base" pathInRepo := "foo/base"
url := rootUrl + "/" + pathInRepo url := rootUrl + "/" + pathInRepo
coRoot := "/tmp" coRoot := "/tmp"
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.MkdirAll(coRoot) fSys.MkdirAll(coRoot)
fSys.MkdirAll(coRoot + "/" + pathInRepo) fSys.MkdirAll(coRoot + "/" + pathInRepo)
fSys.WriteFile( fSys.WriteFile(
@@ -432,7 +432,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
// Define an overlay-base structure in the file system. // Define an overlay-base structure in the file system.
topDir := "/whatever" topDir := "/whatever"
cloneRoot := topDir + "/someClone" cloneRoot := topDir + "/someClone"
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.MkdirAll(topDir + "/highBase") fSys.MkdirAll(topDir + "/highBase")
fSys.MkdirAll(cloneRoot + "/foo/base") fSys.MkdirAll(cloneRoot + "/foo/base")
fSys.MkdirAll(cloneRoot + "/foo/overlay") fSys.MkdirAll(cloneRoot + "/foo/overlay")
@@ -508,7 +508,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
func TestLocalLoaderReferencingGitBase(t *testing.T) { func TestLocalLoaderReferencingGitBase(t *testing.T) {
topDir := "/whatever" topDir := "/whatever"
cloneRoot := topDir + "/someClone" cloneRoot := topDir + "/someClone"
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.MkdirAll(topDir) fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot + "/foo/base") fSys.MkdirAll(cloneRoot + "/foo/base")
@@ -534,7 +534,7 @@ func TestLocalLoaderReferencingGitBase(t *testing.T) {
func TestRepoDirectCycleDetection(t *testing.T) { func TestRepoDirectCycleDetection(t *testing.T) {
topDir := "/cycles" topDir := "/cycles"
cloneRoot := topDir + "/someClone" cloneRoot := topDir + "/someClone"
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.MkdirAll(topDir) fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot) fSys.MkdirAll(cloneRoot)
@@ -563,7 +563,7 @@ func TestRepoDirectCycleDetection(t *testing.T) {
func TestRepoIndirectCycleDetection(t *testing.T) { func TestRepoIndirectCycleDetection(t *testing.T) {
topDir := "/cycles" topDir := "/cycles"
cloneRoot := topDir + "/someClone" cloneRoot := topDir + "/someClone"
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
fSys.MkdirAll(topDir) fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot) fSys.MkdirAll(cloneRoot)

View File

@@ -46,7 +46,7 @@ func TestKeyValuesFromLines(t *testing.T) {
} }
l := NewFileLoaderAtRoot( l := NewFileLoaderAtRoot(
validators.MakeFakeValidator(), fs.MakeFakeFS()) validators.MakeFakeValidator(), fs.MakeFsInMemory())
for _, test := range tests { for _, test := range tests {
pairs, err := l.keyValuesFromLines([]byte(test.content)) pairs, err := l.keyValuesFromLines([]byte(test.content))
if test.expectedErr && err == nil { 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")) fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar"))
l := NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys) l := NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys)
for _, tc := range tests { for _, tc := range tests {

View File

@@ -24,7 +24,7 @@ import (
) )
func TestRestrictionNone(t *testing.T) { func TestRestrictionNone(t *testing.T) {
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
root := fs.ConfirmedDir("irrelevant") root := fs.ConfirmedDir("irrelevant")
path := "whatever" path := "whatever"
p, err := RestrictionNone(fSys, root, path) p, err := RestrictionNone(fSys, root, path)
@@ -37,7 +37,7 @@ func TestRestrictionNone(t *testing.T) {
} }
func TestRestrictionRootOnly(t *testing.T) { func TestRestrictionRootOnly(t *testing.T) {
fSys := fs.MakeFakeFS() fSys := fs.MakeFsInMemory()
root := fs.ConfirmedDir("/tmp/foo") root := fs.ConfirmedDir("/tmp/foo")
path := "/tmp/foo/whatever/beans" path := "/tmp/foo/whatever/beans"

View File

@@ -234,7 +234,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
Type: ifc.SecretTypeOpaque, Type: ifc.SecretTypeOpaque,
}, },
} }
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFsInMemory()
fakeFs.Mkdir(".") fakeFs.Mkdir(".")
actual, err := rmF.NewResMapFromSecretArgs( actual, err := rmF.NewResMapFromSecretArgs(
loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fakeFs), nil, secrets) loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fakeFs), nil, secrets)

View File

@@ -39,7 +39,7 @@ func TestPluginDir(t *testing.T) {
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
fSys := fs.MakeRealFS() fSys := fs.MakeFsOnDisk()
err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(` err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(`
generators: generators:
- config.yaml - config.yaml