Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
1725c23e
Commit
1725c23e
authored
Mar 07, 2015
by
Tim Hockin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement volume plugin wrappers
Convert git_repo and secret into wrappers around empty_dir.
parent
bdc1981e
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
279 additions
and
131 deletions
+279
-131
empty_dir.go
pkg/kubelet/volume/empty_dir/empty_dir.go
+49
-35
empty_dir_test.go
pkg/kubelet/volume/empty_dir/empty_dir_test.go
+1
-1
gce_pd.go
pkg/kubelet/volume/gce_pd/gce_pd.go
+26
-16
gce_pd_test.go
pkg/kubelet/volume/gce_pd/gce_pd_test.go
+3
-3
git_repo.go
pkg/kubelet/volume/git_repo/git_repo.go
+35
-18
git_repo_test.go
pkg/kubelet/volume/git_repo/git_repo_test.go
+2
-1
host_path.go
pkg/kubelet/volume/host_path/host_path.go
+12
-0
host_path_test.go
pkg/kubelet/volume/host_path/host_path_test.go
+2
-2
plugins.go
pkg/kubelet/volume/plugins.go
+11
-0
secret.go
pkg/kubelet/volume/secret/secret.go
+31
-17
secret_test.go
pkg/kubelet/volume/secret/secret_test.go
+4
-2
testing.go
pkg/kubelet/volume/testing.go
+45
-14
volume.go
pkg/kubelet/volume/volume.go
+12
-4
volumes.go
pkg/kubelet/volumes.go
+46
-18
No files found.
pkg/kubelet/volume/empty_dir/empty_dir.go
View file @
1725c23e
...
...
@@ -29,11 +29,21 @@ import (
// This is the primary entrypoint for volume plugins.
func
ProbeVolumePlugins
()
[]
volume
.
Plugin
{
return
[]
volume
.
Plugin
{
&
emptyDirPlugin
{
nil
,
false
},
&
emptyDirPlugin
{
nil
,
true
}}
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
.
Plugin
{
return
[]
volume
.
Plugin
{
&
emptyDirPlugin
{
nil
,
mounter
,
false
},
&
emptyDirPlugin
{
nil
,
mounter
,
true
},
}
}
type
emptyDirPlugin
struct
{
host
volume
.
Host
mounter
mount
.
Interface
legacyMode
bool
// if set, plugin answers to the legacy name
}
...
...
@@ -72,7 +82,7 @@ func (plugin *emptyDirPlugin) CanSupport(spec *api.Volume) bool {
func
(
plugin
*
emptyDirPlugin
)
NewBuilder
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
volume
.
Builder
,
error
)
{
// Inject real implementations here, test through the internal function.
return
plugin
.
newBuilderInternal
(
spec
,
podRef
,
mount
.
New
()
,
&
realMediumer
{})
return
plugin
.
newBuilderInternal
(
spec
,
podRef
,
plugin
.
mounter
,
&
realMediumer
{})
}
func
(
plugin
*
emptyDirPlugin
)
newBuilderInternal
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
,
mounter
mount
.
Interface
,
mediumer
mediumer
)
(
volume
.
Builder
,
error
)
{
...
...
@@ -88,8 +98,8 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.O
podUID
:
podRef
.
UID
,
volName
:
spec
.
Name
,
medium
:
medium
,
mediumer
:
mediumer
,
mounter
:
mounter
,
mediumer
:
mediumer
,
plugin
:
plugin
,
legacyMode
:
false
,
},
nil
...
...
@@ -97,7 +107,7 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.O
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
,
mount
.
New
()
,
&
realMediumer
{})
return
plugin
.
newCleanerInternal
(
volName
,
podUID
,
plugin
.
mounter
,
&
realMediumer
{})
}
func
(
plugin
*
emptyDirPlugin
)
newCleanerInternal
(
volName
string
,
podUID
types
.
UID
,
mounter
mount
.
Interface
,
mediumer
mediumer
)
(
volume
.
Cleaner
,
error
)
{
...
...
@@ -114,17 +124,6 @@ func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UI
plugin
:
plugin
,
legacyMode
:
legacy
,
}
// Figure out the medium.
if
medium
,
err
:=
mediumer
.
GetMedium
(
ed
.
GetPath
());
err
!=
nil
{
return
nil
,
err
}
else
{
switch
medium
{
case
mediumMemory
:
ed
.
medium
=
api
.
StorageTypeMemory
default
:
// assume StorageTypeDefault
}
}
return
ed
,
nil
}
...
...
@@ -154,37 +153,42 @@ type emptyDir struct {
// SetUp creates new directory.
func
(
ed
*
emptyDir
)
SetUp
()
error
{
return
ed
.
SetUpAt
(
ed
.
GetPath
())
}
// SetUpAt creates new directory.
func
(
ed
*
emptyDir
)
SetUpAt
(
dir
string
)
error
{
if
ed
.
legacyMode
{
return
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
switch
ed
.
medium
{
case
api
.
StorageTypeDefault
:
return
ed
.
setupDefault
()
return
ed
.
setupDefault
(
dir
)
case
api
.
StorageTypeMemory
:
return
ed
.
setupTmpfs
()
return
ed
.
setupTmpfs
(
dir
)
default
:
return
fmt
.
Errorf
(
"unknown storage medium %q"
,
ed
.
medium
)
}
}
func
(
ed
*
emptyDir
)
setupDefault
()
error
{
return
os
.
MkdirAll
(
ed
.
GetPath
()
,
0750
)
func
(
ed
*
emptyDir
)
setupDefault
(
dir
string
)
error
{
return
os
.
MkdirAll
(
dir
,
0750
)
}
func
(
ed
*
emptyDir
)
setupTmpfs
()
error
{
func
(
ed
*
emptyDir
)
setupTmpfs
(
dir
string
)
error
{
if
ed
.
mounter
==
nil
{
return
fmt
.
Errorf
(
"memory storage requested, but mounter is nil"
)
}
if
err
:=
os
.
MkdirAll
(
ed
.
GetPath
()
,
0750
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
dir
,
0750
);
err
!=
nil
{
return
err
}
// Make SetUp idempotent.
if
medium
,
err
:=
ed
.
mediumer
.
GetMedium
(
ed
.
GetPath
()
);
err
!=
nil
{
if
medium
,
err
:=
ed
.
mediumer
.
GetMedium
(
dir
);
err
!=
nil
{
return
err
}
else
if
medium
==
mediumMemory
{
return
nil
// current state is what we expect
}
return
ed
.
mounter
.
Mount
(
"tmpfs"
,
ed
.
GetPath
()
,
"tmpfs"
,
0
,
""
)
return
ed
.
mounter
.
Mount
(
"tmpfs"
,
dir
,
"tmpfs"
,
0
,
""
)
}
func
(
ed
*
emptyDir
)
GetPath
()
string
{
...
...
@@ -197,18 +201,28 @@ func (ed *emptyDir) GetPath() string {
// TearDown simply discards everything in the directory.
func
(
ed
*
emptyDir
)
TearDown
()
error
{
switch
ed
.
medium
{
case
api
.
StorageTypeDefault
:
return
ed
.
teardownDefault
()
case
api
.
StorageTypeMemory
:
return
ed
.
teardownTmpfs
()
default
:
return
fmt
.
Errorf
(
"unknown storage medium %q"
,
ed
.
medium
)
return
ed
.
TearDownAt
(
ed
.
GetPath
())
}
// TearDownAt simply discards everything in the directory.
func
(
ed
*
emptyDir
)
TearDownAt
(
dir
string
)
error
{
// Figure out the medium.
if
medium
,
err
:=
ed
.
mediumer
.
GetMedium
(
dir
);
err
!=
nil
{
return
err
}
else
{
switch
medium
{
case
mediumMemory
:
ed
.
medium
=
api
.
StorageTypeMemory
return
ed
.
teardownTmpfs
(
dir
)
default
:
// assume StorageTypeDefault
return
ed
.
teardownDefault
(
dir
)
}
}
}
func
(
ed
*
emptyDir
)
teardownDefault
()
error
{
tmpDir
,
err
:=
volume
.
RenameDirectory
(
ed
.
GetPath
()
,
ed
.
volName
+
".deleting~"
)
func
(
ed
*
emptyDir
)
teardownDefault
(
dir
string
)
error
{
tmpDir
,
err
:=
volume
.
RenameDirectory
(
dir
,
ed
.
volName
+
".deleting~"
)
if
err
!=
nil
{
return
err
}
...
...
@@ -219,14 +233,14 @@ func (ed *emptyDir) teardownDefault() error {
return
nil
}
func
(
ed
*
emptyDir
)
teardownTmpfs
()
error
{
func
(
ed
*
emptyDir
)
teardownTmpfs
(
dir
string
)
error
{
if
ed
.
mounter
==
nil
{
return
fmt
.
Errorf
(
"memory storage requested, but mounter is nil"
)
}
if
err
:=
ed
.
mounter
.
Unmount
(
ed
.
GetPath
()
,
0
);
err
!=
nil
{
if
err
:=
ed
.
mounter
.
Unmount
(
dir
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
os
.
RemoveAll
(
ed
.
GetPath
()
);
err
!=
nil
{
if
err
:=
os
.
RemoveAll
(
dir
);
err
!=
nil
{
return
err
}
return
nil
...
...
pkg/kubelet/volume/empty_dir/empty_dir_test.go
View file @
1725c23e
...
...
@@ -33,7 +33,7 @@ const basePath = "/tmp/fake"
// Construct an instance of a plugin, by name.
func
makePluginUnderTest
(
t
*
testing
.
T
,
plugName
string
)
volume
.
Plugin
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
basePath
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
basePath
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
plugName
)
if
err
!=
nil
{
...
...
pkg/kubelet/volume/gce_pd/gce_pd.go
View file @
1725c23e
...
...
@@ -165,13 +165,18 @@ func detachDiskLogError(pd *gcePersistentDisk) {
// SetUp attaches the disk and bind mounts to the volume path.
func
(
pd
*
gcePersistentDisk
)
SetUp
()
error
{
return
pd
.
SetUpAt
(
pd
.
GetPath
())
}
// SetUpAt attaches the disk and bind mounts to the volume path.
func
(
pd
*
gcePersistentDisk
)
SetUpAt
(
dir
string
)
error
{
if
pd
.
legacyMode
{
return
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
// TODO: handle failed mounts here.
mountpoint
,
err
:=
mount
.
IsMountPoint
(
pd
.
GetPath
()
)
glog
.
V
(
4
)
.
Infof
(
"PersistentDisk set up: %s %v %v"
,
pd
.
GetPath
()
,
mountpoint
,
err
)
mountpoint
,
err
:=
mount
.
IsMountPoint
(
dir
)
glog
.
V
(
4
)
.
Infof
(
"PersistentDisk set up: %s %v %v"
,
dir
,
mountpoint
,
err
)
if
err
!=
nil
&&
!
os
.
IsNotExist
(
err
)
{
return
err
}
...
...
@@ -189,38 +194,37 @@ func (pd *gcePersistentDisk) SetUp() error {
flags
=
mount
.
FlagReadOnly
}
volPath
:=
pd
.
GetPath
()
if
err
:=
os
.
MkdirAll
(
volPath
,
0750
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
dir
,
0750
);
err
!=
nil
{
// TODO: we should really eject the attach/detach out into its own control loop.
detachDiskLogError
(
pd
)
return
err
}
// Perform a bind mount to the full path to allow duplicate mounts of the same PD.
err
=
pd
.
mounter
.
Mount
(
globalPDPath
,
pd
.
GetPath
()
,
""
,
mount
.
FlagBind
|
flags
,
""
)
err
=
pd
.
mounter
.
Mount
(
globalPDPath
,
dir
,
""
,
mount
.
FlagBind
|
flags
,
""
)
if
err
!=
nil
{
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
pd
.
GetPath
()
)
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
dir
)
if
mntErr
!=
nil
{
glog
.
Errorf
(
"isMountpoint check failed: %v"
,
mntErr
)
return
err
}
if
mountpoint
{
if
mntErr
=
pd
.
mounter
.
Unmount
(
pd
.
GetPath
()
,
0
);
mntErr
!=
nil
{
if
mntErr
=
pd
.
mounter
.
Unmount
(
dir
,
0
);
mntErr
!=
nil
{
glog
.
Errorf
(
"Failed to unmount: %v"
,
mntErr
)
return
err
}
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
pd
.
GetPath
()
)
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
dir
)
if
mntErr
!=
nil
{
glog
.
Errorf
(
"isMountpoint check failed: %v"
,
mntErr
)
return
err
}
if
mountpoint
{
// This is very odd, we don't expect it. We'll try again next sync loop.
glog
.
Errorf
(
"%s is still mounted, despite call to unmount(). Will try again next sync loop."
,
pd
.
GetPath
()
)
glog
.
Errorf
(
"%s is still mounted, despite call to unmount(). Will try again next sync loop."
,
dir
)
return
err
}
}
os
.
Remove
(
pd
.
GetPath
()
)
os
.
Remove
(
dir
)
// TODO: we should really eject the attach/detach out into its own control loop.
detachDiskLogError
(
pd
)
return
err
...
...
@@ -244,20 +248,26 @@ func (pd *gcePersistentDisk) GetPath() string {
// Unmounts the bind mount, and detaches the disk only if the PD
// resource was the last reference to that disk on the kubelet.
func
(
pd
*
gcePersistentDisk
)
TearDown
()
error
{
mountpoint
,
err
:=
mount
.
IsMountPoint
(
pd
.
GetPath
())
return
pd
.
TearDownAt
(
pd
.
GetPath
())
}
// Unmounts the bind mount, and detaches the disk only if the PD
// resource was the last reference to that disk on the kubelet.
func
(
pd
*
gcePersistentDisk
)
TearDownAt
(
dir
string
)
error
{
mountpoint
,
err
:=
mount
.
IsMountPoint
(
dir
)
if
err
!=
nil
{
return
err
}
if
!
mountpoint
{
return
os
.
Remove
(
pd
.
GetPath
()
)
return
os
.
Remove
(
dir
)
}
refs
,
err
:=
mount
.
GetMountRefs
(
pd
.
mounter
,
pd
.
GetPath
()
)
refs
,
err
:=
mount
.
GetMountRefs
(
pd
.
mounter
,
dir
)
if
err
!=
nil
{
return
err
}
// Unmount the bind-mount inside this pod
if
err
:=
pd
.
mounter
.
Unmount
(
pd
.
GetPath
()
,
0
);
err
!=
nil
{
if
err
:=
pd
.
mounter
.
Unmount
(
dir
,
0
);
err
!=
nil
{
return
err
}
// If len(refs) is 1, then all bind mounts have been removed, and the
...
...
@@ -269,13 +279,13 @@ func (pd *gcePersistentDisk) TearDown() error {
return
err
}
}
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
pd
.
GetPath
()
)
mountpoint
,
mntErr
:=
mount
.
IsMountPoint
(
dir
)
if
mntErr
!=
nil
{
glog
.
Errorf
(
"isMountpoint check failed: %v"
,
mntErr
)
return
err
}
if
!
mountpoint
{
if
err
:=
os
.
Remove
(
pd
.
GetPath
()
);
err
!=
nil
{
if
err
:=
os
.
Remove
(
dir
);
err
!=
nil
{
return
err
}
}
...
...
pkg/kubelet/volume/gce_pd/gce_pd_test.go
View file @
1725c23e
...
...
@@ -28,7 +28,7 @@ import (
func
TestCanSupport
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
"/tmp/fake"
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/gce-pd"
)
if
err
!=
nil
{
...
...
@@ -66,7 +66,7 @@ func (fake *fakePDManager) DetachDisk(pd *gcePersistentDisk) error {
func
TestPlugin
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
"/tmp/fake"
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/gce-pd"
)
if
err
!=
nil
{
...
...
@@ -132,7 +132,7 @@ func TestPlugin(t *testing.T) {
func
TestPluginLegacy
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
"/tmp/fake"
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"gce-pd"
)
if
err
!=
nil
{
...
...
pkg/kubelet/volume/git_repo/git_repo.go
View file @
1725c23e
...
...
@@ -75,7 +75,7 @@ func (plugin *gitRepoPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectRefe
return
nil
,
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
return
&
gitRepo
{
pod
UID
:
podRef
.
UID
,
pod
Ref
:
*
podRef
,
volName
:
spec
.
Name
,
source
:
spec
.
GitRepo
.
Repository
,
revision
:
spec
.
GitRepo
.
Revision
,
...
...
@@ -91,7 +91,7 @@ func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID) (volum
legacy
=
true
}
return
&
gitRepo
{
pod
UID
:
podUID
,
pod
Ref
:
api
.
ObjectReference
{
UID
:
podUID
}
,
volName
:
volName
,
plugin
:
plugin
,
legacyMode
:
legacy
,
...
...
@@ -102,7 +102,7 @@ func (plugin *gitRepoPlugin) NewCleaner(volName string, podUID types.UID) (volum
// These do not persist beyond the lifetime of a pod.
type
gitRepo
struct
{
volName
string
pod
UID
types
.
UID
pod
Ref
api
.
ObjectReference
source
string
revision
string
exec
exec
.
Interface
...
...
@@ -112,6 +112,17 @@ type gitRepo struct {
// SetUp creates new directory and clones a git repo.
func
(
gr
*
gitRepo
)
SetUp
()
error
{
return
gr
.
SetUpAt
(
gr
.
GetPath
())
}
// This is the spec for the volume that this plugin wraps.
var
wrappedVolumeSpec
=
&
api
.
Volume
{
Name
:
"not-used"
,
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}},
}
// SetUpAt creates new directory and clones a git repo.
func
(
gr
*
gitRepo
)
SetUpAt
(
dir
string
)
error
{
if
gr
.
isReady
()
{
return
nil
}
...
...
@@ -119,16 +130,20 @@ func (gr *gitRepo) SetUp() error {
return
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
volPath
:=
gr
.
GetPath
()
if
err
:=
os
.
MkdirAll
(
volPath
,
0750
);
err
!=
nil
{
// Wrap EmptyDir, let it do the setup.
wrapped
,
err
:=
gr
.
plugin
.
host
.
NewWrapperBuilder
(
wrappedVolumeSpec
,
&
gr
.
podRef
)
if
err
!=
nil
{
return
err
}
if
err
:=
wrapped
.
SetUpAt
(
dir
);
err
!=
nil
{
return
err
}
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"clone"
,
gr
.
source
},
gr
.
GetPath
()
);
err
!=
nil
{
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"clone"
,
gr
.
source
},
dir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to exec 'git clone %s': %s: %v"
,
gr
.
source
,
output
,
err
)
}
files
,
err
:=
ioutil
.
ReadDir
(
gr
.
GetPath
()
)
files
,
err
:=
ioutil
.
ReadDir
(
dir
)
if
err
!=
nil
{
return
err
}
...
...
@@ -141,11 +156,11 @@ func (gr *gitRepo) SetUp() error {
return
nil
}
dir
:=
path
.
Join
(
gr
.
GetPath
()
,
files
[
0
]
.
Name
())
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"checkout"
,
gr
.
revision
},
dir
);
err
!=
nil
{
subdir
:=
path
.
Join
(
dir
,
files
[
0
]
.
Name
())
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"checkout"
,
gr
.
revision
},
sub
dir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to exec 'git checkout %s': %s: %v"
,
gr
.
revision
,
output
,
err
)
}
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"reset"
,
"--hard"
},
dir
);
err
!=
nil
{
if
output
,
err
:=
gr
.
execCommand
(
"git"
,
[]
string
{
"reset"
,
"--hard"
},
sub
dir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to exec 'git reset --hard': %s: %v"
,
output
,
err
)
}
...
...
@@ -154,7 +169,7 @@ func (gr *gitRepo) SetUp() error {
}
func
(
gr
*
gitRepo
)
getMetaDir
()
string
{
return
path
.
Join
(
gr
.
plugin
.
host
.
GetPodPluginDir
(
gr
.
podUID
,
volume
.
EscapePluginName
(
gitRepoPluginName
)),
gr
.
volName
)
return
path
.
Join
(
gr
.
plugin
.
host
.
GetPodPluginDir
(
gr
.
pod
Ref
.
UID
,
volume
.
EscapePluginName
(
gitRepoPluginName
)),
gr
.
volName
)
}
func
(
gr
*
gitRepo
)
isReady
()
bool
{
...
...
@@ -197,18 +212,20 @@ func (gr *gitRepo) GetPath() string {
if
gr
.
legacyMode
{
name
=
gitRepoPluginLegacyName
}
return
gr
.
plugin
.
host
.
GetPodVolumeDir
(
gr
.
podUID
,
volume
.
EscapePluginName
(
name
),
gr
.
volName
)
return
gr
.
plugin
.
host
.
GetPodVolumeDir
(
gr
.
pod
Ref
.
UID
,
volume
.
EscapePluginName
(
name
),
gr
.
volName
)
}
// TearDown simply deletes everything in the directory.
func
(
gr
*
gitRepo
)
TearDown
()
error
{
tmpDir
,
err
:=
volume
.
RenameDirectory
(
gr
.
GetPath
(),
gr
.
volName
+
".deleting~"
)
if
err
!=
nil
{
return
err
}
err
=
os
.
RemoveAll
(
tmpDir
)
return
gr
.
TearDownAt
(
gr
.
GetPath
())
}
// 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
)
if
err
!=
nil
{
return
err
}
return
nil
return
wrapped
.
TearDownAt
(
dir
)
}
pkg/kubelet/volume/git_repo/git_repo_test.go
View file @
1725c23e
...
...
@@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/empty_dir"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
)
...
...
@@ -35,7 +36,7 @@ func newTestHost(t *testing.T) volume.Host {
if
err
!=
nil
{
t
.
Fatalf
(
"can't make a temp rootdir: %v"
,
err
)
}
return
&
volume
.
FakeHost
{
tempDir
,
nil
}
return
volume
.
NewFakeHost
(
tempDir
,
nil
,
empty_dir
.
ProbeVolumePlugins
())
}
func
TestCanSupport
(
t
*
testing
.
T
)
{
...
...
pkg/kubelet/volume/host_path/host_path.go
View file @
1725c23e
...
...
@@ -17,6 +17,8 @@ limitations under the License.
package
host_path
import
(
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
...
...
@@ -71,6 +73,11 @@ func (hp *hostPath) SetUp() error {
return
nil
}
// SetUpAt does not make sense for host paths - probably programmer error.
func
(
hp
*
hostPath
)
SetUpAt
(
dir
string
)
error
{
return
fmt
.
Errorf
(
"SetUpAt() does not make sense for host paths"
)
}
func
(
hp
*
hostPath
)
GetPath
()
string
{
return
hp
.
path
}
...
...
@@ -79,3 +86,8 @@ func (hp *hostPath) GetPath() string {
func
(
hp
*
hostPath
)
TearDown
()
error
{
return
nil
}
// TearDownAt does not make sense for host paths - probably programmer error.
func
(
hp
*
hostPath
)
TearDownAt
(
dir
string
)
error
{
return
fmt
.
Errorf
(
"TearDownAt() does not make sense for host paths"
)
}
pkg/kubelet/volume/host_path/host_path_test.go
View file @
1725c23e
...
...
@@ -26,7 +26,7 @@ import (
func
TestCanSupport
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"fake"
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
"fake"
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/host-path"
)
if
err
!=
nil
{
...
...
@@ -45,7 +45,7 @@ func TestCanSupport(t *testing.T) {
func
TestPlugin
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"fake"
,
nil
}
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
volume
.
NewFakeHost
(
"fake"
,
nil
,
nil
)
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/host-path"
)
if
err
!=
nil
{
...
...
pkg/kubelet/volume/plugins.go
View file @
1725c23e
...
...
@@ -80,6 +80,17 @@ type Host interface {
// GetKubeClient returns a client interface
GetKubeClient
()
client
.
Interface
// NewWrapperBuilder finds an appropriate plugin with which to handle
// 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
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
Builder
,
error
)
// NewWrapperCleaner finds an appropriate plugin with which to handle
// the provided spec. See comments on NewWrapperBuilder for more
// context.
NewWrapperCleaner
(
spec
*
api
.
Volume
,
podUID
types
.
UID
)
(
Cleaner
,
error
)
}
// PluginMgr tracks registered plugins.
...
...
pkg/kubelet/volume/secret/secret.go
View file @
1725c23e
...
...
@@ -19,7 +19,6 @@ package secret
import
(
"fmt"
"io/ioutil"
"os"
"path"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
...
...
@@ -63,7 +62,7 @@ func (plugin *secretPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectRefer
}
func
(
plugin
*
secretPlugin
)
newBuilderInternal
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
volume
.
Builder
,
error
)
{
return
&
secretVolume
{
spec
.
Name
,
podRef
,
plugin
,
&
spec
.
Secret
.
Target
},
nil
return
&
secretVolume
{
spec
.
Name
,
*
podRef
,
plugin
,
spec
.
Secret
.
Target
},
nil
}
func
(
plugin
*
secretPlugin
)
NewCleaner
(
volName
string
,
podUID
types
.
UID
)
(
volume
.
Cleaner
,
error
)
{
...
...
@@ -71,26 +70,39 @@ func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume
}
func
(
plugin
*
secretPlugin
)
newCleanerInternal
(
volName
string
,
podUID
types
.
UID
)
(
volume
.
Cleaner
,
error
)
{
return
&
secretVolume
{
volName
,
&
api
.
ObjectReference
{
UID
:
podUID
},
plugin
,
nil
},
nil
return
&
secretVolume
{
volName
,
api
.
ObjectReference
{
UID
:
podUID
},
plugin
,
api
.
ObjectReference
{}
},
nil
}
// secretVolume handles retrieving secrets from the API server
// and placing them into the volume on the host.
type
secretVolume
struct
{
volName
string
podRef
*
api
.
ObjectReference
podRef
api
.
ObjectReference
plugin
*
secretPlugin
secretRef
*
api
.
ObjectReference
secretRef
api
.
ObjectReference
}
func
(
sv
*
secretVolume
)
SetUp
()
error
{
// TODO: explore tmpfs for secret volumes
hostPath
:=
sv
.
GetPath
()
glog
.
V
(
3
)
.
Infof
(
"Setting up volume %v for pod %v at %v"
,
sv
.
volName
,
sv
.
podRef
.
UID
,
hostPath
)
err
:=
os
.
MkdirAll
(
hostPath
,
0777
)
return
sv
.
SetUpAt
(
sv
.
GetPath
())
}
// This is the spec for the volume that this plugin wraps.
var
wrappedVolumeSpec
=
&
api
.
Volume
{
Name
:
"not-used"
,
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{
Medium
:
api
.
StorageTypeMemory
}},
}
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
)
if
err
!=
nil
{
return
err
}
if
err
:=
wrapped
.
SetUpAt
(
dir
);
err
!=
nil
{
return
err
}
kubeClient
:=
sv
.
plugin
.
host
.
GetKubeClient
()
if
kubeClient
==
nil
{
...
...
@@ -104,7 +116,7 @@ func (sv *secretVolume) SetUp() error {
}
for
name
,
data
:=
range
secret
.
Data
{
hostFilePath
:=
path
.
Join
(
hostPath
,
name
)
hostFilePath
:=
path
.
Join
(
dir
,
name
)
err
:=
ioutil
.
WriteFile
(
hostFilePath
,
data
,
0777
)
if
err
!=
nil
{
glog
.
Errorf
(
"Error writing secret data to host path: %v, %v"
,
hostFilePath
,
err
)
...
...
@@ -120,14 +132,16 @@ func (sv *secretVolume) GetPath() string {
}
func
(
sv
*
secretVolume
)
TearDown
()
error
{
glog
.
V
(
3
)
.
Infof
(
"Tearing down volume %v for pod %v at %v"
,
sv
.
volName
,
sv
.
podRef
.
UID
,
sv
.
GetPath
())
tmpDir
,
err
:=
volume
.
RenameDirectory
(
sv
.
GetPath
(),
sv
.
volName
+
".deleting~"
)
if
err
!=
nil
{
return
err
}
err
=
os
.
RemoveAll
(
tmpDir
)
return
sv
.
TearDownAt
(
sv
.
GetPath
())
}
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
)
if
err
!=
nil
{
return
err
}
return
nil
return
wrapped
.
TearDownAt
(
dir
)
}
pkg/kubelet/volume/secret/secret_test.go
View file @
1725c23e
...
...
@@ -27,16 +27,18 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/empty_dir"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
)
func
newTestHost
(
t
*
testing
.
T
,
fakeKubeC
lient
client
.
Interface
)
volume
.
Host
{
func
newTestHost
(
t
*
testing
.
T
,
c
lient
client
.
Interface
)
volume
.
Host
{
tempDir
,
err
:=
ioutil
.
TempDir
(
"/tmp"
,
"secret_volume_test."
)
if
err
!=
nil
{
t
.
Fatalf
(
"can't make a temp rootdir: %v"
,
err
)
}
return
&
volume
.
FakeHost
{
tempDir
,
fakeKubeClient
}
return
volume
.
NewFakeHost
(
tempDir
,
client
,
empty_dir
.
ProbeVolumePluginsWithMounter
(
&
mount
.
FakeMounter
{}))
}
func
TestCanSupport
(
t
*
testing
.
T
)
{
...
...
pkg/kubelet/volume/testing.go
View file @
1725c23e
...
...
@@ -25,26 +25,49 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
)
// FakeHost is useful for testing volume plugins.
type
FakeHost
struct
{
RootDir
string
KubeClient
client
.
Interface
// fakeHost is useful for testing volume plugins.
type
fakeHost
struct
{
rootDir
string
kubeClient
client
.
Interface
pluginMgr
PluginMgr
}
func
(
f
*
FakeHost
)
GetPluginDir
(
podUID
string
)
string
{
return
path
.
Join
(
f
.
RootDir
,
"plugins"
,
podUID
)
func
NewFakeHost
(
rootDir
string
,
kubeClient
client
.
Interface
,
plugins
[]
Plugin
)
*
fakeHost
{
host
:=
&
fakeHost
{
rootDir
:
rootDir
,
kubeClient
:
kubeClient
}
host
.
pluginMgr
.
InitPlugins
(
plugins
,
host
)
return
host
}
func
(
f
*
FakeHost
)
GetPodVolumeDir
(
podUID
types
.
UID
,
pluginName
,
volumeName
string
)
string
{
return
path
.
Join
(
f
.
RootDir
,
"pods"
,
string
(
podUID
),
"volumes"
,
pluginName
,
volumeName
)
func
(
f
*
fakeHost
)
GetPluginDir
(
podUID
string
)
string
{
return
path
.
Join
(
f
.
rootDir
,
"plugins"
,
podUID
)
}
func
(
f
*
FakeHost
)
GetPodPluginDir
(
podUID
types
.
UID
,
plugin
Name
string
)
string
{
return
path
.
Join
(
f
.
RootDir
,
"pods"
,
string
(
podUID
),
"plugins"
,
plugin
Name
)
func
(
f
*
fakeHost
)
GetPodVolumeDir
(
podUID
types
.
UID
,
pluginName
,
volume
Name
string
)
string
{
return
path
.
Join
(
f
.
rootDir
,
"pods"
,
string
(
podUID
),
"volumes"
,
pluginName
,
volume
Name
)
}
func
(
f
*
FakeHost
)
GetKubeClient
()
client
.
Interface
{
return
f
.
KubeClient
func
(
f
*
fakeHost
)
GetPodPluginDir
(
podUID
types
.
UID
,
pluginName
string
)
string
{
return
path
.
Join
(
f
.
rootDir
,
"pods"
,
string
(
podUID
),
"plugins"
,
pluginName
)
}
func
(
f
*
fakeHost
)
GetKubeClient
()
client
.
Interface
{
return
f
.
kubeClient
}
func
(
f
*
fakeHost
)
NewWrapperBuilder
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
Builder
,
error
)
{
plug
,
err
:=
f
.
pluginMgr
.
FindPluginBySpec
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
return
plug
.
NewBuilder
(
spec
,
podRef
)
}
func
(
f
*
fakeHost
)
NewWrapperCleaner
(
spec
*
api
.
Volume
,
podUID
types
.
UID
)
(
Cleaner
,
error
)
{
plug
,
err
:=
f
.
pluginMgr
.
FindPluginBySpec
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
return
plug
.
NewCleaner
(
spec
.
Name
,
podUID
)
}
// FakePlugin is useful for for testing. It tries to be a fully compliant
...
...
@@ -86,7 +109,11 @@ type FakeVolume struct {
}
func
(
fv
*
FakeVolume
)
SetUp
()
error
{
return
os
.
MkdirAll
(
fv
.
GetPath
(),
0750
)
return
fv
.
SetUpAt
(
fv
.
GetPath
())
}
func
(
fv
*
FakeVolume
)
SetUpAt
(
dir
string
)
error
{
return
os
.
MkdirAll
(
dir
,
0750
)
}
func
(
fv
*
FakeVolume
)
GetPath
()
string
{
...
...
@@ -94,5 +121,9 @@ func (fv *FakeVolume) GetPath() string {
}
func
(
fv
*
FakeVolume
)
TearDown
()
error
{
return
os
.
RemoveAll
(
fv
.
GetPath
())
return
fv
.
TearDownAt
(
fv
.
GetPath
())
}
func
(
fv
*
FakeVolume
)
TearDownAt
(
dir
string
)
error
{
return
os
.
RemoveAll
(
dir
)
}
pkg/kubelet/volume/volume.go
View file @
1725c23e
...
...
@@ -33,17 +33,25 @@ type Interface interface {
type
Builder
interface
{
// Uses Interface to provide the path for Docker binds.
Interface
// SetUp prepares and mounts/unpacks the volume to a
directory path.
//
This may be called more than once, so implementations must be
// idempotent.
// SetUp prepares and mounts/unpacks the volume to a
self-determined
//
directory path. This may be called more than once, so
// i
mplementations must be i
dempotent.
SetUp
()
error
// SetUpAt prepares and mounts/unpacks the volume to the specified
// directory path, which may or may not exist yet. This may be called
// more than once, so implementations must be idempotent.
SetUpAt
(
dir
string
)
error
}
// Cleaner interface provides method to cleanup/unmount the volumes.
type
Cleaner
interface
{
Interface
// TearDown unmounts the volume and removes traces of the SetUp procedure.
// TearDown unmounts the volume from a self-determined directory and
// removes traces of the SetUp procedure.
TearDown
()
error
// TearDown unmounts the volume from the specified directory and
// removes traces of the SetUp procedure.
TearDownAt
(
dir
string
)
error
}
func
RenameDirectory
(
oldPath
,
newName
string
)
(
string
,
error
)
{
...
...
pkg/kubelet/volumes.go
View file @
1725c23e
...
...
@@ -53,23 +53,45 @@ func (vh *volumeHost) GetKubeClient() client.Interface {
return
vh
.
kubelet
.
kubeClient
}
func
(
kl
*
Kubelet
)
newVolumeBuilderFromPlugins
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
volume
.
Builder
{
func
(
vh
*
volumeHost
)
NewWrapperBuilder
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
volume
.
Builder
,
error
)
{
b
,
err
:=
vh
.
kubelet
.
newVolumeBuilderFromPlugins
(
spec
,
podRef
)
if
err
==
nil
&&
b
==
nil
{
return
nil
,
errUnsupportedVolumeType
}
return
b
,
nil
}
func
(
vh
*
volumeHost
)
NewWrapperCleaner
(
spec
*
api
.
Volume
,
podUID
types
.
UID
)
(
volume
.
Cleaner
,
error
)
{
plugin
,
err
:=
vh
.
kubelet
.
volumePluginMgr
.
FindPluginBySpec
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
if
plugin
==
nil
{
// Not found but not an error
return
nil
,
nil
}
c
,
err
:=
plugin
.
NewCleaner
(
spec
.
Name
,
podUID
)
if
err
==
nil
&&
c
==
nil
{
return
nil
,
errUnsupportedVolumeType
}
return
c
,
nil
}
func
(
kl
*
Kubelet
)
newVolumeBuilderFromPlugins
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
volume
.
Builder
,
error
)
{
plugin
,
err
:=
kl
.
volumePluginMgr
.
FindPluginBySpec
(
spec
)
if
err
!=
nil
{
glog
.
Warningf
(
"Can't use volume plugins for %s: %v"
,
spew
.
Sprintf
(
"%#v"
,
*
spec
),
err
)
return
nil
return
nil
,
fmt
.
Errorf
(
"can't use volume plugins for %s: %v"
,
spew
.
Sprintf
(
"%#v"
,
*
spec
),
err
)
}
if
plugin
==
nil
{
glog
.
Errorf
(
"No error, but nil volume plugin for %s"
,
spew
.
Sprintf
(
"%#v"
,
*
spec
))
return
nil
// Not found but not an error
return
nil
,
nil
}
builder
,
err
:=
plugin
.
NewBuilder
(
spec
,
podRef
)
if
err
!=
nil
{
glog
.
Warningf
(
"Error instantiating volume plugin for %s: %v"
,
spew
.
Sprintf
(
"%#v"
,
*
spec
),
err
)
return
nil
return
nil
,
fmt
.
Errorf
(
"failed to instantiate volume plugin for %s: %v"
,
spew
.
Sprintf
(
"%#v"
,
*
spec
),
err
)
}
glog
.
V
(
3
)
.
Infof
(
"Used volume plugin %q for %s"
,
plugin
.
Name
(),
spew
.
Sprintf
(
"%#v"
,
*
spec
))
return
builder
return
builder
,
nil
}
func
(
kl
*
Kubelet
)
mountExternalVolumes
(
pod
*
api
.
Pod
)
(
volumeMap
,
error
)
{
...
...
@@ -84,7 +106,11 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (volumeMap, error) {
}
// Try to use a plugin for this volume.
builder
:=
kl
.
newVolumeBuilderFromPlugins
(
volSpec
,
podRef
)
builder
,
err
:=
kl
.
newVolumeBuilderFromPlugins
(
volSpec
,
podRef
)
if
err
!=
nil
{
glog
.
Errorf
(
"Could not create volume builder for pod %s: %v"
,
pod
.
UID
,
err
)
return
nil
,
err
}
if
builder
==
nil
{
return
nil
,
errUnsupportedVolumeType
}
...
...
@@ -131,7 +157,11 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner {
// or volume objects.
// Try to use a plugin for this volume.
cleaner
:=
kl
.
newVolumeCleanerFromPlugins
(
volumeKind
,
volumeName
,
podUID
)
cleaner
,
err
:=
kl
.
newVolumeCleanerFromPlugins
(
volumeKind
,
volumeName
,
podUID
)
if
err
!=
nil
{
glog
.
Errorf
(
"Could not create volume cleaner for %s: %v"
,
volumeNameDir
.
Name
(),
err
)
continue
}
if
cleaner
==
nil
{
glog
.
Errorf
(
"Could not create volume cleaner for %s: %v"
,
volumeNameDir
.
Name
(),
errUnsupportedVolumeType
)
continue
...
...
@@ -143,23 +173,21 @@ func (kl *Kubelet) getPodVolumesFromDisk() map[string]volume.Cleaner {
return
currentVolumes
}
func
(
kl
*
Kubelet
)
newVolumeCleanerFromPlugins
(
kind
string
,
name
string
,
podUID
types
.
UID
)
volume
.
Cleaner
{
func
(
kl
*
Kubelet
)
newVolumeCleanerFromPlugins
(
kind
string
,
name
string
,
podUID
types
.
UID
)
(
volume
.
Cleaner
,
error
)
{
plugName
:=
volume
.
UnescapePluginName
(
kind
)
plugin
,
err
:=
kl
.
volumePluginMgr
.
FindPluginByName
(
plugName
)
if
err
!=
nil
{
// TODO: Maybe we should launch a cleanup of this dir?
glog
.
Warningf
(
"Can't use volume plugins for %s/%s: %v"
,
podUID
,
kind
,
err
)
return
nil
return
nil
,
fmt
.
Errorf
(
"can't use volume plugins for %s/%s: %v"
,
podUID
,
kind
,
err
)
}
if
plugin
==
nil
{
glog
.
Errorf
(
"No error, but nil volume plugin for %s/%s"
,
podUID
,
kind
)
return
nil
// Not found but not an error.
return
nil
,
nil
}
cleaner
,
err
:=
plugin
.
NewCleaner
(
name
,
podUID
)
if
err
!=
nil
{
glog
.
Warningf
(
"Error instantiating volume plugin for %s/%s: %v"
,
podUID
,
kind
,
err
)
return
nil
return
nil
,
fmt
.
Errorf
(
"failed to instantiate volume plugin for %s/%s: %v"
,
podUID
,
kind
,
err
)
}
glog
.
V
(
3
)
.
Infof
(
"Used volume plugin %q for %s/%s"
,
plugin
.
Name
(),
podUID
,
kind
)
return
cleaner
return
cleaner
,
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment