diff --git a/pkg/minikube/assets/addons.go b/pkg/minikube/assets/addons.go index 9e594e7ac1d5..968d989095f7 100644 --- a/pkg/minikube/assets/addons.go +++ b/pkg/minikube/assets/addons.go @@ -23,6 +23,7 @@ import ( "strconv" "github.com/pkg/errors" + "github.com/spf13/afero" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/util" @@ -247,10 +248,10 @@ var Addons = map[string]*Addon{ } func AddMinikubeDirAssets(assets *[]CopyableFile) error { - if err := addMinikubeDirToAssets(constants.MakeMiniPath("addons"), constants.AddonsPath, assets); err != nil { + if err := addMinikubeDirToAssets(nil, constants.MakeMiniPath("addons"), constants.AddonsPath, assets); err != nil { return errors.Wrap(err, "adding addons folder to assets") } - if err := addMinikubeDirToAssets(constants.MakeMiniPath("files"), "", assets); err != nil { + if err := addMinikubeDirToAssets(nil, constants.MakeMiniPath("files"), "", assets); err != nil { return errors.Wrap(err, "adding files rootfs to assets") } @@ -260,9 +261,12 @@ func AddMinikubeDirAssets(assets *[]CopyableFile) error { // AddMinikubeDirToAssets adds all the files in the basedir argument to the list // of files to be copied to the vm. If vmpath is left blank, the files will be // transferred to the location according to their relative minikube folder path. -func addMinikubeDirToAssets(basedir, vmpath string, assets *[]CopyableFile) error { - err := filepath.Walk(basedir, func(hostpath string, info os.FileInfo, err error) error { - isDir, err := util.IsDirectory(hostpath) +func addMinikubeDirToAssets(fs afero.Fs, basedir, vmpath string, assets *[]CopyableFile) error { + if fs == nil { + fs = afero.NewOsFs() + } + err := afero.Walk(fs, basedir, func(hostpath string, info os.FileInfo, err error) error { + isDir, err := util.IsDirectory(fs, hostpath) if err != nil { return errors.Wrapf(err, "checking if %s is directory", hostpath) } @@ -283,7 +287,7 @@ func addMinikubeDirToAssets(basedir, vmpath string, assets *[]CopyableFile) erro permString = fmt.Sprintf("0%s", permString) } - f, err := NewFileAsset(hostpath, vmdir, filepath.Base(hostpath), permString) + f, err := NewFileAsset(fs, hostpath, vmdir, filepath.Base(hostpath), permString) if err != nil { return errors.Wrapf(err, "creating file asset for %s", hostpath) } diff --git a/pkg/minikube/assets/addons_test.go b/pkg/minikube/assets/addons_test.go new file mode 100644 index 000000000000..d97e0d73a038 --- /dev/null +++ b/pkg/minikube/assets/addons_test.go @@ -0,0 +1,132 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 assets + +import ( + "path/filepath" + "testing" + + "github.com/spf13/afero" + "k8s.io/minikube/pkg/minikube/constants" +) + +func TestAddMinikubeDirAssets(t *testing.T) { + + tests := []struct { + description string + baseDir string + files []struct { + relativePath string + expectedPath string + } + vmPath string + expectedCfg string + }{ + { + description: "relative path assets", + baseDir: "/files", + files: []struct { + relativePath string + expectedPath string + }{ + { + relativePath: "/dir1/file1.txt", + expectedPath: constants.AddonsPath, + }, + { + relativePath: "/dir1/file2.txt", + expectedPath: constants.AddonsPath, + }, + { + relativePath: "/dir2/file1.txt", + expectedPath: constants.AddonsPath, + }, + }, + vmPath: constants.AddonsPath, + }, + { + description: "absolute path assets", + baseDir: "/files", + files: []struct { + relativePath string + expectedPath string + }{ + { + relativePath: "/dir1/file1.txt", + expectedPath: "/dir1", + }, + { + relativePath: "/dir1/file2.txt", + expectedPath: "/dir1", + }, + { + relativePath: "/dir2/file1.txt", + expectedPath: "/dir2", + }, + }, + vmPath: "", + }, + } + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + fs := afero.NewMemMapFs() + assetNames := make([]string, 0) + for _, fileDef := range test.files { + err := func() error { + path := filepath.Join(test.baseDir, fileDef.relativePath) + assetNames = append(assetNames, path) + err := fs.MkdirAll(filepath.Dir(path), 0755) + if err != nil { + return err + } + + file, err := fs.Create(path) + if err != nil { + return err + } + + defer file.Close() + + _, err = file.WriteString("test") + return err + }() + if err != nil { + t.Errorf("unable to create file on fs: %v", err) + return + } + } + + var actualFiles []CopyableFile + err := addMinikubeDirToAssets(fs, test.baseDir, test.vmPath, &actualFiles) + if err != nil { + t.Errorf("got unexpected error add minikube dir assets: %v", err) + return + } + for idx, actualFile := range actualFiles { + if actualFile.GetAssetName() != assetNames[idx] { + t.Errorf("actual file assets does not match expected. actual:\n%s\nexpected:\n%s", actualFile.GetAssetName(), assetNames[idx]) + return + } + if actualFile.GetTargetDir() != test.files[idx].expectedPath { + t.Errorf("actual file target dir does not match expected. actual:\n%s\nexpected:\n%s", actualFile.GetTargetDir(), test.files[idx].expectedPath) + return + } + } + }) + } + +} diff --git a/pkg/minikube/assets/vm_assets.go b/pkg/minikube/assets/vm_assets.go index 27d668a7ea5e..c8858a1d4c6a 100644 --- a/pkg/minikube/assets/vm_assets.go +++ b/pkg/minikube/assets/vm_assets.go @@ -23,6 +23,7 @@ import ( "path" "github.com/pkg/errors" + "github.com/spf13/afero" ) type CopyableFile interface { @@ -68,7 +69,10 @@ func NewMemoryAssetTarget(d []byte, targetPath, permissions string) *MemoryAsset return NewMemoryAsset(d, path.Dir(targetPath), path.Base(targetPath), permissions) } -func NewFileAsset(assetName, targetDir, targetName, permissions string) (*FileAsset, error) { +func NewFileAsset(fs afero.Fs, assetName, targetDir, targetName, permissions string) (*FileAsset, error) { + if fs == nil { + fs = afero.NewOsFs() + } f := &FileAsset{ BaseAsset{ AssetName: assetName, @@ -77,7 +81,7 @@ func NewFileAsset(assetName, targetDir, targetName, permissions string) (*FileAs Permissions: permissions, }, } - file, err := os.Open(f.AssetName) + file, err := fs.Open(f.AssetName) if err != nil { return nil, errors.Wrapf(err, "Error opening file asset: %s", f.AssetName) } diff --git a/pkg/minikube/bootstrapper/certs.go b/pkg/minikube/bootstrapper/certs.go index 984973d1caae..5eff336d6664 100644 --- a/pkg/minikube/bootstrapper/certs.go +++ b/pkg/minikube/bootstrapper/certs.go @@ -58,7 +58,7 @@ func SetupCerts(cmd CommandRunner, k8s config.KubernetesConfig) error { if strings.HasSuffix(cert, ".key") { perms = "0600" } - certFile, err := assets.NewFileAsset(p, util.DefaultCertPath, cert, perms) + certFile, err := assets.NewFileAsset(nil, p, util.DefaultCertPath, cert, perms) if err != nil { return err } diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index 34cb39c4b93c..2161566ff026 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -366,7 +366,7 @@ func (k *KubeadmBootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { if err != nil { return errors.Wrapf(err, "downloading %s", bin) } - f, err := assets.NewFileAsset(path, "/usr/bin", bin, "0641") + f, err := assets.NewFileAsset(nil, path, "/usr/bin", bin, "0641") if err != nil { return errors.Wrap(err, "making new file asset") } diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index 155782c876fa..24d4603d442b 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -202,7 +202,7 @@ func LoadFromCacheBlocking(cmd bootstrapper.CommandRunner, src string) error { } } dst := path.Join(tempLoadDir, filename) - f, err := assets.NewFileAsset(src, tempLoadDir, filename, "0777") + f, err := assets.NewFileAsset(nil, src, tempLoadDir, filename, "0777") if err != nil { return errors.Wrapf(err, "creating copyable file asset: %s", filename) } diff --git a/pkg/provision/buildroot.go b/pkg/provision/buildroot.go index ef1732dccd1c..b9c9439da341 100644 --- a/pkg/provision/buildroot.go +++ b/pkg/provision/buildroot.go @@ -235,7 +235,7 @@ func configureAuth(p *BuildrootProvisioner) error { } for src, dst := range hostCerts { - f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0777") + f, err := assets.NewFileAsset(nil, src, path.Dir(dst), filepath.Base(dst), "0777") if err != nil { return errors.Wrapf(err, "open cert file: %s", src) } @@ -280,7 +280,7 @@ func configureAuth(p *BuildrootProvisioner) error { } sshRunner := bootstrapper.NewSSHRunner(sshClient) for src, dst := range remoteCerts { - f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0640") + f, err := assets.NewFileAsset(nil, src, path.Dir(dst), filepath.Base(dst), "0640") if err != nil { return errors.Wrapf(err, "error copying %s to %s", src, dst) } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 0d0b50d70e82..87be29517b24 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -33,6 +33,7 @@ import ( units "github.com/docker/go-units" "github.com/golang/glog" "github.com/pkg/errors" + "github.com/spf13/afero" ) const ErrPrefix = "! " @@ -168,8 +169,8 @@ func (m MultiError) ToError() error { return errors.New(strings.Join(errStrings, "\n")) } -func IsDirectory(path string) (bool, error) { - fileInfo, err := os.Stat(path) +func IsDirectory(fs afero.Fs, path string) (bool, error) { + fileInfo, err := fs.Stat(path) if err != nil { return false, errors.Wrapf(err, "Error calling os.Stat on file %s", path) }