diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 2c794781a52..a14d0f452af 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -51,6 +51,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" nodeutil "k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/oom" @@ -287,9 +288,11 @@ func (s *KubeletServer) KubeletConfig() (*KubeletConfig, error) { } mounter := mount.New() + var writer io.Writer = &io.StdWriter{} if s.Containerized { glog.V(2).Info("Running kubelet in containerized mode (experimental)") mounter = mount.NewNsenterMounter() + writer = &io.NsenterWriter{} } tlsOptions, err := s.InitializeTLS() @@ -384,6 +387,7 @@ func (s *KubeletServer) KubeletConfig() (*KubeletConfig, error) { SyncFrequency: s.SyncFrequency, SystemContainer: s.SystemContainer, TLSOptions: tlsOptions, + Writer: writer, VolumePlugins: ProbeVolumePlugins(), }, nil } @@ -592,6 +596,7 @@ func SimpleKubelet(client *client.Client, DockerFreeDiskMB: 256, RootFreeDiskMB: 256, } + kcfg := KubeletConfig{ Address: net.ParseIP(address), CAdvisorInterface: cadvisorInterface, @@ -630,6 +635,7 @@ func SimpleKubelet(client *client.Client, SyncFrequency: syncFrequency, SystemContainer: "", TLSOptions: tlsOptions, + Writer: &io.StdWriter{}, VolumePlugins: volumePlugins, } return &kcfg @@ -812,6 +818,7 @@ type KubeletConfig struct { SyncFrequency time.Duration SystemContainer string TLSOptions *kubelet.TLSOptions + Writer io.Writer VolumePlugins []volume.VolumePlugin } @@ -873,6 +880,7 @@ func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod kc.RktPath, kc.RktStage1Image, kc.Mounter, + kc.Writer, kc.DockerDaemonContainer, kc.SystemContainer, kc.ConfigureCBR0, diff --git a/contrib/mesos/pkg/executor/service/service.go b/contrib/mesos/pkg/executor/service/service.go index d0c5f110c0e..1f81210ef37 100644 --- a/contrib/mesos/pkg/executor/service/service.go +++ b/contrib/mesos/pkg/executor/service/service.go @@ -327,6 +327,7 @@ func (ks *KubeletExecutorServer) createAndInitKubelet( kc.RktPath, kc.RktStage1Image, kc.Mounter, + kc.Writer, kc.DockerDaemonContainer, kc.SystemContainer, kc.ConfigureCBR0, diff --git a/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go b/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go index f65d9cd50a3..af1f6243d98 100644 --- a/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go +++ b/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/types" + ioutil "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/watch" @@ -273,14 +274,22 @@ func (f *PersistentVolumeRecycler) GetKubeClient() client.Interface { return f.kubeClient } -func (f *PersistentVolumeRecycler) NewWrapperBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (f *PersistentVolumeRecycler) NewWrapperBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { return nil, fmt.Errorf("NewWrapperBuilder not supported by PVClaimBinder's VolumeHost implementation") } -func (f *PersistentVolumeRecycler) NewWrapperCleaner(spec *volume.Spec, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (f *PersistentVolumeRecycler) NewWrapperCleaner(spec *volume.Spec, podUID types.UID) (volume.Cleaner, error) { return nil, fmt.Errorf("NewWrapperCleaner not supported by PVClaimBinder's VolumeHost implementation") } func (f *PersistentVolumeRecycler) GetCloudProvider() cloudprovider.Interface { return nil } + +func (f *PersistentVolumeRecycler) GetMounter() mount.Interface { + return nil +} + +func (f *PersistentVolumeRecycler) GetWriter() ioutil.Writer { + return nil +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 4676d6f3981..8aa1baf336a 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -60,6 +60,7 @@ import ( "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/bandwidth" utilErrors "k8s.io/kubernetes/pkg/util/errors" + kubeio "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/procfs" @@ -161,6 +162,7 @@ func NewMainKubelet( rktPath string, rktStage1Image string, mounter mount.Interface, + writer kubeio.Writer, dockerDaemonContainer string, systemContainer string, configureCBR0 bool, @@ -261,6 +263,7 @@ func NewMainKubelet( oomWatcher: oomWatcher, cgroupRoot: cgroupRoot, mounter: mounter, + writer: writer, configureCBR0: configureCBR0, pods: pods, syncLoopMonitor: util.AtomicValue{}, @@ -499,6 +502,9 @@ type Kubelet struct { // Mounter to use for volumes. mounter mount.Interface + // Writer interface to use for volumes. + writer kubeio.Writer + // Manager of non-Runtime containers. containerManager containerManager diff --git a/pkg/kubelet/volumes.go b/pkg/kubelet/volumes.go index d9b3c303bc9..b8e48efd7be 100644 --- a/pkg/kubelet/volumes.go +++ b/pkg/kubelet/volumes.go @@ -28,6 +28,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" ) @@ -56,15 +57,15 @@ func (vh *volumeHost) GetKubeClient() client.Interface { return vh.kubelet.kubeClient } -func (vh *volumeHost) NewWrapperBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { - b, err := vh.kubelet.newVolumeBuilderFromPlugins(spec, pod, opts, mounter) +func (vh *volumeHost) NewWrapperBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { + b, err := vh.kubelet.newVolumeBuilderFromPlugins(spec, pod, opts) if err == nil && b == nil { return nil, errUnsupportedVolumeType } return b, nil } -func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID) (volume.Cleaner, error) { plugin, err := vh.kubelet.volumePluginMgr.FindPluginBySpec(spec) if err != nil { return nil, err @@ -73,7 +74,7 @@ func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID, mou // Not found but not an error return nil, nil } - c, err := plugin.NewCleaner(spec.Name(), podUID, mounter) + c, err := plugin.NewCleaner(spec.Name(), podUID) if err == nil && c == nil { return nil, errUnsupportedVolumeType } @@ -84,7 +85,15 @@ func (vh *volumeHost) GetCloudProvider() cloudprovider.Interface { return vh.kubelet.cloud } -func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (vh *volumeHost) GetMounter() mount.Interface { + return vh.kubelet.mounter +} + +func (vh *volumeHost) GetWriter() io.Writer { + return vh.kubelet.writer +} + +func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec) if err != nil { return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err) @@ -93,7 +102,7 @@ func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, pod *api.Pod, // Not found but not an error return nil, nil } - builder, err := plugin.NewBuilder(spec, pod, opts, mounter) + builder, err := plugin.NewBuilder(spec, pod, opts) if err != nil { return nil, fmt.Errorf("failed to instantiate volume plugin for %s: %v", spec.Name(), err) } @@ -113,7 +122,7 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap, // Try to use a plugin for this volume. internal := volume.NewSpecFromVolume(volSpec) - builder, err := kl.newVolumeBuilderFromPlugins(internal, pod, volume.VolumeOptions{RootContext: rootContext}, kl.mounter) + builder, err := kl.newVolumeBuilderFromPlugins(internal, pod, volume.VolumeOptions{RootContext: rootContext}) if err != nil { glog.Errorf("Could not create volume builder for pod %s: %v", pod.UID, err) return nil, err @@ -180,7 +189,7 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner { // or volume objects. // Try to use a plugin for this volume. - cleaner, err := kl.newVolumeCleanerFromPlugins(volume.Kind, volume.Name, podUID, kl.mounter) + cleaner, err := kl.newVolumeCleanerFromPlugins(volume.Kind, volume.Name, podUID) if err != nil { glog.Errorf("Could not create volume cleaner for %s: %v", volume.Name, err) continue @@ -195,7 +204,7 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner { return currentVolumes } -func (kl *Kubelet) newVolumeCleanerFromPlugins(kind string, name string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (kl *Kubelet) newVolumeCleanerFromPlugins(kind string, name string, podUID types.UID) (volume.Cleaner, error) { plugName := util.UnescapeQualifiedNameForDisk(kind) plugin, err := kl.volumePluginMgr.FindPluginByName(plugName) if err != nil { @@ -206,7 +215,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, mounter) + cleaner, err := plugin.NewCleaner(name, podUID) if err != nil { return nil, fmt.Errorf("failed to instantiate volume plugin for %s/%s: %v", podUID, kind, err) } diff --git a/pkg/util/io/io_test.go b/pkg/util/io/io_test.go index 5b691e27f7f..549081f3dd8 100644 --- a/pkg/util/io/io_test.go +++ b/pkg/util/io/io_test.go @@ -14,13 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package io +package io_test import ( "fmt" "github.com/pborman/uuid" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/volume" "os" "testing" @@ -36,11 +37,11 @@ func TestSavePodToFile(t *testing.T) { path := fmt.Sprintf("/tmp/kube-io-test-%s", uuid.New()) defer os.Remove(path) - if err := SavePodToFile(pod, path, 777); err != nil { + if err := io.SavePodToFile(pod, path, 777); err != nil { t.Fatalf("failed to save pod to file: %v", err) } - podFromFile, err := LoadPodFromFile(path) + podFromFile, err := io.LoadPodFromFile(path) if err != nil { t.Fatalf("failed to load pod from file: %v", err) } diff --git a/pkg/util/io/writer.go b/pkg/util/io/writer.go new file mode 100644 index 00000000000..7e0217266b2 --- /dev/null +++ b/pkg/util/io/writer.go @@ -0,0 +1,77 @@ +/* +Copyright 2015 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 io + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + + "github.com/golang/glog" +) + +// Writer is an interface which allows to write data to a file. +type Writer interface { + WriteFile(filename string, data []byte, perm os.FileMode) error +} + +// StdWriter implements Writer interface and uses standard libraries +// for writing data to files. +type StdWriter struct { +} + +func (writer *StdWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { + return ioutil.WriteFile(filename, data, perm) +} + +// Alternative implementation of Writer interface that allows writing data to file +// using nsenter command. +// If a program (e.g. kubelet) runs in a container it may want to write data to +// a mounted device. Since in Docker, mount propagation mode is set to private, +// it will not see the mounted device in its own namespace. To work around this +// limitaion one has to first enter hosts namespace (by using 'nsenter') and only +// then write data. +type NsenterWriter struct { +} + +func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { + cmd := "nsenter" + base_args := []string{ + "--mount=/rootfs/proc/1/ns/mnt", + "--", + } + + echo_args := append(base_args, "sh", "-c", + fmt.Sprintf("echo %q | cat > %s", data, filename)) + glog.V(5).Infof("Command to write data to file: %v %v", cmd, echo_args) + outputBytes, err := exec.Command(cmd, echo_args...).CombinedOutput() + if err != nil { + glog.Errorf("Output from writing to %q: %v", filename, string(outputBytes)) + return err + } + + chmod_args := append(base_args, "chmod", fmt.Sprintf("%o", perm), filename) + glog.V(5).Infof("Command to change permissions to file: %v %v", cmd, chmod_args) + outputBytes, err = exec.Command(cmd, chmod_args...).CombinedOutput() + if err != nil { + glog.Errorf("Output from chmod command: %v", string(outputBytes)) + return err + } + + return nil +} diff --git a/pkg/volume/aws_ebs/aws_ebs.go b/pkg/volume/aws_ebs/aws_ebs.go index 662bd2052c9..d72baf35838 100644 --- a/pkg/volume/aws_ebs/aws_ebs.go +++ b/pkg/volume/aws_ebs/aws_ebs.go @@ -69,9 +69,9 @@ func (plugin *awsElasticBlockStorePlugin) GetAccessModes() []api.PersistentVolum } } -func (plugin *awsElasticBlockStorePlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *awsElasticBlockStorePlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, pod.UID, &AWSDiskUtil{}, mounter) + return plugin.newBuilderInternal(spec, pod.UID, &AWSDiskUtil{}, plugin.host.GetMounter()) } func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager ebsManager, mounter mount.Interface) (volume.Builder, error) { @@ -106,12 +106,12 @@ func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec, fsType: fsType, partition: partition, readOnly: readOnly, - diskMounter: &mount.SafeFormatAndMount{mounter, exec.New()}}, nil + diskMounter: &mount.SafeFormatAndMount{plugin.host.GetMounter(), exec.New()}}, nil } -func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &AWSDiskUtil{}, mounter) + return plugin.newCleanerInternal(volName, podUID, &AWSDiskUtil{}, plugin.host.GetMounter()) } func (plugin *awsElasticBlockStorePlugin) newCleanerInternal(volName string, podUID types.UID, manager ebsManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/aws_ebs/aws_ebs_test.go b/pkg/volume/aws_ebs/aws_ebs_test.go index be3948093d5..81c4938ef7d 100644 --- a/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/pkg/volume/aws_ebs/aws_ebs_test.go @@ -201,7 +201,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/cephfs/cephfs.go b/pkg/volume/cephfs/cephfs.go index a98ce1d435b..4dbed2574cb 100644 --- a/pkg/volume/cephfs/cephfs.go +++ b/pkg/volume/cephfs/cephfs.go @@ -63,7 +63,7 @@ func (plugin *cephfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { } } -func (plugin *cephfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *cephfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { cephvs := plugin.getVolumeSource(spec) secret := "" if cephvs.SecretRef != nil { @@ -82,7 +82,7 @@ func (plugin *cephfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume glog.V(1).Infof("found ceph secret info: %s", name) } } - return plugin.newBuilderInternal(spec, pod.UID, mounter, secret) + return plugin.newBuilderInternal(spec, pod.UID, plugin.host.GetMounter(), secret) } func (plugin *cephfsPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, mounter mount.Interface, secret string) (volume.Builder, error) { @@ -110,8 +110,8 @@ func (plugin *cephfsPlugin) newBuilderInternal(spec *volume.Spec, podUID types.U }, nil } -func (plugin *cephfsPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID, mounter) +func (plugin *cephfsPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, plugin.host.GetMounter()) } func (plugin *cephfsPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/cinder/cinder.go b/pkg/volume/cinder/cinder.go index 34f47af2de4..6311142a376 100644 --- a/pkg/volume/cinder/cinder.go +++ b/pkg/volume/cinder/cinder.go @@ -62,8 +62,8 @@ func (plugin *cinderPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { } } -func (plugin *cinderPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { - return plugin.newBuilderInternal(spec, pod.UID, &CinderDiskUtil{}, mounter) +func (plugin *cinderPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { + return plugin.newBuilderInternal(spec, pod.UID, &CinderDiskUtil{}, plugin.host.GetMounter()) } func (plugin *cinderPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager cdManager, mounter mount.Interface) (volume.Builder, error) { @@ -92,8 +92,8 @@ func (plugin *cinderPlugin) newBuilderInternal(spec *volume.Spec, podUID types.U blockDeviceMounter: &cinderSafeFormatAndMount{mounter, exec.New()}}, nil } -func (plugin *cinderPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID, &CinderDiskUtil{}, mounter) +func (plugin *cinderPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, &CinderDiskUtil{}, plugin.host.GetMounter()) } func (plugin *cinderPlugin) newCleanerInternal(volName string, podUID types.UID, manager cdManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/downwardapi/downwardapi.go b/pkg/volume/downwardapi/downwardapi.go index c1b4b65bb7f..860b9025cae 100644 --- a/pkg/volume/downwardapi/downwardapi.go +++ b/pkg/volume/downwardapi/downwardapi.go @@ -30,7 +30,6 @@ import ( "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" utilErrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "github.com/golang/glog" @@ -64,13 +63,12 @@ func (plugin *downwardAPIPlugin) CanSupport(spec *volume.Spec) bool { return spec.Volume != nil && spec.Volume.DownwardAPI != nil } -func (plugin *downwardAPIPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *downwardAPIPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { v := &downwardAPIVolume{ volName: spec.Name(), pod: pod, podUID: pod.UID, plugin: plugin, - mounter: mounter, } v.fieldReferenceFileNames = make(map[string]string) for _, fileInfo := range spec.Volume.DownwardAPI.Items { @@ -81,8 +79,8 @@ func (plugin *downwardAPIPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opt opts: &opts}, nil } -func (plugin *downwardAPIPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return &downwardAPIVolumeCleaner{&downwardAPIVolume{volName: volName, podUID: podUID, plugin: plugin, mounter: mounter}}, nil +func (plugin *downwardAPIPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return &downwardAPIVolumeCleaner{&downwardAPIVolume{volName: volName, podUID: podUID, plugin: plugin}}, nil } // downwardAPIVolume retrieves downward API data and placing them into the volume on the host. @@ -92,7 +90,6 @@ type downwardAPIVolume struct { pod *api.Pod podUID types.UID // TODO: remove this redundancy as soon NewCleaner func will have *api.POD and not only types.UID plugin *downwardAPIPlugin - mounter mount.Interface } // This is the spec for the volume that this plugin wraps. @@ -121,7 +118,7 @@ func (b *downwardAPIVolumeBuilder) SetUp() error { func (b *downwardAPIVolumeBuilder) SetUpAt(dir string) error { glog.V(3).Infof("Setting up a downwardAPI volume %v for pod %v/%v at %v", b.volName, b.pod.Namespace, b.pod.Name, dir) // Wrap EmptyDir. Here we rely on the idempotency of the wrapped plugin to avoid repeatedly mounting - wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, b.pod, *b.opts, b.mounter) + wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, b.pod, *b.opts) if err != nil { glog.Errorf("Couldn't setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err @@ -360,7 +357,7 @@ func (c *downwardAPIVolumeCleaner) TearDownAt(dir string) error { glog.V(3).Infof("Tearing down volume %v for pod %v at %v", c.volName, c.podUID, dir) // Wrap EmptyDir, let it do the teardown. - wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID, c.mounter) + wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID) if err != nil { return err } diff --git a/pkg/volume/downwardapi/downwardapi_test.go b/pkg/volume/downwardapi/downwardapi_test.go index 82d9d72de12..cb7906be6dc 100644 --- a/pkg/volume/downwardapi/downwardapi_test.go +++ b/pkg/volume/downwardapi/downwardapi_test.go @@ -27,7 +27,6 @@ import ( client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/empty_dir" ) @@ -64,7 +63,7 @@ func TestCanSupport(t *testing.T) { } func CleanEverything(plugin volume.VolumePlugin, testVolumeName, volumePath string, testPodUID types.UID, t *testing.T) { - cleaner, err := plugin.NewCleaner(testVolumeName, testPodUID, mount.New()) + cleaner, err := plugin.NewCleaner(testVolumeName, testPodUID) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } @@ -117,7 +116,7 @@ func TestLabels(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Labels: labels}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) @@ -182,7 +181,7 @@ func TestAnnotations(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Annotations: annotations}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -242,7 +241,7 @@ func TestName(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Name: testName}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -303,7 +302,7 @@ func TestNamespace(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Namespace: testNamespace}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -366,7 +365,7 @@ func TestWriteTwiceNoUpdate(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Labels: labels}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) @@ -450,7 +449,7 @@ func TestWriteTwiceWithUpdate(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Labels: labels}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) @@ -556,7 +555,7 @@ func TestWriteWithUnixPath(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Labels: labels, Annotations: annotations}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) @@ -627,7 +626,7 @@ func TestWriteWithUnixPathBadPath(t *testing.T) { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID, Labels: labels}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) diff --git a/pkg/volume/empty_dir/empty_dir.go b/pkg/volume/empty_dir/empty_dir.go index ed9b12c5470..054998dfca7 100644 --- a/pkg/volume/empty_dir/empty_dir.go +++ b/pkg/volume/empty_dir/empty_dir.go @@ -69,8 +69,8 @@ func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool { return false } -func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { - return plugin.newBuilderInternal(spec, pod, mounter, &realMountDetector{mounter}, opts, newChconRunner()) +func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { + return plugin.newBuilderInternal(spec, pod, plugin.host.GetMounter(), &realMountDetector{plugin.host.GetMounter()}, opts, newChconRunner()) } func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions, chconRunner chconRunner) (volume.Builder, error) { @@ -90,9 +90,9 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod }, nil } -func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, mounter, &realMountDetector{mounter}) + return plugin.newCleanerInternal(volName, podUID, plugin.host.GetMounter(), &realMountDetector{plugin.host.GetMounter()}) } 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_test.go b/pkg/volume/empty_dir/empty_dir_test.go index bbe11db32c9..3373c91bf82 100644 --- a/pkg/volume/empty_dir/empty_dir_test.go +++ b/pkg/volume/empty_dir/empty_dir_test.go @@ -288,7 +288,7 @@ func TestPluginBackCompat(t *testing.T) { Name: "vol1", } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{RootContext: ""}, nil) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{RootContext: ""}) 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 e48ea049825..f1bae04a264 100644 --- a/pkg/volume/gce_pd/gce_pd.go +++ b/pkg/volume/gce_pd/gce_pd.go @@ -66,9 +66,9 @@ func (plugin *gcePersistentDiskPlugin) GetAccessModes() []api.PersistentVolumeAc } } -func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, pod.UID, &GCEDiskUtil{}, mounter) + return plugin.newBuilderInternal(spec, pod.UID, &GCEDiskUtil{}, plugin.host.GetMounter()) } func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Builder, error) { @@ -107,9 +107,9 @@ func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, pod diskMounter: &mount.SafeFormatAndMount{mounter, exec.New()}}, nil } -func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &GCEDiskUtil{}, mounter) + return plugin.newCleanerInternal(volName, podUID, &GCEDiskUtil{}, plugin.host.GetMounter()) } 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 fa7ad892a1d..caa9a64dffe 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -215,7 +215,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/git_repo/git_repo.go b/pkg/volume/git_repo/git_repo.go index c15594ec3d9..23a04004727 100644 --- a/pkg/volume/git_repo/git_repo.go +++ b/pkg/volume/git_repo/git_repo.go @@ -25,7 +25,6 @@ import ( "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -57,12 +56,11 @@ func (plugin *gitRepoPlugin) CanSupport(spec *volume.Spec) bool { return spec.Volume != nil && spec.Volume.GitRepo != nil } -func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { return &gitRepoVolumeBuilder{ gitRepoVolume: &gitRepoVolume{ volName: spec.Name(), podUID: pod.UID, - mounter: mounter, plugin: plugin, }, pod: *pod, @@ -73,12 +71,11 @@ func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts vo }, nil } -func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { return &gitRepoVolumeCleaner{ &gitRepoVolume{ volName: volName, podUID: podUID, - mounter: mounter, plugin: plugin, }, }, nil @@ -89,7 +86,6 @@ func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID, mounte type gitRepoVolume struct { volName string podUID types.UID - mounter mount.Interface plugin *gitRepoPlugin } @@ -134,7 +130,7 @@ func (b *gitRepoVolumeBuilder) SetUpAt(dir string) error { } // Wrap EmptyDir, let it do the setup. - wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &b.pod, b.opts, b.mounter) + wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &b.pod, b.opts) if err != nil { return err } @@ -196,7 +192,7 @@ func (c *gitRepoVolumeCleaner) TearDown() error { // TearDownAt simply deletes everything in the directory. func (c *gitRepoVolumeCleaner) TearDownAt(dir string) error { // Wrap EmptyDir, let it do the teardown. - wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID, c.mounter) + wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID) 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 0afba537974..5f915504132 100644 --- a/pkg/volume/git_repo/git_repo_test.go +++ b/pkg/volume/git_repo/git_repo_test.go @@ -27,7 +27,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/empty_dir" ) @@ -120,7 +119,7 @@ func TestPlugin(t *testing.T) { }, } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{RootContext: ""}, mount.New()) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{RootContext: ""}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -142,7 +141,7 @@ func TestPlugin(t *testing.T) { } } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), mount.New()) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) 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 33c4a351557..e5c658dafd6 100644 --- a/pkg/volume/glusterfs/glusterfs.go +++ b/pkg/volume/glusterfs/glusterfs.go @@ -66,7 +66,7 @@ func (plugin *glusterfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode } } -func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { source, _ := plugin.getGlusterVolumeSource(spec) ep_name := source.EndpointsName ns := pod.Namespace @@ -76,7 +76,7 @@ func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ vol return nil, err } glog.V(1).Infof("Glusterfs: endpoints %v", ep) - return plugin.newBuilderInternal(spec, ep, pod, mounter, exec.New()) + return plugin.newBuilderInternal(spec, ep, pod, plugin.host.GetMounter(), exec.New()) } func (plugin *glusterfsPlugin) getGlusterVolumeSource(spec *volume.Spec) (*api.GlusterfsVolumeSource, bool) { @@ -104,8 +104,8 @@ func (plugin *glusterfsPlugin) newBuilderInternal(spec *volume.Spec, ep *api.End exe: exe}, nil } -func (plugin *glusterfsPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID, mounter) +func (plugin *glusterfsPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, plugin.host.GetMounter()) } func (plugin *glusterfsPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/glusterfs/glusterfs_test.go b/pkg/volume/glusterfs/glusterfs_test.go index f603159bd1e..74250e59e8e 100644 --- a/pkg/volume/glusterfs/glusterfs_test.go +++ b/pkg/volume/glusterfs/glusterfs_test.go @@ -210,7 +210,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/host_path/host_path.go b/pkg/volume/host_path/host_path.go index 35c11a48a0f..069c1a4cc8f 100644 --- a/pkg/volume/host_path/host_path.go +++ b/pkg/volume/host_path/host_path.go @@ -23,7 +23,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" ) @@ -89,7 +88,7 @@ func (plugin *hostPathPlugin) GetAccessModes() []api.PersistentVolumeAccessMode } } -func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, _ mount.Interface) (volume.Builder, error) { +func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { if spec.Volume != nil && spec.Volume.HostPath != nil { return &hostPathBuilder{ hostPath: &hostPath{path: spec.Volume.HostPath.Path}, @@ -103,7 +102,7 @@ func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volu } } -func (plugin *hostPathPlugin) NewCleaner(volName string, podUID types.UID, _ mount.Interface) (volume.Cleaner, error) { +func (plugin *hostPathPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { return &hostPathCleaner{&hostPath{""}}, nil } diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 8dde6f4eb83..f1600a36a82 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -156,7 +156,7 @@ func TestPlugin(t *testing.T) { VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/vol1"}}, } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}, nil) + builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -173,7 +173,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Expected success, got: %v", err) } - cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) + cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } @@ -227,7 +227,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/iscsi/iscsi.go b/pkg/volume/iscsi/iscsi.go index ef9dca56fb5..1d67e04385f 100644 --- a/pkg/volume/iscsi/iscsi.go +++ b/pkg/volume/iscsi/iscsi.go @@ -75,9 +75,9 @@ func (plugin *iscsiPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { } } -func (plugin *iscsiPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *iscsiPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, pod.UID, &ISCSIUtil{}, mounter) + return plugin.newBuilderInternal(spec, pod.UID, &ISCSIUtil{}, plugin.host.GetMounter()) } func (plugin *iscsiPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface) (volume.Builder, error) { @@ -110,9 +110,9 @@ func (plugin *iscsiPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UI }, nil } -func (plugin *iscsiPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *iscsiPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &ISCSIUtil{}, mounter) + return plugin.newCleanerInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetMounter()) } func (plugin *iscsiPlugin) newCleanerInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/iscsi/iscsi_test.go b/pkg/volume/iscsi/iscsi_test.go index b2d05cdf8fe..9ee8eef9769 100644 --- a/pkg/volume/iscsi/iscsi_test.go +++ b/pkg/volume/iscsi/iscsi_test.go @@ -244,7 +244,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index dc4352e4f96..d3fdfb3452d 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -79,8 +79,8 @@ func (plugin *nfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { } } -func (plugin *nfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { - return plugin.newBuilderInternal(spec, pod, mounter) +func (plugin *nfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { + return plugin.newBuilderInternal(spec, pod, plugin.host.GetMounter()) } func (plugin *nfsPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface) (volume.Builder, error) { @@ -106,8 +106,8 @@ func (plugin *nfsPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mou }, nil } -func (plugin *nfsPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return plugin.newCleanerInternal(volName, podUID, mounter) +func (plugin *nfsPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return plugin.newCleanerInternal(volName, podUID, plugin.host.GetMounter()) } func (plugin *nfsPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index 186d291664f..594d6fb707c 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -245,7 +245,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/persistent_claim/persistent_claim.go b/pkg/volume/persistent_claim/persistent_claim.go index f2891f057a1..de1659d6e93 100644 --- a/pkg/volume/persistent_claim/persistent_claim.go +++ b/pkg/volume/persistent_claim/persistent_claim.go @@ -18,10 +18,10 @@ package persistent_claim import ( "fmt" + "github.com/golang/glog" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" ) @@ -52,7 +52,7 @@ func (plugin *persistentClaimPlugin) CanSupport(spec *volume.Spec) bool { return spec.Volume != nil && spec.Volume.PersistentVolumeClaim != nil } -func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { claim, err := plugin.host.GetKubeClient().PersistentVolumeClaims(pod.Namespace).Get(spec.Volume.PersistentVolumeClaim.ClaimName) if err != nil { glog.Errorf("Error finding claim: %+v\n", spec.Volume.PersistentVolumeClaim.ClaimName) @@ -79,7 +79,7 @@ func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, return nil, err } - builder, err := plugin.host.NewWrapperBuilder(volume.NewSpecFromPersistentVolume(pv, spec.ReadOnly), pod, opts, mounter) + builder, err := plugin.host.NewWrapperBuilder(volume.NewSpecFromPersistentVolume(pv, spec.ReadOnly), pod, opts) if err != nil { glog.Errorf("Error creating builder for claim: %+v\n", claim.Name) return nil, err @@ -92,6 +92,6 @@ func (plugin *persistentClaimPlugin) IsReadOnly() bool { return plugin.readOnly } -func (plugin *persistentClaimPlugin) NewCleaner(_ string, _ types.UID, _ mount.Interface) (volume.Cleaner, error) { +func (plugin *persistentClaimPlugin) NewCleaner(_ string, _ types.UID) (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 c0843128db7..89ab507ce5d 100644 --- a/pkg/volume/persistent_claim/persistent_claim_test.go +++ b/pkg/volume/persistent_claim/persistent_claim_test.go @@ -249,7 +249,7 @@ func TestNewBuilder(t *testing.T) { } spec := &volume.Spec{Volume: &api.Volume{VolumeSource: item.podVolume}} pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !item.expectedFailure { if err != nil { @@ -304,7 +304,7 @@ func TestNewBuilderClaimNotBound(t *testing.T) { } spec := &volume.Spec{Volume: &api.Volume{VolumeSource: podVolume}} pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) 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 b9d8752165d..dc010ead223 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/errors" + "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/validation" ) @@ -64,12 +65,12 @@ type VolumePlugin interface { // Ownership of the spec pointer in *not* transferred. // - spec: The api.Volume spec // - pod: The enclosing pod - NewBuilder(spec *Spec, podRef *api.Pod, opts VolumeOptions, mounter mount.Interface) (Builder, error) + NewBuilder(spec *Spec, podRef *api.Pod, opts VolumeOptions) (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, mounter mount.Interface) (Cleaner, error) + NewCleaner(name string, podUID types.UID) (Cleaner, error) } // PersistentVolumePlugin is an extended interface of VolumePlugin and is used @@ -125,15 +126,21 @@ 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, pod *api.Pod, opts VolumeOptions, mounter mount.Interface) (Builder, error) + NewWrapperBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions) (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, mounter mount.Interface) (Cleaner, error) + NewWrapperCleaner(spec *Spec, podUID types.UID) (Cleaner, error) - //Get cloud provider from kubelet + // Get cloud provider from kubelet. GetCloudProvider() cloudprovider.Interface + + // Get mounter interface. + GetMounter() mount.Interface + + // Get writer interface for writing data to disk. + GetWriter() io.Writer } // VolumePluginMgr tracks registered plugins. diff --git a/pkg/volume/rbd/rbd.go b/pkg/volume/rbd/rbd.go index 90dece133cd..55b53b0eaa1 100644 --- a/pkg/volume/rbd/rbd.go +++ b/pkg/volume/rbd/rbd.go @@ -73,7 +73,7 @@ func (plugin *rbdPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { } } -func (plugin *rbdPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *rbdPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) { secret := "" source, _ := plugin.getRBDVolumeSource(spec) @@ -95,7 +95,7 @@ func (plugin *rbdPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.Vo } // Inject real implementations here, test through the internal function. - return plugin.newBuilderInternal(spec, pod.UID, &RBDUtil{}, mounter, secret) + return plugin.newBuilderInternal(spec, pod.UID, &RBDUtil{}, plugin.host.GetMounter(), secret) } func (plugin *rbdPlugin) getRBDVolumeSource(spec *volume.Spec) (*api.RBDVolumeSource, bool) { @@ -142,9 +142,9 @@ func (plugin *rbdPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, }, nil } -func (plugin *rbdPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { +func (plugin *rbdPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { // Inject real implementations here, test through the internal function. - return plugin.newCleanerInternal(volName, podUID, &RBDUtil{}, mounter) + return plugin.newCleanerInternal(volName, podUID, &RBDUtil{}, plugin.host.GetMounter()) } func (plugin *rbdPlugin) newCleanerInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface) (volume.Cleaner, error) { diff --git a/pkg/volume/rbd/rbd_test.go b/pkg/volume/rbd/rbd_test.go index 1c007ed0abb..a42f609e185 100644 --- a/pkg/volume/rbd/rbd_test.go +++ b/pkg/volume/rbd/rbd_test.go @@ -201,7 +201,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { // readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes spec := volume.NewSpecFromPersistentVolume(pv, true) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} - builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil) + builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{}) if !builder.IsReadOnly() { t.Errorf("Expected true for builder.IsReadOnly") diff --git a/pkg/volume/secret/secret.go b/pkg/volume/secret/secret.go index 2162a42f011..6591ccfdcc4 100644 --- a/pkg/volume/secret/secret.go +++ b/pkg/volume/secret/secret.go @@ -18,7 +18,6 @@ package secret import ( "fmt" - "io/ioutil" "os" "path" @@ -26,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" + ioutil "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -59,16 +59,16 @@ func (plugin *secretPlugin) CanSupport(spec *volume.Spec) bool { return spec.Volume != nil && spec.Volume.Secret != nil } -func (plugin *secretPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) { +func (plugin *secretPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) { return &secretVolumeBuilder{ - secretVolume: &secretVolume{spec.Name(), pod.UID, plugin, mounter}, + secretVolume: &secretVolume{spec.Name(), pod.UID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter()}, secretName: spec.Volume.Secret.SecretName, pod: *pod, opts: &opts}, nil } -func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) { - return &secretVolumeCleaner{&secretVolume{volName, podUID, plugin, mounter}}, nil +func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { + return &secretVolumeCleaner{&secretVolume{volName, podUID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter()}}, nil } type secretVolume struct { @@ -76,6 +76,7 @@ type secretVolume struct { podUID types.UID plugin *secretPlugin mounter mount.Interface + writer ioutil.Writer } var _ volume.Volume = &secretVolume{} @@ -126,7 +127,7 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error { glog.V(3).Infof("Setting up volume %v for pod %v at %v", b.volName, b.pod.UID, dir) // Wrap EmptyDir, let it do the setup. - wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &b.pod, *b.opts, b.mounter) + wrapped, err := b.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &b.pod, *b.opts) if err != nil { return err } @@ -155,7 +156,7 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error { for name, data := range secret.Data { hostFilePath := path.Join(dir, name) glog.V(3).Infof("Writing secret data %v/%v/%v (%v bytes) to host file %v", b.pod.Namespace, b.secretName, name, len(data), hostFilePath) - err := ioutil.WriteFile(hostFilePath, data, 0444) + err := b.writer.WriteFile(hostFilePath, data, 0444) if err != nil { glog.Errorf("Error writing secret data to host path: %v, %v", hostFilePath, err) return err @@ -195,7 +196,7 @@ func (c *secretVolumeCleaner) TearDownAt(dir string) error { glog.V(3).Infof("Tearing down volume %v for pod %v at %v", c.volName, c.podUID, dir) // Wrap EmptyDir, let it do the teardown. - wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID, c.mounter) + wrapped, err := c.plugin.host.NewWrapperCleaner(wrappedVolumeSpec, c.podUID) if err != nil { return err } diff --git a/pkg/volume/secret/secret_test.go b/pkg/volume/secret/secret_test.go index d652bbf72d0..5ccc6aa7654 100644 --- a/pkg/volume/secret/secret_test.go +++ b/pkg/volume/secret/secret_test.go @@ -85,7 +85,7 @@ func TestPlugin(t *testing.T) { } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -140,14 +140,14 @@ func TestPluginIdempotent(t *testing.T) { podVolumeDir := fmt.Sprintf("%v/pods/test_pod_uid2/volumes/kubernetes.io~secret/test_volume_name", rootDir) podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid2/plugins/kubernetes.io~secret/test_volume_name", rootDir) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} - mounter := &mount.FakeMounter{} + mounter := host.GetMounter().(*mount.FakeMounter) mounter.MountPoints = []mount.MountPoint{ { Path: podVolumeDir, }, } util.SetReady(podMetadataDir) - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, mounter) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -199,7 +199,7 @@ func TestPluginReboot(t *testing.T) { } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} - builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) + builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } @@ -275,7 +275,7 @@ func doTestSecretDataInVolume(volumePath string, secret api.Secret, t *testing.T } func doTestCleanAndTeardown(plugin volume.VolumePlugin, podUID types.UID, testVolumeName, volumePath string, t *testing.T) { - cleaner, err := plugin.NewCleaner(testVolumeName, podUID, mount.New()) + cleaner, err := plugin.NewCleaner(testVolumeName, podUID) 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 39eb1f86422..9244eeda6ab 100644 --- a/pkg/volume/testing.go +++ b/pkg/volume/testing.go @@ -26,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" ) @@ -35,10 +36,14 @@ type fakeVolumeHost struct { kubeClient client.Interface pluginMgr VolumePluginMgr cloud cloudprovider.Interface + mounter mount.Interface + writer io.Writer } func NewFakeVolumeHost(rootDir string, kubeClient client.Interface, plugins []VolumePlugin) *fakeVolumeHost { host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: nil} + host.mounter = &mount.FakeMounter{} + host.writer = &io.StdWriter{} host.pluginMgr.InitPlugins(plugins, host) return host } @@ -63,20 +68,28 @@ func (f *fakeVolumeHost) GetCloudProvider() cloudprovider.Interface { return f.cloud } -func (f *fakeVolumeHost) NewWrapperBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions, mounter mount.Interface) (Builder, error) { - plug, err := f.pluginMgr.FindPluginBySpec(spec) - if err != nil { - return nil, err - } - return plug.NewBuilder(spec, pod, opts, mounter) +func (f *fakeVolumeHost) GetMounter() mount.Interface { + return f.mounter } -func (f *fakeVolumeHost) NewWrapperCleaner(spec *Spec, podUID types.UID, mounter mount.Interface) (Cleaner, error) { +func (f *fakeVolumeHost) GetWriter() io.Writer { + return f.writer +} + +func (f *fakeVolumeHost) NewWrapperBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions) (Builder, error) { plug, err := f.pluginMgr.FindPluginBySpec(spec) if err != nil { return nil, err } - return plug.NewCleaner(spec.Name(), podUID, mounter) + return plug.NewBuilder(spec, pod, opts) +} + +func (f *fakeVolumeHost) NewWrapperCleaner(spec *Spec, podUID types.UID) (Cleaner, error) { + plug, err := f.pluginMgr.FindPluginBySpec(spec) + if err != nil { + return nil, err + } + return plug.NewCleaner(spec.Name(), podUID) } func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin { @@ -117,11 +130,11 @@ func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool { return true } -func (plugin *FakeVolumePlugin) NewBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions, mounter mount.Interface) (Builder, error) { +func (plugin *FakeVolumePlugin) NewBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions) (Builder, error) { return &FakeVolume{pod.UID, spec.Name(), plugin}, nil } -func (plugin *FakeVolumePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (Cleaner, error) { +func (plugin *FakeVolumePlugin) NewCleaner(volName string, podUID types.UID) (Cleaner, error) { return &FakeVolume{podUID, volName, plugin}, nil }