From b538642464bcc02c08e8a61e81466ccc2a5bb4ed Mon Sep 17 00:00:00 2001 From: Paul Morie Date: Mon, 4 May 2015 10:43:10 -0400 Subject: [PATCH] Inject mounter into volume plugins --- cmd/kubelet/app/server.go | 7 +++++- pkg/kubelet/kubelet.go | 9 +++++++- pkg/kubelet/volumes.go | 21 +++++++++--------- pkg/volume/aws_ebs/aws_ebs.go | 8 +++---- pkg/volume/empty_dir/empty_dir.go | 20 +++++------------ pkg/volume/empty_dir/empty_dir_linux.go | 6 +++++ pkg/volume/empty_dir/empty_dir_test.go | 2 +- pkg/volume/gce_pd/gce_pd.go | 8 +++---- pkg/volume/gce_pd/gce_pd_test.go | 4 ++-- pkg/volume/git_repo/git_repo.go | 12 ++++++---- pkg/volume/git_repo/git_repo_test.go | 9 ++++---- pkg/volume/glusterfs/glusterfs.go | 8 +++---- pkg/volume/host_path/host_path.go | 5 +++-- pkg/volume/host_path/host_path_test.go | 4 ++-- pkg/volume/iscsi/iscsi.go | 8 +++---- pkg/volume/nfs/nfs.go | 4 ++-- .../persistent_claim/persistent_claim.go | 7 +++--- .../persistent_claim/persistent_claim_test.go | 4 ++-- pkg/volume/plugins.go | 9 ++++---- pkg/volume/secret/secret.go | 22 ++++++++++--------- pkg/volume/secret/secret_test.go | 6 ++--- pkg/volume/testing.go | 13 ++++++----- 22 files changed, 109 insertions(+), 87 deletions(-) diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index ce66f9031e2..29e7b30d951 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -45,6 +45,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network" "github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" @@ -309,6 +310,7 @@ func (s *KubeletServer) Run(_ []string) error { ResourceContainer: s.ResourceContainer, CgroupRoot: s.CgroupRoot, ContainerRuntime: s.ContainerRuntime, + Mounter: mount.New(), } RunKubelet(&kcfg, nil) @@ -419,6 +421,7 @@ func SimpleKubelet(client *client.Client, OSInterface: osInterface, CgroupRoot: "", ContainerRuntime: "docker", + Mounter: mount.New(), } return &kcfg } @@ -548,6 +551,7 @@ type KubeletConfig struct { OSInterface kubecontainer.OSInterface CgroupRoot string ContainerRuntime string + Mounter mount.Interface } func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) { @@ -594,7 +598,8 @@ func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod kc.ResourceContainer, kc.OSInterface, kc.CgroupRoot, - kc.ContainerRuntime) + kc.ContainerRuntime, + kc.Mounter) if err != nil { return nil, nil, err diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 630f3e20b90..849e56734ec 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -51,6 +51,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" utilErrors "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/version" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -121,7 +122,8 @@ func NewMainKubelet( resourceContainer string, osInterface kubecontainer.OSInterface, cgroupRoot string, - containerRuntime string) (*Kubelet, error) { + containerRuntime string, + mounter mount.Interface) (*Kubelet, error) { if rootDirectory == "" { return nil, fmt.Errorf("invalid root directory %q", rootDirectory) } @@ -234,6 +236,7 @@ func NewMainKubelet( os: osInterface, oomWatcher: oomWatcher, cgroupRoot: cgroupRoot, + mounter: mounter, } if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil { @@ -401,6 +404,7 @@ type Kubelet struct { // status. Kubelet may fail to update node status reliablly if the value is too small, // as it takes time to gather all necessary node information. nodeStatusUpdateFrequency time.Duration + // The name of the resource-only container to run the Kubelet in (empty for no container). // Name must be absolute. resourceContainer string @@ -412,6 +416,9 @@ type Kubelet struct { // If non-empty, pass this to the container runtime as the root cgroup. cgroupRoot string + + // Mounter to use for volumes. + mounter mount.Interface } // getRootDir returns the full path to the directory under which kubelet can diff --git a/pkg/kubelet/volumes.go b/pkg/kubelet/volumes.go index 5cbee68853d..ee437d643df 100644 --- a/pkg/kubelet/volumes.go +++ b/pkg/kubelet/volumes.go @@ -25,6 +25,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" "github.com/davecgh/go-spew/spew" "github.com/golang/glog" @@ -54,15 +55,15 @@ func (vh *volumeHost) GetKubeClient() client.Interface { return vh.kubelet.kubeClient } -func (vh *volumeHost) NewWrapperBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { - b, err := vh.kubelet.newVolumeBuilderFromPlugins(spec, podRef, opts) +func (vh *volumeHost) NewWrapperBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { + b, err := vh.kubelet.newVolumeBuilderFromPlugins(spec, podRef, opts, mounter) if err == nil && b == nil { return nil, errUnsupportedVolumeType } return b, nil } -func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID) (volume.Cleaner, error) { +func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { plugin, err := vh.kubelet.volumePluginMgr.FindPluginBySpec(spec) if err != nil { return nil, err @@ -71,14 +72,14 @@ func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID) (vo // Not found but not an error return nil, nil } - c, err := plugin.NewCleaner(spec.Name, podUID) + c, err := plugin.NewCleaner(spec.Name, podUID, mounter) if err == nil && c == nil { return nil, errUnsupportedVolumeType } return c, nil } -func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { +func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec) if err != nil { return nil, fmt.Errorf("can't use volume plugins for %s: %v", spew.Sprintf("%#v", *spec), err) @@ -87,7 +88,7 @@ func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, podRef *api.Ob // Not found but not an error return nil, nil } - builder, err := plugin.NewBuilder(spec, podRef, opts) + builder, err := plugin.NewBuilder(spec, podRef, opts, mounter) if err != nil { return nil, fmt.Errorf("failed to instantiate volume plugin for %s: %v", spew.Sprintf("%#v", *spec), err) } @@ -113,7 +114,7 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (volumeMap, error) { // Try to use a plugin for this volume. internal := volume.NewSpecFromVolume(volSpec) - builder, err := kl.newVolumeBuilderFromPlugins(internal, podRef, volume.VolumeOptions{rootContext}) + builder, err := kl.newVolumeBuilderFromPlugins(internal, podRef, volume.VolumeOptions{rootContext}, kl.mounter) if err != nil { glog.Errorf("Could not create volume builder for pod %s: %v", pod.UID, err) return nil, err @@ -164,7 +165,7 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner { // or volume objects. // Try to use a plugin for this volume. - cleaner, err := kl.newVolumeCleanerFromPlugins(volumeKind, volumeName, podUID) + cleaner, err := kl.newVolumeCleanerFromPlugins(volumeKind, volumeName, podUID, kl.mounter) if err != nil { glog.Errorf("Could not create volume cleaner for %s: %v", volumeNameDir.Name(), err) continue @@ -180,7 +181,7 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner { return currentVolumes } -func (kl *Kubelet) newVolumeCleanerFromPlugins(kind string, name string, podUID types.UID) (volume.Cleaner, error) { +func (kl *Kubelet) newVolumeCleanerFromPlugins(kind string, name string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { plugName := util.UnescapeQualifiedNameForDisk(kind) plugin, err := kl.volumePluginMgr.FindPluginByName(plugName) if err != nil { @@ -191,7 +192,7 @@ func (kl *Kubelet) newVolumeCleanerFromPlugins(kind string, name string, podUID // Not found but not an error. return nil, nil } - cleaner, err := plugin.NewCleaner(name, podUID) + cleaner, err := plugin.NewCleaner(name, podUID, mounter) if err != nil { return nil, fmt.Errorf("failed to instantiate volume plugin for %s/%s: %v", podUID, kind, err) } diff --git a/pkg/volume/aws_ebs/aws_ebs.go b/pkg/volume/aws_ebs/aws_ebs.go index f6b2aa62706..e4a99e97846 100644 --- a/pkg/volume/aws_ebs/aws_ebs.go +++ b/pkg/volume/aws_ebs/aws_ebs.go @@ -68,9 +68,9 @@ func (plugin *awsElasticBlockStorePlugin) GetAccessModes() []api.AccessModeType } } -func (plugin *awsElasticBlockStorePlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *awsElasticBlockStorePlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, podRef.UID, &AWSDiskUtil{}, mount.New()) + return plugin.newBuilderInternal(spec, podRef.UID, &AWSDiskUtil{}, mounter) } func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Builder, error) { @@ -103,9 +103,9 @@ func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec, }, nil } -func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &AWSDiskUtil{}, mount.New()) + return plugin.newCleanerInternal(volName, podUID, &AWSDiskUtil{}, mounter) } func (plugin *awsElasticBlockStorePlugin) newCleanerInternal(volName string, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/empty_dir/empty_dir.go b/pkg/volume/empty_dir/empty_dir.go index e2d7bb286ad..01581b49e58 100644 --- a/pkg/volume/empty_dir/empty_dir.go +++ b/pkg/volume/empty_dir/empty_dir.go @@ -30,21 +30,14 @@ import ( // This is the primary entrypoint for volume plugins. func ProbeVolumePlugins() []volume.VolumePlugin { - return ProbeVolumePluginsWithMounter(mount.New()) -} - -// ProbePluginsWithMounter is a convenience for testing other plugins which wrap this one. -//FIXME: alternative: pass mount.Interface to all ProbeVolumePlugins() functions? Opinions? -func ProbeVolumePluginsWithMounter(mounter mount.Interface) []volume.VolumePlugin { return []volume.VolumePlugin{ - &emptyDirPlugin{nil, mounter, false}, - &emptyDirPlugin{nil, mounter, true}, + &emptyDirPlugin{nil, false}, + &emptyDirPlugin{nil, true}, } } type emptyDirPlugin struct { host volume.VolumeHost - mounter mount.Interface legacyMode bool // if set, plugin answers to the legacy name } @@ -78,9 +71,8 @@ func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool { return false } -func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { - // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, podRef, plugin.mounter, &realMountDetector{plugin.mounter}, opts) +func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { + return plugin.newBuilderInternal(spec, podRef, mounter, &realMountDetector{mounter}, opts) } func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, podRef *api.ObjectReference, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions) (volume.Builder, error) { @@ -104,9 +96,9 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, podRef *api. }, nil } -func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, plugin.mounter, &realMountDetector{plugin.mounter}) + return plugin.newCleanerInternal(volName, podUID, mounter, &realMountDetector{mounter}) } func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface, mountDetector mountDetector) (volume.Cleaner, error) { diff --git a/pkg/volume/empty_dir/empty_dir_linux.go b/pkg/volume/empty_dir/empty_dir_linux.go index a026da510ae..aaf2a71fc54 100644 --- a/pkg/volume/empty_dir/empty_dir_linux.go +++ b/pkg/volume/empty_dir/empty_dir_linux.go @@ -1,3 +1,5 @@ +// +build linux + /* Copyright 2015 The Kubernetes Authors All rights reserved. @@ -21,6 +23,7 @@ import ( "syscall" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" + "github.com/golang/glog" ) // Defined by Linux - the type number for tmpfs mounts. @@ -32,6 +35,7 @@ type realMountDetector struct { } func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) { + glog.V(5).Infof("Determining mount medium of %v", path) isMnt, err := m.mounter.IsMountPoint(path) if err != nil { return 0, false, fmt.Errorf("IsMountPoint(%q): %v", path, err) @@ -40,6 +44,8 @@ func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, er if err := syscall.Statfs(path, &buf); err != nil { return 0, false, fmt.Errorf("statfs(%q): %v", path, err) } + + glog.V(5).Info("Statfs_t of %v: %+v", path, buf) if buf.Type == linuxTmpfsMagic { return mediumMemory, isMnt, nil } diff --git a/pkg/volume/empty_dir/empty_dir_test.go b/pkg/volume/empty_dir/empty_dir_test.go index 20bc3137bb9..977cb7de68e 100644 --- a/pkg/volume/empty_dir/empty_dir_test.go +++ b/pkg/volume/empty_dir/empty_dir_test.go @@ -197,7 +197,7 @@ func TestPluginBackCompat(t *testing.T) { spec := &api.Volume{ Name: "vol1", } - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}, nil) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } diff --git a/pkg/volume/gce_pd/gce_pd.go b/pkg/volume/gce_pd/gce_pd.go index 36725cf7a27..1f73c2bbfb0 100644 --- a/pkg/volume/gce_pd/gce_pd.go +++ b/pkg/volume/gce_pd/gce_pd.go @@ -75,9 +75,9 @@ func (plugin *gcePersistentDiskPlugin) GetAccessModes() []api.AccessModeType { } } -func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, podRef.UID, &GCEDiskUtil{}, mount.New()) + return plugin.newBuilderInternal(spec, podRef.UID, &GCEDiskUtil{}, mounter) } func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Builder, error) { @@ -116,9 +116,9 @@ func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, pod }, nil } -func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &GCEDiskUtil{}, mount.New()) + return plugin.newCleanerInternal(volName, podUID, &GCEDiskUtil{}, mounter) } func (plugin *gcePersistentDiskPlugin) newCleanerInternal(volName string, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/gce_pd/gce_pd_test.go b/pkg/volume/gce_pd/gce_pd_test.go index 07181ce6444..4eb9d5c9f7f 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -186,11 +186,11 @@ func TestPluginLegacy(t *testing.T) { } spec := &api.Volume{VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}} - if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}); err == nil { + if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}, nil); err == nil { t.Errorf("Expected failiure") } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } diff --git a/pkg/volume/git_repo/git_repo.go b/pkg/volume/git_repo/git_repo.go index ef9359c4c4d..744bddbd6e9 100644 --- a/pkg/volume/git_repo/git_repo.go +++ b/pkg/volume/git_repo/git_repo.go @@ -25,6 +25,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" volumeutil "github.com/GoogleCloudPlatform/kubernetes/pkg/volume/util" ) @@ -66,7 +67,7 @@ func (plugin *gitRepoPlugin) CanSupport(spec *volume.Spec) bool { return spec.VolumeSource.GitRepo != nil } -func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { +func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { if plugin.legacyMode { // Legacy mode instances can be cleaned up but not created anew. return nil, fmt.Errorf("legacy mode: can not create new instances") @@ -80,10 +81,11 @@ func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectRef plugin: plugin, legacyMode: false, opts: opts, + mounter: mounter, }, nil } -func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { legacy := false if plugin.legacyMode { legacy = true @@ -93,6 +95,7 @@ func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID) (volum volName: volName, plugin: plugin, legacyMode: legacy, + mounter: mounter, }, nil } @@ -107,6 +110,7 @@ type gitRepo struct { plugin *gitRepoPlugin legacyMode bool opts volume.VolumeOptions + mounter mount.Interface } // SetUp creates new directory and clones a git repo. @@ -130,7 +134,7 @@ func (gr *gitRepo) SetUpAt(dir string) error { } // Wrap EmptyDir, let it do the setup. - wrapped, err := gr.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &gr.podRef, gr.opts) + wrapped, err := gr.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &gr.podRef, gr.opts, gr.mounter) if err != nil { return err } @@ -193,7 +197,7 @@ func (gr *gitRepo) TearDown() error { // TearDownAt simply deletes everything in the directory. func (gr *gitRepo) TearDownAt(dir string) error { // Wrap EmptyDir, let it do the teardown. - wrapped, err := gr.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, gr.podRef.UID) + wrapped, err := gr.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, gr.podRef.UID, gr.mounter) if err != nil { return err } diff --git a/pkg/volume/git_repo/git_repo_test.go b/pkg/volume/git_repo/git_repo_test.go index d18336e8487..37d7d5df2c6 100644 --- a/pkg/volume/git_repo/git_repo_test.go +++ b/pkg/volume/git_repo/git_repo_test.go @@ -27,6 +27,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume/empty_dir" ) @@ -118,7 +119,7 @@ func TestPlugin(t *testing.T) { }, }, } - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}, mount.New()) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -140,7 +141,7 @@ func TestPlugin(t *testing.T) { } } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), mount.New()) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } @@ -174,11 +175,11 @@ func TestPluginLegacy(t *testing.T) { } spec := &api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}} - if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}); err == nil { + if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}, nil); err == nil { t.Errorf("Expected failiure") } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } diff --git a/pkg/volume/glusterfs/glusterfs.go b/pkg/volume/glusterfs/glusterfs.go index a4c141d2ecc..a18a8c00c6e 100644 --- a/pkg/volume/glusterfs/glusterfs.go +++ b/pkg/volume/glusterfs/glusterfs.go @@ -64,7 +64,7 @@ func (plugin *glusterfsPlugin) GetAccessModes() []api.AccessModeType { } } -func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { ep_name := spec.VolumeSource.Glusterfs.EndpointsName ns := podRef.Namespace ep, err := plugin.host.GetKubeClient().Endpoints(ns).Get(ep_name) @@ -73,7 +73,7 @@ func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectR return nil, err } glog.V(1).Infof("Glusterfs: endpoints %v", ep) - return plugin.newBuilderInternal(spec, ep, podRef, mount.New(), exec.New()) + return plugin.newBuilderInternal(spec, ep, podRef, mounter, exec.New()) } func (plugin *glusterfsPlugin) newBuilderInternal(spec *volume.Spec, ep *api.Endpoints, podRef *api.ObjectReference, mounter mount.Interface, exe exec.Interface) (volume.Builder, error) { @@ -89,8 +89,8 @@ func (plugin *glusterfsPlugin) newBuilderInternal(spec *volume.Spec, ep *api.End }, nil } -func (plugin *glusterfsPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID, mount.New()) +func (plugin *glusterfsPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, mounter) } func (plugin *glusterfsPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/host_path/host_path.go b/pkg/volume/host_path/host_path.go index 0606d03aa8e..70d5aeae23f 100644 --- a/pkg/volume/host_path/host_path.go +++ b/pkg/volume/host_path/host_path.go @@ -21,6 +21,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" ) @@ -57,7 +58,7 @@ func (plugin *hostPathPlugin) GetAccessModes() []api.AccessModeType { } } -func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, _ mount.Interface) (volume.Builder, error) { if spec.VolumeSource.HostPath != nil { return &hostPath{spec.VolumeSource.HostPath.Path}, nil } else { @@ -65,7 +66,7 @@ func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectRe } } -func (plugin *hostPathPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *hostPathPlugin) NewCleaner(volName string, podUID types.UID, _ mount.Interface) (volume.Cleaner, error) { return &hostPath{""}, nil } diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 0049d5f43eb..6a652fe6190 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -68,7 +68,7 @@ func TestPlugin(t *testing.T) { Name: "vol1", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/vol1"}}, } - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}, nil) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -85,7 +85,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Expected success, got: %v", err) } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } diff --git a/pkg/volume/iscsi/iscsi.go b/pkg/volume/iscsi/iscsi.go index b062b43e4f4..97d892ba090 100644 --- a/pkg/volume/iscsi/iscsi.go +++ b/pkg/volume/iscsi/iscsi.go @@ -72,9 +72,9 @@ func (plugin *ISCSIPlugin) GetAccessModes() []api.AccessModeType { } } -func (plugin *ISCSIPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *ISCSIPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, podRef.UID, &ISCSIUtil{}, mount.New()) + return plugin.newBuilderInternal(spec, podRef.UID, &ISCSIUtil{}, mounter) } func (plugin *ISCSIPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface) (volume.Builder, error) { @@ -95,9 +95,9 @@ func (plugin *ISCSIPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UI }, nil } -func (plugin *ISCSIPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *ISCSIPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &ISCSIUtil{}, mount.New()) + return plugin.newCleanerInternal(volName, podUID, &ISCSIUtil{}, mounter) } func (plugin *ISCSIPlugin) newCleanerInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index 32f6c4902f9..cde14268fe2 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -64,7 +64,7 @@ func (plugin *nfsPlugin) GetAccessModes() []api.AccessModeType { } } -func (plugin *nfsPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions) (volume.Builder, error) { +func (plugin *nfsPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, _ volume.VolumeOptions, _ mount.Interface) (volume.Builder, error) { return plugin.newBuilderInternal(spec, podRef, plugin.mounter) } @@ -80,7 +80,7 @@ func (plugin *nfsPlugin) newBuilderInternal(spec *volume.Spec, podRef *api.Objec }, nil } -func (plugin *nfsPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *nfsPlugin) NewCleaner(volName string, podUID types.UID, _ mount.Interface) (volume.Cleaner, error) { return plugin.newCleanerInternal(volName, podUID, plugin.mounter) } diff --git a/pkg/volume/persistent_claim/persistent_claim.go b/pkg/volume/persistent_claim/persistent_claim.go index 060fe7475cc..8fd62b78137 100644 --- a/pkg/volume/persistent_claim/persistent_claim.go +++ b/pkg/volume/persistent_claim/persistent_claim.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" "github.com/golang/glog" ) @@ -50,7 +51,7 @@ func (plugin *persistentClaimPlugin) CanSupport(spec *volume.Spec) bool { return spec.VolumeSource.PersistentVolumeClaimVolumeSource != nil } -func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { +func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { claim, err := plugin.host.GetKubeClient().PersistentVolumeClaims(podRef.Namespace).Get(spec.VolumeSource.PersistentVolumeClaimVolumeSource.ClaimName) if err != nil { glog.Errorf("Error finding claim: %+v\n", spec.VolumeSource.PersistentVolumeClaimVolumeSource.ClaimName) @@ -67,7 +68,7 @@ func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, podRef *api.O return nil, err } - builder, err := plugin.host.NewWrapperBuilder(volume.NewSpecFromPersistentVolume(pv), podRef, opts) + builder, err := plugin.host.NewWrapperBuilder(volume.NewSpecFromPersistentVolume(pv), podRef, opts, mounter) if err != nil { glog.Errorf("Error creating builder for claim: %+v\n", claim.Name) return nil, err @@ -76,6 +77,6 @@ func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, podRef *api.O return builder, nil } -func (plugin *persistentClaimPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { +func (plugin *persistentClaimPlugin) NewCleaner(_ string, _ types.UID, _ mount.Interface) (volume.Cleaner, error) { return nil, fmt.Errorf("This will never be called directly. The PV backing this claim has a cleaner. Kubelet uses that cleaner, not this one, when removing orphaned volumes.") } diff --git a/pkg/volume/persistent_claim/persistent_claim_test.go b/pkg/volume/persistent_claim/persistent_claim_test.go index 75cf935317a..45af97c61d5 100644 --- a/pkg/volume/persistent_claim/persistent_claim_test.go +++ b/pkg/volume/persistent_claim/persistent_claim_test.go @@ -169,7 +169,7 @@ func TestNewBuilder(t *testing.T) { Name: "vol1", VolumeSource: item.podVolume, } - builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}) + builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}, nil) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -229,7 +229,7 @@ func TestNewBuilderClaimNotBound(t *testing.T) { Name: "vol1", VolumeSource: podVolume, } - builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}) + builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{}, nil) if builder != nil { t.Errorf("Expected a nil builder if the claim wasn't bound") } diff --git a/pkg/volume/plugins.go b/pkg/volume/plugins.go index d03cf11aa01..7669ae53841 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -26,6 +26,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/golang/glog" ) @@ -62,12 +63,12 @@ type VolumePlugin interface { // Ownership of the spec pointer in *not* transferred. // - spec: The api.Volume spec // - podRef: a reference to the enclosing pod - NewBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions) (Builder, error) + NewBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions, mounter mount.Interface) (Builder, error) // NewCleaner creates a new volume.Cleaner from recoverable state. // - name: The volume name, as per the api.Volume spec. // - podUID: The UID of the enclosing pod - NewCleaner(name string, podUID types.UID) (Cleaner, error) + NewCleaner(name string, podUID types.UID, mounter mount.Interface) (Cleaner, error) } // PersistentVolumePlugin is an extended interface of VolumePlugin and is used @@ -105,12 +106,12 @@ type VolumeHost interface { // the provided spec. This is used to implement volume plugins which // "wrap" other plugins. For example, the "secret" volume is // implemented in terms of the "emptyDir" volume. - NewWrapperBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions) (Builder, error) + NewWrapperBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions, mounter mount.Interface) (Builder, error) // NewWrapperCleaner finds an appropriate plugin with which to handle // the provided spec. See comments on NewWrapperBuilder for more // context. - NewWrapperCleaner(spec *Spec, podUID types.UID) (Cleaner, error) + NewWrapperCleaner(spec *Spec, podUID types.UID, mounter mount.Interface) (Cleaner, error) } // VolumePluginMgr tracks registered plugins. diff --git a/pkg/volume/secret/secret.go b/pkg/volume/secret/secret.go index 7ac1a4c4930..c41e437ac41 100644 --- a/pkg/volume/secret/secret.go +++ b/pkg/volume/secret/secret.go @@ -24,6 +24,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" "github.com/GoogleCloudPlatform/kubernetes/pkg/volume" volumeutil "github.com/GoogleCloudPlatform/kubernetes/pkg/volume/util" "github.com/golang/glog" @@ -55,20 +56,20 @@ func (plugin *secretPlugin) CanSupport(spec *volume.Spec) bool { return spec.VolumeSource.Secret != nil } -func (plugin *secretPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { - return plugin.newBuilderInternal(spec, podRef, opts) +func (plugin *secretPlugin) NewBuilder(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { + return plugin.newBuilderInternal(spec, podRef, opts, mounter) } -func (plugin *secretPlugin) newBuilderInternal(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions) (volume.Builder, error) { - return &secretVolume{spec.Name, *podRef, plugin, spec.VolumeSource.Secret.SecretName, &opts}, nil +func (plugin *secretPlugin) newBuilderInternal(spec *volume.Spec, podRef *api.ObjectReference, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { + return &secretVolume{spec.Name, *podRef, plugin, spec.VolumeSource.Secret.SecretName, &opts, mounter}, nil } -func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID) +func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, mounter) } -func (plugin *secretPlugin) newCleanerInternal(volName string, podUID types.UID) (volume.Cleaner, error) { - return &secretVolume{volName, api.ObjectReference{UID: podUID}, plugin, "", nil}, nil +func (plugin *secretPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { + return &secretVolume{volName, api.ObjectReference{UID: podUID}, plugin, "", nil, mounter}, nil } // secretVolume handles retrieving secrets from the API server @@ -79,6 +80,7 @@ type secretVolume struct { plugin *secretPlugin secretName string opts *volume.VolumeOptions + mounter mount.Interface } func (sv *secretVolume) SetUp() error { @@ -99,7 +101,7 @@ func (sv *secretVolume) SetUpAt(dir string) error { glog.V(3).Infof("Setting up volume %v for pod %v at %v", sv.volName, sv.podRef.UID, dir) // Wrap EmptyDir, let it do the setup. - wrapped, err := sv.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &sv.podRef, *sv.opts) + wrapped, err := sv.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &sv.podRef, *sv.opts, sv.mounter) if err != nil { return err } @@ -161,7 +163,7 @@ func (sv *secretVolume) TearDownAt(dir string) error { glog.V(3).Infof("Tearing down volume %v for pod %v at %v", sv.volName, sv.podRef.UID, dir) // Wrap EmptyDir, let it do the teardown. - wrapped, err := sv.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, sv.podRef.UID) + wrapped, err := sv.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, sv.podRef.UID, sv.mounter) if err != nil { return err } diff --git a/pkg/volume/secret/secret_test.go b/pkg/volume/secret/secret_test.go index ed27c3a9145..8a37735333d 100644 --- a/pkg/volume/secret/secret_test.go +++ b/pkg/volume/secret/secret_test.go @@ -39,7 +39,7 @@ func newTestHost(t *testing.T, client client.Interface) volume.VolumeHost { t.Fatalf("can't make a temp rootdir: %v", err) } - return volume.NewFakeVolumeHost(tempDir, client, empty_dir.ProbeVolumePluginsWithMounter(&mount.FakeMounter{})) + return volume.NewFakeVolumeHost(tempDir, client, empty_dir.ProbeVolumePlugins()) } func TestCanSupport(t *testing.T) { @@ -97,7 +97,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Can't find the plugin by name") } - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), &api.ObjectReference{UID: types.UID(testPodUID)}, volume.VolumeOptions{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), &api.ObjectReference{UID: types.UID(testPodUID)}, volume.VolumeOptions{}, &mount.FakeMounter{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -139,7 +139,7 @@ func TestPlugin(t *testing.T) { } } - cleaner, err := plugin.NewCleaner(testVolumeName, types.UID(testPodUID)) + cleaner, err := plugin.NewCleaner(testVolumeName, types.UID(testPodUID), mount.New()) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } diff --git a/pkg/volume/testing.go b/pkg/volume/testing.go index d6df0e58c6e..240c2ceaf25 100644 --- a/pkg/volume/testing.go +++ b/pkg/volume/testing.go @@ -24,6 +24,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount" ) // fakeVolumeHost is useful for testing volume plugins. @@ -55,20 +56,20 @@ func (f *fakeVolumeHost) GetKubeClient() client.Interface { return f.kubeClient } -func (f *fakeVolumeHost) NewWrapperBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions) (Builder, error) { +func (f *fakeVolumeHost) NewWrapperBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions, mounter mount.Interface) (Builder, error) { plug, err := f.pluginMgr.FindPluginBySpec(spec) if err != nil { return nil, err } - return plug.NewBuilder(spec, podRef, opts) + return plug.NewBuilder(spec, podRef, opts, mounter) } -func (f *fakeVolumeHost) NewWrapperCleaner(spec *Spec, podUID types.UID) (Cleaner, error) { +func (f *fakeVolumeHost) NewWrapperCleaner(spec *Spec, podUID types.UID, mounter mount.Interface) (Cleaner, error) { plug, err := f.pluginMgr.FindPluginBySpec(spec) if err != nil { return nil, err } - return plug.NewCleaner(spec.Name, podUID) + return plug.NewCleaner(spec.Name, podUID, mounter) } // FakeVolumePlugin is useful for testing. It tries to be a fully compliant @@ -95,11 +96,11 @@ func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool { return true } -func (plugin *FakeVolumePlugin) NewBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions) (Builder, error) { +func (plugin *FakeVolumePlugin) NewBuilder(spec *Spec, podRef *api.ObjectReference, opts VolumeOptions, mounter mount.Interface) (Builder, error) { return &FakeVolume{podRef.UID, spec.Name, plugin}, nil } -func (plugin *FakeVolumePlugin) NewCleaner(volName string, podUID types.UID) (Cleaner, error) { +func (plugin *FakeVolumePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (Cleaner, error) { return &FakeVolume{podUID, volName, plugin}, nil }