From 194d845fc995c6256448f324ef9c876c996a44fa Mon Sep 17 00:00:00 2001 From: Mengqi Yu Date: Tue, 20 Feb 2018 18:07:25 -0800 Subject: [PATCH 01/12] initial commit for file loader --- factory.go | 36 ++++++++++++++++++++++++++++ fake/fakefileloader.go | 36 ++++++++++++++++++++++++++++ fileloader.go | 35 +++++++++++++++++++++++++++ fileloader_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++ loader.go | 21 ++++++++++++++++ 5 files changed, 182 insertions(+) create mode 100644 factory.go create mode 100644 fake/fakefileloader.go create mode 100644 fileloader.go create mode 100644 fileloader_test.go create mode 100644 loader.go diff --git a/factory.go b/factory.go new file mode 100644 index 000000000..86fc97527 --- /dev/null +++ b/factory.go @@ -0,0 +1,36 @@ +/* +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 loader + +import ( + "fmt" + + "k8s.io/kubectl/pkg/kinflate/util/fs" +) + +func GetLoader(location string) (Loader, error) { + switch { + case isFilePath(location): + return NewFileLoader(fs.MakeRealFS(), location) + default: + return nil, fmt.Errorf("unknown scheme: %v", location) + } +} + +func isFilePath(location string) bool { + return true +} diff --git a/fake/fakefileloader.go b/fake/fakefileloader.go new file mode 100644 index 000000000..1df7b2c0b --- /dev/null +++ b/fake/fakefileloader.go @@ -0,0 +1,36 @@ +/* +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 fake + +import "k8s.io/kubectl/pkg/loader" + +type fakefileLoader struct { + data []byte + err error +} + +// NewFakeFileLoader returns Loader which always returns byte array and an error. +// Example: case no error: NewFakeFileLoader(yamlBytes, nil) +// Example: case return an error: NewFakeFileLoader(nil, errors.New("forced error")) +// Location parameter is unneeded because we always return data bytes or an error. +func NewFakeFileLoader(content []byte, e error) (loader.Loader, error) { + return &fakefileLoader{data: content, err: e}, nil +} + +func (l *fakefileLoader) Load() ([]byte, error) { + return l.data, l.err +} diff --git a/fileloader.go b/fileloader.go new file mode 100644 index 000000000..91ce86b0c --- /dev/null +++ b/fileloader.go @@ -0,0 +1,35 @@ +/* +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 loader + +import ( + "k8s.io/kubectl/pkg/kinflate/util/fs" +) + +type fileLoader struct { + fs fs.FileSystem + + path string +} + +func NewFileLoader(fs fs.FileSystem, path string) (Loader, error) { + return &fileLoader{fs: fs, path: path}, nil +} + +func (l *fileLoader) Load() ([]byte, error) { + return l.fs.ReadFile(l.path) +} diff --git a/fileloader_test.go b/fileloader_test.go new file mode 100644 index 000000000..2461e3e76 --- /dev/null +++ b/fileloader_test.go @@ -0,0 +1,54 @@ +/* +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 loader + +import ( + "reflect" + "testing" + + "k8s.io/kubectl/pkg/kinflate/util/fs" +) + +func TestFileLoaderHappyPath(t *testing.T) { + fakefs := fs.MakeFakeFS() + location := "foo" + content := []byte("bar") + fakefs.WriteFile(location, content) + l, err := NewFileLoader(fakefs, location) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + b, err := l.Load() + if err != nil { + t.Fatalf("unexpected error in Load: %v", err) + } + if !reflect.DeepEqual(b, content) { + t.Fatalf("expected %s, but got %s", content, b) + } +} + +func TestFileLoaderFileNotFound(t *testing.T) { + fakefs := fs.MakeFakeFS() + l, err := NewFileLoader(fakefs, "path/does/not/exist") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + _, err = l.Load() + if err == nil { + t.Fatal("expected error in Load, but no error returned") + } +} diff --git a/loader.go b/loader.go new file mode 100644 index 000000000..d6f2fd3cf --- /dev/null +++ b/loader.go @@ -0,0 +1,21 @@ +/* +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 loader + +type Loader interface { + Load() ([]byte, error) +} From c7ec56e3e5add160c5a44492b39e74c7104c3ba3 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Thu, 22 Feb 2018 15:38:43 -0800 Subject: [PATCH 02/12] Refactor Loader interface --- fake/fakefileloader.go | 36 ---------------- fileloader.go | 25 ++++++++--- fileloader_test.go | 8 ++-- loader.go | 83 +++++++++++++++++++++++++++++++++++- factory.go => loader_test.go | 25 ++++++----- 5 files changed, 119 insertions(+), 58 deletions(-) delete mode 100644 fake/fakefileloader.go rename factory.go => loader_test.go (56%) diff --git a/fake/fakefileloader.go b/fake/fakefileloader.go deleted file mode 100644 index 1df7b2c0b..000000000 --- a/fake/fakefileloader.go +++ /dev/null @@ -1,36 +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 fake - -import "k8s.io/kubectl/pkg/loader" - -type fakefileLoader struct { - data []byte - err error -} - -// NewFakeFileLoader returns Loader which always returns byte array and an error. -// Example: case no error: NewFakeFileLoader(yamlBytes, nil) -// Example: case return an error: NewFakeFileLoader(nil, errors.New("forced error")) -// Location parameter is unneeded because we always return data bytes or an error. -func NewFakeFileLoader(content []byte, e error) (loader.Loader, error) { - return &fakefileLoader{data: content, err: e}, nil -} - -func (l *fakefileLoader) Load() ([]byte, error) { - return l.data, l.err -} diff --git a/fileloader.go b/fileloader.go index 91ce86b0c..eb73461e2 100644 --- a/fileloader.go +++ b/fileloader.go @@ -17,19 +17,32 @@ limitations under the License. package loader import ( + "path/filepath" + "k8s.io/kubectl/pkg/kinflate/util/fs" ) +// Implements internal interface schemeLoader. type fileLoader struct { fs fs.FileSystem - - path string } -func NewFileLoader(fs fs.FileSystem, path string) (Loader, error) { - return &fileLoader{fs: fs, path: path}, nil +func newFileLoader(fs fs.FileSystem) (schemeLoader, error) { + return &fileLoader{fs: fs}, nil } -func (l *fileLoader) Load() ([]byte, error) { - return l.fs.ReadFile(l.path) +// Join the root path with the location path. +func (l *fileLoader) fullLocation(root string, location string) string { + fullLocation := location + if !filepath.IsAbs(location) { + fullLocation = filepath.Join(root, location) + } + return fullLocation +} + +// Load returns the bytes from reading a file at fullFilePath. +// Implements the Loader interface. +func (l *fileLoader) load(fullFilePath string) ([]byte, error) { + // TODO: Check that fullFilePath is an absolute file path. + return l.fs.ReadFile(fullFilePath) } diff --git a/fileloader_test.go b/fileloader_test.go index 2461e3e76..a9bb4b2a9 100644 --- a/fileloader_test.go +++ b/fileloader_test.go @@ -28,11 +28,11 @@ func TestFileLoaderHappyPath(t *testing.T) { location := "foo" content := []byte("bar") fakefs.WriteFile(location, content) - l, err := NewFileLoader(fakefs, location) + l, err := newFileLoader(fakefs) if err != nil { t.Fatalf("unexpected error: %v", err) } - b, err := l.Load() + b, err := l.load(location) if err != nil { t.Fatalf("unexpected error in Load: %v", err) } @@ -43,11 +43,11 @@ func TestFileLoaderHappyPath(t *testing.T) { func TestFileLoaderFileNotFound(t *testing.T) { fakefs := fs.MakeFakeFS() - l, err := NewFileLoader(fakefs, "path/does/not/exist") + l, err := newFileLoader(fakefs) if err != nil { t.Fatalf("unexpected error: %v", err) } - _, err = l.Load() + _, err = l.load("/path/does/not/exist") if err == nil { t.Fatal("expected error in Load, but no error returned") } diff --git a/loader.go b/loader.go index d6f2fd3cf..dd5e1b671 100644 --- a/loader.go +++ b/loader.go @@ -16,6 +16,87 @@ limitations under the License. package loader +import ( + "fmt" + + "k8s.io/kubectl/pkg/kinflate/util/fs" +) + +// Loader abstracts how bytes are read for manifest, resource, patch, or other +// files. Each Loader is tightly coupled with the location of a manifest file. +// So each file without an absolute path is located relative to the +// manifest file it was read from. Each Load() call is relative to this manifest +// location (referenced as root). The Loader hides how to read bytes from different +// "schemes" (e.g. file, url, or git). type Loader interface { - Load() ([]byte, error) + // Clones new Loader for a new app/package with its own manifest from the current + // Loader. The "newRoot" can be relative or absolute. If it's relative, the new + // Loader root is calculated from the current Loader root. Can be a file or directory. + // If it's a file, then the base directory is used for root calculation. + New(newRoot string) (Loader, error) + // Returns the bytes at location or an error. If it's a relative path, then + // the location is expanded using the Loader root. + // Example: returns YAML bytes at location "/home/seans/project/service.yaml". + Load(location string) ([]byte, error) +} + +// Private implmentation of Loader interface. +type loaderImpl struct { + root string + fs fs.FileSystem + // http client for URL loading + // git client for Git loading +} + +// RootLoader initializes the first Loader, with the initial root location. +func RootLoader(root string, fs fs.FileSystem) Loader { + // TODO: Validate the root + return &loaderImpl{root: root, fs: fs} +} + +// New clones a new Loader with a new absolute root path. +func (l *loaderImpl) New(newRoot string) (Loader, error) { + loader, err := l.getSchemeLoader(newRoot) + if err != nil { + return nil, err + } + return &loaderImpl{root: loader.fullLocation(l.root, newRoot), fs: l.fs}, nil +} + +// Load returns the bytes at the specified location. +// Implemented by getting a scheme-specific structure to +// load the bytes. +func (l *loaderImpl) Load(location string) ([]byte, error) { + loader, err := l.getSchemeLoader(location) + if err != nil { + return nil, err + } + fullLocation := loader.fullLocation(l.root, location) + return loader.load(fullLocation) +} + +// Helper function to parse scheme from location parameter and return +func (l *loaderImpl) getSchemeLoader(location string) (schemeLoader, error) { + // FIXME: First check the scheme of root location. + switch { + case isFilePath(location): + return newFileLoader(l.fs) + default: + return nil, fmt.Errorf("unknown scheme: %v", location) + } +} + +// Parses the location to determine if it is a file path. +func isFilePath(location string) bool { + return true +} + +///////////////////////////////////////////////// +// Internal interface for specific type of loader +// Examples: fileLoader, HttpLoader, or GitLoader +type schemeLoader interface { + // Combines the root and path into a full location string. + fullLocation(root string, path string) string + // Must be a full, non-relative location string. + load(location string) ([]byte, error) } diff --git a/factory.go b/loader_test.go similarity index 56% rename from factory.go rename to loader_test.go index 86fc97527..35dd75391 100644 --- a/factory.go +++ b/loader_test.go @@ -17,20 +17,23 @@ limitations under the License. package loader import ( - "fmt" + "reflect" + "testing" "k8s.io/kubectl/pkg/kinflate/util/fs" ) -func GetLoader(location string) (Loader, error) { - switch { - case isFilePath(location): - return NewFileLoader(fs.MakeRealFS(), location) - default: - return nil, fmt.Errorf("unknown scheme: %v", location) +func TestLoader_Load(t *testing.T) { + fakefs := fs.MakeFakeFS() + location := "/home/seans/project/Kube-manifest.yaml" + content := []byte("This is a kinflate manifest") + fakefs.WriteFile(location, content) + loader := RootLoader(location, fakefs) + manifestBytes, err := loader.Load(location) + if err != nil { + t.Fatalf("Unexpected error in Load(): %v", err) + } + if !reflect.DeepEqual(content, manifestBytes) { + t.Fatalf("expected %s, but got %s", content, manifestBytes) } } - -func isFilePath(location string) bool { - return true -} From 2803503e3a2b83874ef4a8eeae1c7411ff96e095 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Fri, 23 Feb 2018 16:48:28 -0800 Subject: [PATCH 03/12] Refactor Loader interface --- fileloader.go | 59 ++++++++++++++++--- fileloader_test.go | 54 ------------------ loader.go | 139 ++++++++++++++++++++++----------------------- loader_test.go | 106 +++++++++++++++++++++++++++++++--- 4 files changed, 216 insertions(+), 142 deletions(-) delete mode 100644 fileloader_test.go diff --git a/fileloader.go b/fileloader.go index eb73461e2..46eb58885 100644 --- a/fileloader.go +++ b/fileloader.go @@ -17,32 +17,75 @@ limitations under the License. package loader import ( + "fmt" + "os" "path/filepath" "k8s.io/kubectl/pkg/kinflate/util/fs" ) -// Implements internal interface schemeLoader. +const currentDir = "." + +// Internal implementation of SchemeLoader interface. type fileLoader struct { fs fs.FileSystem } -func newFileLoader(fs fs.FileSystem) (schemeLoader, error) { - return &fileLoader{fs: fs}, nil +// NewFileLoader returns a SchemeLoader to handle a file system. +func NewFileLoader(fs fs.FileSystem) SchemeLoader { + return &fileLoader{fs: fs} } -// Join the root path with the location path. -func (l *fileLoader) fullLocation(root string, location string) string { +// Is the location calculated with the root and location params a full file path. +func (l *fileLoader) IsScheme(root string, location string) bool { + fullFilePath, err := l.FullLocation(root, location) + if err != nil { + return false + } + return filepath.IsAbs(fullFilePath) +} + +// Returns the directory of the calculated full file path. +// Example: "/home/seans/project", "subdir/file.txt" -> "/home/seans/project/subdir". +func (l *fileLoader) Root(root string, location string) (string, error) { + fullFilePath, err := l.FullLocation(root, location) + if err != nil { + return "", err + } + return filepath.Dir(fullFilePath), nil +} + +// If location is a full file path, then ignore root. If location is relative, then +// join the root path with the location path. Either root or location can be empty, +// but not both. +// Example: "/home/seans/project", "subdir/file.txt" -> "/home/seans/project/subdir/file.txt". +func (l *fileLoader) FullLocation(root string, location string) (string, error) { + // First, validate the parameters + if len(root) == 0 && len(location) == 0 { + return "", fmt.Errorf("Unable to calculate full location: root and location empty") + } + // Special case current directory, expanding to full file path. + if location == currentDir { + currentDir, err := os.Getwd() + if err != nil { + return "", err + } + location = currentDir + } + // Assume the location is an full file path. If not, then join root with location. fullLocation := location if !filepath.IsAbs(location) { fullLocation = filepath.Join(root, location) } - return fullLocation + return fullLocation, nil } // Load returns the bytes from reading a file at fullFilePath. // Implements the Loader interface. -func (l *fileLoader) load(fullFilePath string) ([]byte, error) { - // TODO: Check that fullFilePath is an absolute file path. +func (l *fileLoader) Load(fullFilePath string) ([]byte, error) { + // Validate path to load from is a full file path. + if !filepath.IsAbs(fullFilePath) { + return nil, fmt.Errorf("Attempting to load file without full file path: %s\n", fullFilePath) + } return l.fs.ReadFile(fullFilePath) } diff --git a/fileloader_test.go b/fileloader_test.go deleted file mode 100644 index a9bb4b2a9..000000000 --- a/fileloader_test.go +++ /dev/null @@ -1,54 +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 loader - -import ( - "reflect" - "testing" - - "k8s.io/kubectl/pkg/kinflate/util/fs" -) - -func TestFileLoaderHappyPath(t *testing.T) { - fakefs := fs.MakeFakeFS() - location := "foo" - content := []byte("bar") - fakefs.WriteFile(location, content) - l, err := newFileLoader(fakefs) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - b, err := l.load(location) - if err != nil { - t.Fatalf("unexpected error in Load: %v", err) - } - if !reflect.DeepEqual(b, content) { - t.Fatalf("expected %s, but got %s", content, b) - } -} - -func TestFileLoaderFileNotFound(t *testing.T) { - fakefs := fs.MakeFakeFS() - l, err := newFileLoader(fakefs) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = l.load("/path/does/not/exist") - if err == nil { - t.Fatal("expected error in Load, but no error returned") - } -} diff --git a/loader.go b/loader.go index dd5e1b671..6952ec37b 100644 --- a/loader.go +++ b/loader.go @@ -16,87 +16,82 @@ limitations under the License. package loader -import ( - "fmt" +import "fmt" - "k8s.io/kubectl/pkg/kinflate/util/fs" -) - -// Loader abstracts how bytes are read for manifest, resource, patch, or other -// files. Each Loader is tightly coupled with the location of a manifest file. -// So each file without an absolute path is located relative to the -// manifest file it was read from. Each Load() call is relative to this manifest -// location (referenced as root). The Loader hides how to read bytes from different -// "schemes" (e.g. file, url, or git). +// Loader interface exposes methods to read bytes in a scheme-agnostic manner. +// The Loader encapsulating a root location to calculate where to read from. type Loader interface { - // Clones new Loader for a new app/package with its own manifest from the current - // Loader. The "newRoot" can be relative or absolute. If it's relative, the new - // Loader root is calculated from the current Loader root. Can be a file or directory. - // If it's a file, then the base directory is used for root calculation. + // Root returns the scheme-specific string representing the root location for this Loader. + Root() string + // New returns Loader located at newRoot. New(newRoot string) (Loader, error) - // Returns the bytes at location or an error. If it's a relative path, then - // the location is expanded using the Loader root. - // Example: returns YAML bytes at location "/home/seans/project/service.yaml". + // Load returns the bytes read from the location or an error. Load(location string) ([]byte, error) } // Private implmentation of Loader interface. type loaderImpl struct { - root string - fs fs.FileSystem - // http client for URL loading - // git client for Git loading + root string + schemes []SchemeLoader } -// RootLoader initializes the first Loader, with the initial root location. -func RootLoader(root string, fs fs.FileSystem) Loader { - // TODO: Validate the root - return &loaderImpl{root: root, fs: fs} -} - -// New clones a new Loader with a new absolute root path. -func (l *loaderImpl) New(newRoot string) (Loader, error) { - loader, err := l.getSchemeLoader(newRoot) - if err != nil { - return nil, err - } - return &loaderImpl{root: loader.fullLocation(l.root, newRoot), fs: l.fs}, nil -} - -// Load returns the bytes at the specified location. -// Implemented by getting a scheme-specific structure to -// load the bytes. -func (l *loaderImpl) Load(location string) ([]byte, error) { - loader, err := l.getSchemeLoader(location) - if err != nil { - return nil, err - } - fullLocation := loader.fullLocation(l.root, location) - return loader.load(fullLocation) -} - -// Helper function to parse scheme from location parameter and return -func (l *loaderImpl) getSchemeLoader(location string) (schemeLoader, error) { - // FIXME: First check the scheme of root location. - switch { - case isFilePath(location): - return newFileLoader(l.fs) - default: - return nil, fmt.Errorf("unknown scheme: %v", location) - } -} - -// Parses the location to determine if it is a file path. -func isFilePath(location string) bool { - return true -} - -///////////////////////////////////////////////// -// Internal interface for specific type of loader -// Examples: fileLoader, HttpLoader, or GitLoader -type schemeLoader interface { +// Interface for different types of loaders (e.g. fileLoader, httpLoader, etc.) +type SchemeLoader interface { + // Does this location correspond to this scheme. + IsScheme(root string, location string) bool + // Calulcate a new root. + Root(root string, location string) (string, error) // Combines the root and path into a full location string. - fullLocation(root string, path string) string - // Must be a full, non-relative location string. - load(location string) ([]byte, error) + FullLocation(root string, path string) (string, error) + // Load bytes at scheme-specific location or an error. + Load(location string) ([]byte, error) +} + +const emptyRoot = "" + +// Init initializes the first loader with the supported schemes. +// Example schemes: fileLoader, httpLoader, gitLoader. +func Init(schemes []SchemeLoader) Loader { + return &loaderImpl{root: emptyRoot, schemes: schemes} +} + +// Root returns the scheme-specific root location for this Loader. +func (l *loaderImpl) Root() string { + return l.root +} + +// Returns a new Loader rooted at newRoot. +func (l *loaderImpl) New(newRoot string) (Loader, error) { + scheme, err := l.getSchemeLoader(newRoot) + if err != nil { + return nil, err + } + root, err := scheme.Root(l.root, newRoot) + if err != nil { + return nil, err + } + return &loaderImpl{root: root, schemes: l.schemes}, nil +} + +// Load returns all the bytes read from scheme-specific location or an error. +func (l *loaderImpl) Load(location string) ([]byte, error) { + scheme, err := l.getSchemeLoader(location) + if err != nil { + return nil, err + } + fullLocation, err := scheme.FullLocation(l.root, location) + if err != nil { + return nil, err + } + return scheme.Load(fullLocation) +} + +// Helper function to parse scheme from location parameter. +func (l *loaderImpl) getSchemeLoader(location string) (SchemeLoader, error) { + for _, scheme := range l.schemes { + if scheme.IsScheme(l.root, location) { + return scheme, nil + } + } + return nil, fmt.Errorf("Unknown Scheme: %s, %s\n", l.root, location) } diff --git a/loader_test.go b/loader_test.go index 35dd75391..af8eec9ec 100644 --- a/loader_test.go +++ b/loader_test.go @@ -17,23 +17,113 @@ limitations under the License. package loader import ( + "path/filepath" "reflect" "testing" "k8s.io/kubectl/pkg/kinflate/util/fs" ) +var rootDir = "/home/seans/project" +var rootFile = "file.yaml" +var rootFilePath = filepath.Join(rootDir, rootFile) +var rootFileContent = []byte("This is a yaml file") + +var subDirectory = "subdir" +var subDirectoryPath = filepath.Join(subDirectory, rootFile) +var subDirectoryContent = []byte("Subdirectory file content") + +var anotherRootDir = "/home/seans/project2" +var anotherFilePath = filepath.Join(anotherRootDir, rootFile) +var anotherFileContent = []byte("This is another yaml file") + +func TestLoader_Root(t *testing.T) { + + rootLoader := initializeRootLoader() + _, err := rootLoader.New("") + if err == nil { + t.Fatalf("Expected error for empty root location not returned") + } + _, err = rootLoader.New("https://google.com/project") + if err == nil { + t.Fatalf("Expected error for unknown scheme not returned") + } + + loader, err := rootLoader.New(rootFilePath) + if err != nil { + t.Fatalf("Unexpected in New(): %v\n", err) + } + if rootDir != loader.Root() { + t.Fatalf("Incorrect Loader Root: %s\n", loader.Root()) + } + + subLoader, err := loader.New(subDirectoryPath) + if err != nil { + t.Fatalf("Unexpected in New(): %v\n", err) + } + if filepath.Join(rootDir, subDirectory) != subLoader.Root() { + t.Fatalf("Incorrect Loader Root: %s\n", subLoader.Root()) + } + + anotherLoader, err := loader.New(anotherFilePath) + if err != nil { + t.Fatalf("Unexpected in New(): %v\n", err) + } + if anotherRootDir != anotherLoader.Root() { + t.Fatalf("Incorrect Loader Root: %s\n", anotherLoader.Root()) + } + + currentDirLoader, err := loader.New(".") + if err != nil { + t.Fatalf("Unexpected in New(): %v\n", err) + } + if !filepath.IsAbs(currentDirLoader.Root()) { + t.Fatalf("Incorrect Loader Root: %s\n", currentDirLoader.Root()) + } +} + func TestLoader_Load(t *testing.T) { - fakefs := fs.MakeFakeFS() - location := "/home/seans/project/Kube-manifest.yaml" - content := []byte("This is a kinflate manifest") - fakefs.WriteFile(location, content) - loader := RootLoader(location, fakefs) - manifestBytes, err := loader.Load(location) + rootLoader := initializeRootLoader() + loader, err := rootLoader.New(rootFilePath) + if err != nil { + t.Fatalf("Unexpected in New(): %v\n", err) + } + fileBytes, err := loader.Load(rootFilePath) if err != nil { t.Fatalf("Unexpected error in Load(): %v", err) } - if !reflect.DeepEqual(content, manifestBytes) { - t.Fatalf("expected %s, but got %s", content, manifestBytes) + if !reflect.DeepEqual(rootFileContent, fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", rootFileContent, fileBytes) } + fileBytes, err = loader.Load(subDirectoryPath) + if err != nil { + t.Fatalf("Unexpected error in Load(): %v", err) + } + if !reflect.DeepEqual(subDirectoryContent, fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", subDirectoryContent, fileBytes) + } + fileBytes, err = loader.Load(anotherFilePath) + if err != nil { + t.Fatalf("Unexpected error in Load(): %v", err) + } + if !reflect.DeepEqual(anotherFileContent, fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", anotherFileContent, fileBytes) + } + +} + +func initializeRootLoader() Loader { + fs := initializeFakeFilesystem() + var schemes []SchemeLoader + schemes = append(schemes, NewFileLoader(fs)) + rootLoader := Init(schemes) + return rootLoader +} + +func initializeFakeFilesystem() fs.FileSystem { + fakefs := fs.MakeFakeFS() + fakefs.WriteFile(rootFilePath, rootFileContent) + fakefs.WriteFile(filepath.Join(rootDir, subDirectoryPath), subDirectoryContent) + fakefs.WriteFile(anotherFilePath, anotherFileContent) + return fakefs } From 2848fcf962313cf5f6267aae1b727b7a9c4f105d Mon Sep 17 00:00:00 2001 From: Sunil Arora Date: Fri, 23 Feb 2018 15:54:16 -0800 Subject: [PATCH 04/12] kinflate: configmap resource implementation using loader --- fake_loader.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 fake_loader.go diff --git a/fake_loader.go b/fake_loader.go new file mode 100644 index 000000000..4124b472b --- /dev/null +++ b/fake_loader.go @@ -0,0 +1,32 @@ +/* +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 loader + +// FakeLoader implements Loader interface. +type FakeLoader struct { + Content string +} + +func (f FakeLoader) New(root string) (Loader, error) { + return f, nil +} + +func (f FakeLoader) Load(location string) ([]byte, error) { + return []byte(f.Content), nil +} + +var _ Loader = FakeLoader{} From dcc56032ac21aa7f163b6445c5d0f38421fa1fef Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 26 Feb 2018 13:28:03 -0800 Subject: [PATCH 05/12] Fix for FakeLoader to add new Root() method in Loader interface --- fake_loader.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fake_loader.go b/fake_loader.go index 4124b472b..f4725ab58 100644 --- a/fake_loader.go +++ b/fake_loader.go @@ -21,6 +21,10 @@ type FakeLoader struct { Content string } +func (f FakeLoader) Root() string { + return "/fake/root" +} + func (f FakeLoader) New(root string) (Loader, error) { return f, nil } From 560e29408ea13db9a5c96db48e04a0e5af9ab834 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 26 Feb 2018 15:38:48 -0800 Subject: [PATCH 06/12] Move fake loader into its own package --- fake_loader.go => loadertest/fake_loader.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename fake_loader.go => loadertest/fake_loader.go (84%) diff --git a/fake_loader.go b/loadertest/fake_loader.go similarity index 84% rename from fake_loader.go rename to loadertest/fake_loader.go index f4725ab58..da03b6bd1 100644 --- a/fake_loader.go +++ b/loadertest/fake_loader.go @@ -14,7 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package loader +package loadertest + +import "k8s.io/kubectl/pkg/loader" // FakeLoader implements Loader interface. type FakeLoader struct { @@ -25,7 +27,7 @@ func (f FakeLoader) Root() string { return "/fake/root" } -func (f FakeLoader) New(root string) (Loader, error) { +func (f FakeLoader) New(root string) (loader.Loader, error) { return f, nil } @@ -33,4 +35,4 @@ func (f FakeLoader) Load(location string) ([]byte, error) { return []byte(f.Content), nil } -var _ Loader = FakeLoader{} +var _ loader.Loader = FakeLoader{} From 59031c1d08f246a3027df9cbf1042da7bba0303c Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 26 Feb 2018 16:32:14 -0800 Subject: [PATCH 07/12] Updated loader test to remove variables and logic; makes test easier to validated and reason about --- loader_test.go | 86 +++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/loader_test.go b/loader_test.go index af8eec9ec..50b97cae7 100644 --- a/loader_test.go +++ b/loader_test.go @@ -24,22 +24,22 @@ import ( "k8s.io/kubectl/pkg/kinflate/util/fs" ) -var rootDir = "/home/seans/project" -var rootFile = "file.yaml" -var rootFilePath = filepath.Join(rootDir, rootFile) -var rootFileContent = []byte("This is a yaml file") - -var subDirectory = "subdir" -var subDirectoryPath = filepath.Join(subDirectory, rootFile) -var subDirectoryContent = []byte("Subdirectory file content") - -var anotherRootDir = "/home/seans/project2" -var anotherFilePath = filepath.Join(anotherRootDir, rootFile) -var anotherFileContent = []byte("This is another yaml file") +func initializeRootLoader(fakefs fs.FileSystem) Loader { + var schemes []SchemeLoader + schemes = append(schemes, NewFileLoader(fakefs)) + rootLoader := Init(schemes) + return rootLoader +} func TestLoader_Root(t *testing.T) { - rootLoader := initializeRootLoader() + // Initialize the fake file system and the root loader. + fakefs := fs.MakeFakeFS() + fakefs.WriteFile("/home/seans/project/file.yaml", []byte("Unused")) + fakefs.WriteFile("/home/seans/project/subdir/file.yaml", []byte("Unused")) + fakefs.WriteFile("/home/seans/project2/file.yaml", []byte("Unused")) + rootLoader := initializeRootLoader(fakefs) + _, err := rootLoader.New("") if err == nil { t.Fatalf("Expected error for empty root location not returned") @@ -49,30 +49,31 @@ func TestLoader_Root(t *testing.T) { t.Fatalf("Expected error for unknown scheme not returned") } - loader, err := rootLoader.New(rootFilePath) + loader, err := rootLoader.New("/home/seans/project/file.yaml") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } - if rootDir != loader.Root() { + if "/home/seans/project" != loader.Root() { t.Fatalf("Incorrect Loader Root: %s\n", loader.Root()) } - subLoader, err := loader.New(subDirectoryPath) + subLoader, err := loader.New("subdir/file.yaml") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } - if filepath.Join(rootDir, subDirectory) != subLoader.Root() { + if "/home/seans/project/subdir" != subLoader.Root() { t.Fatalf("Incorrect Loader Root: %s\n", subLoader.Root()) } - anotherLoader, err := loader.New(anotherFilePath) + anotherLoader, err := loader.New("/home/seans/project2/file.yaml") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } - if anotherRootDir != anotherLoader.Root() { + if "/home/seans/project2" != anotherLoader.Root() { t.Fatalf("Incorrect Loader Root: %s\n", anotherLoader.Root()) } + // Current directory should be expanded to a full absolute file path. currentDirLoader, err := loader.New(".") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) @@ -83,47 +84,40 @@ func TestLoader_Root(t *testing.T) { } func TestLoader_Load(t *testing.T) { - rootLoader := initializeRootLoader() - loader, err := rootLoader.New(rootFilePath) + + // Initialize the fake file system and the root loader. + fakefs := fs.MakeFakeFS() + fakefs.WriteFile("/home/seans/project/file.yaml", []byte("This is a yaml file")) + fakefs.WriteFile("/home/seans/project/subdir/file.yaml", []byte("Subdirectory file content")) + fakefs.WriteFile("/home/seans/project2/file.yaml", []byte("This is another yaml file")) + rootLoader := initializeRootLoader(fakefs) + + loader, err := rootLoader.New("/home/seans/project/file.yaml") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } - fileBytes, err := loader.Load(rootFilePath) + fileBytes, err := loader.Load("file.yaml") // Load relative to root location if err != nil { t.Fatalf("Unexpected error in Load(): %v", err) } - if !reflect.DeepEqual(rootFileContent, fileBytes) { - t.Fatalf("Load failed. Expected %s, but got %s", rootFileContent, fileBytes) + if !reflect.DeepEqual([]byte("This is a yaml file"), fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", "This is a yaml file", fileBytes) } - fileBytes, err = loader.Load(subDirectoryPath) + + fileBytes, err = loader.Load("subdir/file.yaml") if err != nil { t.Fatalf("Unexpected error in Load(): %v", err) } - if !reflect.DeepEqual(subDirectoryContent, fileBytes) { - t.Fatalf("Load failed. Expected %s, but got %s", subDirectoryContent, fileBytes) + if !reflect.DeepEqual([]byte("Subdirectory file content"), fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", "Subdirectory file content", fileBytes) } - fileBytes, err = loader.Load(anotherFilePath) + + fileBytes, err = loader.Load("/home/seans/project2/file.yaml") if err != nil { t.Fatalf("Unexpected error in Load(): %v", err) } - if !reflect.DeepEqual(anotherFileContent, fileBytes) { - t.Fatalf("Load failed. Expected %s, but got %s", anotherFileContent, fileBytes) + if !reflect.DeepEqual([]byte("This is another yaml file"), fileBytes) { + t.Fatalf("Load failed. Expected %s, but got %s", "This is another yaml file", fileBytes) } } - -func initializeRootLoader() Loader { - fs := initializeFakeFilesystem() - var schemes []SchemeLoader - schemes = append(schemes, NewFileLoader(fs)) - rootLoader := Init(schemes) - return rootLoader -} - -func initializeFakeFilesystem() fs.FileSystem { - fakefs := fs.MakeFakeFS() - fakefs.WriteFile(rootFilePath, rootFileContent) - fakefs.WriteFile(filepath.Join(rootDir, subDirectoryPath), subDirectoryContent) - fakefs.WriteFile(anotherFilePath, anotherFileContent) - return fakefs -} From 2a5e1b5acb7e1b2a0185c0fee4f973e72915bcd1 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Tue, 27 Feb 2018 12:43:01 -0800 Subject: [PATCH 08/12] Update FakeLoader for simpler interface; FakeLoader uses real Loader --- loadertest/fake_loader.go | 45 +++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/loadertest/fake_loader.go b/loadertest/fake_loader.go index da03b6bd1..1dd0b6369 100644 --- a/loadertest/fake_loader.go +++ b/loadertest/fake_loader.go @@ -16,23 +16,50 @@ limitations under the License. package loadertest -import "k8s.io/kubectl/pkg/loader" +import ( + "os" -// FakeLoader implements Loader interface. + "k8s.io/kubectl/pkg/kinflate/util/fs" + "k8s.io/kubectl/pkg/loader" +) + +// FakeLoader encapsulates the delegate Loader and the fake file system. type FakeLoader struct { - Content string + fs fs.FileSystem + delegate loader.Loader +} + +// NewFakeLoader returns a Loader that delegates calls, and encapsulates +// a fake file system that the Loader reads from . "initialFilePath" parameter +// must be an absolute path. +func NewFakeLoader(initialFilePath string) FakeLoader { + // Create fake filesystem and inject it into initial Loader. + fakefs := fs.MakeFakeFS() + var schemes []loader.SchemeLoader + schemes = append(schemes, loader.NewFileLoader(fakefs)) + rootLoader := loader.Init(schemes) + loader, _ := rootLoader.New(initialFilePath) + return FakeLoader{fs: fakefs, delegate: loader} +} + +// Adds a fake file to the file system. +func (f FakeLoader) AddFile(fullFilePath string, content []byte) error { + return f.fs.WriteFile(fullFilePath, content) +} + +// Adds a fake directory to the file system. +func (f FakeLoader) AddDirectory(fullDirPath string, mode os.FileMode) error { + return f.fs.Mkdir(fullDirPath, mode) } func (f FakeLoader) Root() string { - return "/fake/root" + return f.delegate.Root() } -func (f FakeLoader) New(root string) (loader.Loader, error) { - return f, nil +func (f FakeLoader) New(newRoot string) (loader.Loader, error) { + return f.delegate.New(newRoot) } func (f FakeLoader) Load(location string) ([]byte, error) { - return []byte(f.Content), nil + return f.delegate.Load(location) } - -var _ loader.Loader = FakeLoader{} From 62655260a6b4e1cec6822b2b7f8251cf6b85eb16 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Tue, 27 Feb 2018 15:30:32 -0800 Subject: [PATCH 09/12] Allow fake loader be initialized with directory --- loadertest/fake_loader.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/loadertest/fake_loader.go b/loadertest/fake_loader.go index 1dd0b6369..0b1ca2ed5 100644 --- a/loadertest/fake_loader.go +++ b/loadertest/fake_loader.go @@ -18,6 +18,7 @@ package loadertest import ( "os" + "strings" "k8s.io/kubectl/pkg/kinflate/util/fs" "k8s.io/kubectl/pkg/loader" @@ -30,11 +31,15 @@ type FakeLoader struct { } // NewFakeLoader returns a Loader that delegates calls, and encapsulates -// a fake file system that the Loader reads from . "initialFilePath" parameter -// must be an absolute path. +// a fake file system that the Loader reads from. "initialFilePath" parameter +// must be an absolute path, and it can be a directory if it has a +// trailing slash: "/home/seans/project/" (dir) -- "/home/seans/project" (file) func NewFakeLoader(initialFilePath string) FakeLoader { // Create fake filesystem and inject it into initial Loader. fakefs := fs.MakeFakeFS() + if strings.HasSuffix(initialFilePath, "/") { + fakefs.Mkdir(initialFilePath, 0x777) + } var schemes []loader.SchemeLoader schemes = append(schemes, loader.NewFileLoader(fakefs)) rootLoader := loader.Init(schemes) From f640a250d99f89fbc605eb4efcf86d1145f89771 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Wed, 28 Feb 2018 11:41:18 -0800 Subject: [PATCH 10/12] Simplified Loader.New() to always take a directory (not a file) --- fileloader.go | 16 +++------------- loader.go | 12 ++++++++---- loader_test.go | 12 +++++++----- loadertest/fake_loader.go | 13 ++++--------- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/fileloader.go b/fileloader.go index 46eb58885..060d85f62 100644 --- a/fileloader.go +++ b/fileloader.go @@ -45,20 +45,10 @@ func (l *fileLoader) IsScheme(root string, location string) bool { return filepath.IsAbs(fullFilePath) } -// Returns the directory of the calculated full file path. -// Example: "/home/seans/project", "subdir/file.txt" -> "/home/seans/project/subdir". -func (l *fileLoader) Root(root string, location string) (string, error) { - fullFilePath, err := l.FullLocation(root, location) - if err != nil { - return "", err - } - return filepath.Dir(fullFilePath), nil -} - // If location is a full file path, then ignore root. If location is relative, then // join the root path with the location path. Either root or location can be empty, -// but not both. -// Example: "/home/seans/project", "subdir/file.txt" -> "/home/seans/project/subdir/file.txt". +// but not both. Special case for ".": Expands to current working directory. +// Example: "/home/seans/project", "subdir/bar" -> "/home/seans/project/subdir/bar". func (l *fileLoader) FullLocation(root string, location string) (string, error) { // First, validate the parameters if len(root) == 0 && len(location) == 0 { @@ -72,7 +62,7 @@ func (l *fileLoader) FullLocation(root string, location string) (string, error) } location = currentDir } - // Assume the location is an full file path. If not, then join root with location. + // Assume the location is a full file path. If not, then join root with location. fullLocation := location if !filepath.IsAbs(location) { fullLocation = filepath.Join(root, location) diff --git a/loader.go b/loader.go index 6952ec37b..5b0c59d59 100644 --- a/loader.go +++ b/loader.go @@ -39,8 +39,6 @@ type loaderImpl struct { type SchemeLoader interface { // Does this location correspond to this scheme. IsScheme(root string, location string) bool - // Calulcate a new root. - Root(root string, location string) (string, error) // Combines the root and path into a full location string. FullLocation(root string, path string) (string, error) // Load bytes at scheme-specific location or an error. @@ -60,13 +58,17 @@ func (l *loaderImpl) Root() string { return l.root } -// Returns a new Loader rooted at newRoot. +// Returns a new Loader rooted at newRoot. "newRoot" MUST be +// a directory (not a file). The directory can have a trailing +// slash or not. +// Example: "/home/seans/project" or "/home/seans/project/" +// NOT "/home/seans/project/file.yaml". func (l *loaderImpl) New(newRoot string) (Loader, error) { scheme, err := l.getSchemeLoader(newRoot) if err != nil { return nil, err } - root, err := scheme.Root(l.root, newRoot) + root, err := scheme.FullLocation(l.root, newRoot) if err != nil { return nil, err } @@ -74,6 +76,8 @@ func (l *loaderImpl) New(newRoot string) (Loader, error) { } // Load returns all the bytes read from scheme-specific location or an error. +// "location" can be an absolute path, or if relative, full location is +// calculated from the Root(). func (l *loaderImpl) Load(location string) ([]byte, error) { scheme, err := l.getSchemeLoader(location) if err != nil { diff --git a/loader_test.go b/loader_test.go index 50b97cae7..7213de836 100644 --- a/loader_test.go +++ b/loader_test.go @@ -49,15 +49,16 @@ func TestLoader_Root(t *testing.T) { t.Fatalf("Expected error for unknown scheme not returned") } - loader, err := rootLoader.New("/home/seans/project/file.yaml") + // Test with trailing slash in directory. + loader, err := rootLoader.New("/home/seans/project/") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } - if "/home/seans/project" != loader.Root() { + if "/home/seans/project/" != loader.Root() { t.Fatalf("Incorrect Loader Root: %s\n", loader.Root()) } - subLoader, err := loader.New("subdir/file.yaml") + subLoader, err := loader.New("subdir") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } @@ -65,7 +66,8 @@ func TestLoader_Root(t *testing.T) { t.Fatalf("Incorrect Loader Root: %s\n", subLoader.Root()) } - anotherLoader, err := loader.New("/home/seans/project2/file.yaml") + // Test without trailing slash in directory. + anotherLoader, err := loader.New("/home/seans/project2") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } @@ -92,7 +94,7 @@ func TestLoader_Load(t *testing.T) { fakefs.WriteFile("/home/seans/project2/file.yaml", []byte("This is another yaml file")) rootLoader := initializeRootLoader(fakefs) - loader, err := rootLoader.New("/home/seans/project/file.yaml") + loader, err := rootLoader.New("/home/seans/project") if err != nil { t.Fatalf("Unexpected in New(): %v\n", err) } diff --git a/loadertest/fake_loader.go b/loadertest/fake_loader.go index 0b1ca2ed5..a2e51a8f9 100644 --- a/loadertest/fake_loader.go +++ b/loadertest/fake_loader.go @@ -18,7 +18,6 @@ package loadertest import ( "os" - "strings" "k8s.io/kubectl/pkg/kinflate/util/fs" "k8s.io/kubectl/pkg/loader" @@ -31,19 +30,15 @@ type FakeLoader struct { } // NewFakeLoader returns a Loader that delegates calls, and encapsulates -// a fake file system that the Loader reads from. "initialFilePath" parameter -// must be an absolute path, and it can be a directory if it has a -// trailing slash: "/home/seans/project/" (dir) -- "/home/seans/project" (file) -func NewFakeLoader(initialFilePath string) FakeLoader { +// a fake file system that the Loader reads from. "initialDir" parameter +// must be an full, absolute directory (trailing slash doesn't matter). +func NewFakeLoader(initialDir string) FakeLoader { // Create fake filesystem and inject it into initial Loader. fakefs := fs.MakeFakeFS() - if strings.HasSuffix(initialFilePath, "/") { - fakefs.Mkdir(initialFilePath, 0x777) - } var schemes []loader.SchemeLoader schemes = append(schemes, loader.NewFileLoader(fakefs)) rootLoader := loader.Init(schemes) - loader, _ := rootLoader.New(initialFilePath) + loader, _ := rootLoader.New(initialDir) return FakeLoader{fs: fakefs, delegate: loader} } From 60485ef8245a894a98ef5e155b2fc831c8e1c774 Mon Sep 17 00:00:00 2001 From: Jingfang Liu Date: Tue, 10 Apr 2018 14:32:02 -0700 Subject: [PATCH 11/12] change kinflate to kustomize --- fileloader.go | 2 +- loader_test.go | 2 +- loadertest/fake_loader.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fileloader.go b/fileloader.go index 060d85f62..d4cd2c68e 100644 --- a/fileloader.go +++ b/fileloader.go @@ -21,7 +21,7 @@ import ( "os" "path/filepath" - "k8s.io/kubectl/pkg/kinflate/util/fs" + "k8s.io/kubectl/pkg/kustomize/util/fs" ) const currentDir = "." diff --git a/loader_test.go b/loader_test.go index 7213de836..db081e8a0 100644 --- a/loader_test.go +++ b/loader_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - "k8s.io/kubectl/pkg/kinflate/util/fs" + "k8s.io/kubectl/pkg/kustomize/util/fs" ) func initializeRootLoader(fakefs fs.FileSystem) Loader { diff --git a/loadertest/fake_loader.go b/loadertest/fake_loader.go index a2e51a8f9..9887510a4 100644 --- a/loadertest/fake_loader.go +++ b/loadertest/fake_loader.go @@ -19,7 +19,7 @@ package loadertest import ( "os" - "k8s.io/kubectl/pkg/kinflate/util/fs" + "k8s.io/kubectl/pkg/kustomize/util/fs" "k8s.io/kubectl/pkg/loader" ) From f857153351df1f01c890e85ed7ac70c991d59414 Mon Sep 17 00:00:00 2001 From: Jeffrey Regan Date: Fri, 11 May 2018 14:01:15 -0700 Subject: [PATCH 12/12] Isolated content of pkg/loader --- fileloader.go => pkg/loader/fileloader.go | 0 loader.go => pkg/loader/loader.go | 0 loader_test.go => pkg/loader/loader_test.go | 0 {loadertest => pkg/loader/loadertest}/fake_loader.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename fileloader.go => pkg/loader/fileloader.go (100%) rename loader.go => pkg/loader/loader.go (100%) rename loader_test.go => pkg/loader/loader_test.go (100%) rename {loadertest => pkg/loader/loadertest}/fake_loader.go (100%) diff --git a/fileloader.go b/pkg/loader/fileloader.go similarity index 100% rename from fileloader.go rename to pkg/loader/fileloader.go diff --git a/loader.go b/pkg/loader/loader.go similarity index 100% rename from loader.go rename to pkg/loader/loader.go diff --git a/loader_test.go b/pkg/loader/loader_test.go similarity index 100% rename from loader_test.go rename to pkg/loader/loader_test.go diff --git a/loadertest/fake_loader.go b/pkg/loader/loadertest/fake_loader.go similarity index 100% rename from loadertest/fake_loader.go rename to pkg/loader/loadertest/fake_loader.go