Skip to content

Commit

Permalink
Add glob support
Browse files Browse the repository at this point in the history
  • Loading branch information
Liujingfang1 committed Jun 27, 2018
1 parent c25ed7f commit 6392e66
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 10 deletions.
19 changes: 19 additions & 0 deletions pkg/fs/fakefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,29 @@ func (fs *FakeFS) ReadFile(name string) ([]byte, error) {
return nil, fmt.Errorf("cannot read file %q", name)
}

// ReadFiles looks through all files in the fake filesystem
// and find the matching files and then read content from all of them
func (fs *FakeFS) ReadFiles(name string) (map[string][]byte, error) {
result := map[string][]byte{}
for p, f := range fs.m {
if fs.pathMatch(p, name) {
result[p] = f.content
}
}
return result, nil
}

// WriteFile always succeeds and does nothing.
func (fs *FakeFS) WriteFile(name string, c []byte) error {
ff := &FakeFile{}
ff.Write(c)
fs.m[name] = ff
return nil
}

func (fs *FakeFS) pathMatch(path, pattern string) bool {
if path == pattern {
return true
}
return false
}
1 change: 1 addition & 0 deletions pkg/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type FileSystem interface {
Open(name string) (File, error)
Stat(name string) (os.FileInfo, error)
ReadFile(name string) ([]byte, error)
ReadFiles(name string) (map[string][]byte, error)
WriteFile(name string, data []byte) error
}

Expand Down
21 changes: 21 additions & 0 deletions pkg/fs/realfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package fs
import (
"io/ioutil"
"os"
"path/filepath"
)

var _ FileSystem = realFS{}
Expand Down Expand Up @@ -46,6 +47,26 @@ func (realFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) }
// ReadFile delegates to ioutil.ReadFile.
func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) }

// ReadFiles use glob to find the matching files and then read content from all of them
func (realFS) ReadFiles(name string) (map[string][]byte, error) {
files, err := filepath.Glob(name)
if err != nil || len(files) == 0 {
return nil, err
}

output := map[string][]byte{}
for _, file := range files {
bytes, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
if bytes != nil {
output[file] = bytes
}
}
return output, nil
}

// WriteFile delegates to ioutil.WriteFile with read/write permissions.
func (realFS) WriteFile(name string, c []byte) error {
return ioutil.WriteFile(name, c, 0666)
Expand Down
58 changes: 58 additions & 0 deletions pkg/fs/realfs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
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"
"path"
"reflect"
"testing"
)

func TestReadFilesRealFS(t *testing.T) {
x := MakeRealFS()
testDir := "kustomize_testing_dir"
err := x.Mkdir(testDir, 0777)
defer os.RemoveAll(testDir)

if err != nil {
t.Fatalf("unexpected error %s", err)
}

err = x.WriteFile(path.Join(testDir, "foo"), []byte(`foo`))
if err != nil {
t.Fatalf("unexpected error %s", err)
}
err = x.WriteFile(path.Join(testDir, "bar"), []byte(`bar`))
if err != nil {
t.Fatalf("unexpected error %s", err)
}

expected := map[string][]byte{
path.Join(testDir, "foo"): []byte(`foo`),
path.Join(testDir, "bar"): []byte(`bar`),
}

content, err := x.ReadFiles("kustomize_testing_dir/*")
if !reflect.DeepEqual(content, expected) {
t.Fatalf("actual: %+v doesn't match expected: %+v", content, expected)

}
if err != nil {
t.Fatalf("unexpected error %s", err)
}
}
5 changes: 5 additions & 0 deletions pkg/internal/loadertest/fakeloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,8 @@ func (f FakeLoader) New(newRoot string) (loader.Loader, error) {
func (f FakeLoader) Load(location string) ([]byte, error) {
return f.delegate.Load(location)
}

// GlobLoad performs load from a given location.
func (f FakeLoader) GlobLoad(location string) (map[string][]byte, error) {
return f.delegate.GlobLoad(location)
}
10 changes: 10 additions & 0 deletions pkg/loader/fileloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,13 @@ func (l *fileLoader) Load(fullFilePath string) ([]byte, error) {
}
return l.fs.ReadFile(fullFilePath)
}

// GlobLoad returns the map from path to bytes from reading a glob path.
// Implements the Loader interface.
func (l *fileLoader) GlobLoad(fullFilePath string) (map[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.ReadFiles(fullFilePath)
}
19 changes: 19 additions & 0 deletions pkg/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type Loader interface {
New(newRoot string) (Loader, error)
// Load returns the bytes read from the location or an error.
Load(location string) ([]byte, error)
// GlobLoad returns the bytes read from a glob path or an error.
GlobLoad(location string) (map[string][]byte, error)
}

// Private implmentation of Loader interface.
Expand All @@ -44,6 +46,8 @@ type SchemeLoader interface {
FullLocation(root string, path string) (string, error)
// Load bytes at scheme-specific location or an error.
Load(location string) ([]byte, error)
// GlobLoad returns the bytes read from a glob path or an error.
GlobLoad(location string) (map[string][]byte, error)
}

const emptyRoot = ""
Expand Down Expand Up @@ -91,6 +95,21 @@ func (l *loaderImpl) Load(location string) ([]byte, error) {
return scheme.Load(fullLocation)
}

// GlobLoad returns a map from path to 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) GlobLoad(location string) (map[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.GlobLoad(fullLocation)
}

// Helper function to parse scheme from location parameter.
func (l *loaderImpl) getSchemeLoader(location string) (SchemeLoader, error) {
for _, scheme := range l.schemes {
Expand Down
24 changes: 14 additions & 10 deletions pkg/resmap/resmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,18 @@ func NewResourceSliceFromPatches(
loader loader.Loader, paths []string) ([]*resource.Resource, error) {
result := []*resource.Resource{}
for _, path := range paths {
content, err := loader.Load(path)
contents, err := loader.GlobLoad(path)
if err != nil {
return nil, err
}
for p, content := range contents {
res, err := newResourceSliceFromBytes(content)
if err != nil {
return nil, internal.ErrorHandler(err, p)
}
result = append(result, res...)

res, err := newResourceSliceFromBytes(content)
if err != nil {
return nil, internal.ErrorHandler(err, path)
}
result = append(result, res...)
}
return result, nil
}
Expand All @@ -131,15 +133,17 @@ func NewResourceSliceFromPatches(
func NewResMapFromFiles(loader loader.Loader, paths []string) (ResMap, error) {
result := []ResMap{}
for _, path := range paths {
content, err := loader.Load(path)
contents, err := loader.GlobLoad(path)
if err != nil {
return nil, errors.Wrap(err, "Load from path "+path+" failed")
}
res, err := newResMapFromBytes(content)
if err != nil {
return nil, internal.ErrorHandler(err, path)
for p, content := range contents {
res, err := newResMapFromBytes(content)
if err != nil {
return nil, internal.ErrorHandler(err, p)
}
result = append(result, res)
}
result = append(result, res)
}
return MergeWithoutOverride(result...)
}
Expand Down

0 comments on commit 6392e66

Please sign in to comment.