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
efcde725
Commit
efcde725
authored
Mar 13, 2015
by
Victor Marmol
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5166 from thockin/tmpfs
Add tmpfs support as a flag on emptyDir
parents
b02412f4
caca5e73
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
374 additions
and
46 deletions
+374
-46
types.go
pkg/api/types.go
+19
-2
types.go
pkg/api/v1beta1/types.go
+13
-1
types.go
pkg/api/v1beta2/types.go
+13
-1
types.go
pkg/api/v1beta3/types.go
+13
-1
empty_dir.go
pkg/kubelet/volume/empty_dir/empty_dir.go
+113
-5
empty_dir_linux.go
pkg/kubelet/volume/empty_dir/empty_dir_linux.go
+39
-0
empty_dir_test.go
pkg/kubelet/volume/empty_dir/empty_dir_test.go
+117
-34
empty_dir_unsupported.go
pkg/kubelet/volume/empty_dir/empty_dir_unsupported.go
+26
-0
fake.go
pkg/util/mount/fake.go
+20
-1
mount_linux_test.go
pkg/util/mount/mount_linux_test.go
+1
-1
No files found.
pkg/api/types.go
View file @
efcde725
...
@@ -182,12 +182,29 @@ type VolumeSource struct {
...
@@ -182,12 +182,29 @@ type VolumeSource struct {
Secret
*
SecretVolumeSource
`json:"secret"`
Secret
*
SecretVolumeSource
`json:"secret"`
}
}
// HostPathVolumeSource represents
bare host directory volume
.
// HostPathVolumeSource represents
a host directory mapped into a pod
.
type
HostPathVolumeSource
struct
{
type
HostPathVolumeSource
struct
{
Path
string
`json:"path"`
Path
string
`json:"path"`
}
}
type
EmptyDirVolumeSource
struct
{}
// EmptyDirVolumeSource represents an empty directory for a pod.
type
EmptyDirVolumeSource
struct
{
// TODO: Longer term we want to represent the selection of underlying
// media more like a scheduling problem - user says what traits they
// need, we give them a backing store that satisifies that. For now
// this will cover the most common needs.
// Optional: what type of storage medium should back this directory.
// The default is "" which means to use the node's default medium.
Medium
StorageType
`json:"medium"`
}
// StorageType defines ways that storage can be allocated to a volume.
type
StorageType
string
const
(
StorageTypeDefault
StorageType
=
""
// use whatever the default is for the node
StorageTypeMemory
StorageType
=
"Memory"
// use memory (tmpfs)
)
// Protocol defines network protocols supported for things like conatiner ports.
// Protocol defines network protocols supported for things like conatiner ports.
type
Protocol
string
type
Protocol
string
...
...
pkg/api/v1beta1/types.go
View file @
efcde725
...
@@ -112,7 +112,19 @@ type HostPathVolumeSource struct {
...
@@ -112,7 +112,19 @@ type HostPathVolumeSource struct {
Path
string
`json:"path" description:"path of the directory on the host"`
Path
string
`json:"path" description:"path of the directory on the host"`
}
}
type
EmptyDirVolumeSource
struct
{}
type
EmptyDirVolumeSource
struct
{
// Optional: what type of storage medium should back this directory.
// The default is "" which means to use the node's default medium.
Medium
StorageType
`json:"medium" description:"type of storage used to back the volume; must be an empty string (default) or Memory"`
}
// StorageType defines ways that storage can be allocated to a volume.
type
StorageType
string
const
(
StorageTypeDefault
StorageType
=
""
// use whatever the default is for the node
StorageTypeMemory
StorageType
=
"Memory"
// use memory (tmpfs)
)
// Protocol defines network protocols supported for things like conatiner ports.
// Protocol defines network protocols supported for things like conatiner ports.
type
Protocol
string
type
Protocol
string
...
...
pkg/api/v1beta2/types.go
View file @
efcde725
...
@@ -90,7 +90,19 @@ type HostPathVolumeSource struct {
...
@@ -90,7 +90,19 @@ type HostPathVolumeSource struct {
// Represents an empty directory volume.
// Represents an empty directory volume.
//
//
// https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md#emptydir
// https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md#emptydir
type
EmptyDirVolumeSource
struct
{}
type
EmptyDirVolumeSource
struct
{
// Optional: what type of storage medium should back this directory.
// The default is "" which means to use the node's default medium.
Medium
StorageType
`json:"medium" description:"type of storage used to back the volume; must be an empty string (default) or Memory"`
}
// StorageType defines ways that storage can be allocated to a volume.
type
StorageType
string
const
(
StorageTypeDefault
StorageType
=
""
// use whatever the default is for the node
StorageTypeMemory
StorageType
=
"Memory"
// use memory (tmpfs)
)
// SecretVolumeSource adapts a Secret into a VolumeSource
// SecretVolumeSource adapts a Secret into a VolumeSource
//
//
...
...
pkg/api/v1beta3/types.go
View file @
efcde725
...
@@ -206,7 +206,19 @@ type HostPathVolumeSource struct {
...
@@ -206,7 +206,19 @@ type HostPathVolumeSource struct {
Path
string
`json:"path" description:"path of the directory on the host"`
Path
string
`json:"path" description:"path of the directory on the host"`
}
}
type
EmptyDirVolumeSource
struct
{}
type
EmptyDirVolumeSource
struct
{
// Optional: what type of storage medium should back this directory.
// The default is "" which means to use the node's default medium.
Medium
StorageType
`json:"medium" description:"type of storage used to back the volume; must be an empty string (default) or Memory"`
}
// StorageType defines ways that storage can be allocated to a volume.
type
StorageType
string
const
(
StorageTypeDefault
StorageType
=
""
// use whatever the default is for the node
StorageTypeMemory
StorageType
=
"Memory"
// use memory (tmpfs)
)
// Protocol defines network protocols supported for things like conatiner ports.
// Protocol defines network protocols supported for things like conatiner ports.
type
Protocol
string
type
Protocol
string
...
...
pkg/kubelet/volume/empty_dir/empty_dir.go
View file @
efcde725
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
)
)
// This is the primary entrypoint for volume plugins.
// This is the primary entrypoint for volume plugins.
...
@@ -70,26 +71,83 @@ func (plugin *emptyDirPlugin) CanSupport(spec *api.Volume) bool {
...
@@ -70,26 +71,83 @@ func (plugin *emptyDirPlugin) CanSupport(spec *api.Volume) bool {
}
}
func
(
plugin
*
emptyDirPlugin
)
NewBuilder
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
)
(
volume
.
Builder
,
error
)
{
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
{})
}
func
(
plugin
*
emptyDirPlugin
)
newBuilderInternal
(
spec
*
api
.
Volume
,
podRef
*
api
.
ObjectReference
,
mounter
mount
.
Interface
,
mediumer
mediumer
)
(
volume
.
Builder
,
error
)
{
if
plugin
.
legacyMode
{
if
plugin
.
legacyMode
{
// Legacy mode instances can be cleaned up but not created anew.
// Legacy mode instances can be cleaned up but not created anew.
return
nil
,
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
return
nil
,
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
}
return
&
emptyDir
{
podRef
.
UID
,
spec
.
Name
,
plugin
,
false
},
nil
medium
:=
api
.
StorageTypeDefault
if
spec
.
EmptyDir
!=
nil
{
// Support a non-specified source as EmptyDir.
medium
=
spec
.
EmptyDir
.
Medium
}
return
&
emptyDir
{
podUID
:
podRef
.
UID
,
volName
:
spec
.
Name
,
medium
:
medium
,
mediumer
:
mediumer
,
mounter
:
mounter
,
plugin
:
plugin
,
legacyMode
:
false
,
},
nil
}
}
func
(
plugin
*
emptyDirPlugin
)
NewCleaner
(
volName
string
,
podUID
types
.
UID
)
(
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
,
mount
.
New
(),
&
realMediumer
{})
}
func
(
plugin
*
emptyDirPlugin
)
newCleanerInternal
(
volName
string
,
podUID
types
.
UID
,
mounter
mount
.
Interface
,
mediumer
mediumer
)
(
volume
.
Cleaner
,
error
)
{
legacy
:=
false
legacy
:=
false
if
plugin
.
legacyMode
{
if
plugin
.
legacyMode
{
legacy
=
true
legacy
=
true
}
}
return
&
emptyDir
{
podUID
,
volName
,
plugin
,
legacy
},
nil
ed
:=
&
emptyDir
{
podUID
:
podUID
,
volName
:
volName
,
medium
:
api
.
StorageTypeDefault
,
// might be changed later
mounter
:
mounter
,
mediumer
:
mediumer
,
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
}
// mediumer abstracts how to find what storageMedium a path is backed by.
type
mediumer
interface
{
GetMedium
(
path
string
)
(
storageMedium
,
error
)
}
}
type
storageMedium
int
const
(
mediumUnknown
storageMedium
=
0
// assume anything we don't explicitly handle is this
mediumMemory
storageMedium
=
1
// memory (e.g. tmpfs on linux)
)
// EmptyDir volumes are temporary directories exposed to the pod.
// EmptyDir volumes are temporary directories exposed to the pod.
// These do not persist beyond the lifetime of a pod.
// These do not persist beyond the lifetime of a pod.
type
emptyDir
struct
{
type
emptyDir
struct
{
podUID
types
.
UID
podUID
types
.
UID
volName
string
volName
string
medium
api
.
StorageType
mounter
mount
.
Interface
mediumer
mediumer
plugin
*
emptyDirPlugin
plugin
*
emptyDirPlugin
legacyMode
bool
legacyMode
bool
}
}
...
@@ -99,8 +157,34 @@ func (ed *emptyDir) SetUp() error {
...
@@ -99,8 +157,34 @@ func (ed *emptyDir) SetUp() error {
if
ed
.
legacyMode
{
if
ed
.
legacyMode
{
return
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
return
fmt
.
Errorf
(
"legacy mode: can not create new instances"
)
}
}
path
:=
ed
.
GetPath
()
switch
ed
.
medium
{
return
os
.
MkdirAll
(
path
,
0750
)
case
api
.
StorageTypeDefault
:
return
ed
.
setupDefault
()
case
api
.
StorageTypeMemory
:
return
ed
.
setupTmpfs
()
default
:
return
fmt
.
Errorf
(
"unknown storage medium %q"
,
ed
.
medium
)
}
}
func
(
ed
*
emptyDir
)
setupDefault
()
error
{
return
os
.
MkdirAll
(
ed
.
GetPath
(),
0750
)
}
func
(
ed
*
emptyDir
)
setupTmpfs
()
error
{
if
ed
.
mounter
==
nil
{
return
fmt
.
Errorf
(
"memory storage requested, but mounter is nil"
)
}
if
err
:=
os
.
MkdirAll
(
ed
.
GetPath
(),
0750
);
err
!=
nil
{
return
err
}
// Make SetUp idempotent.
if
medium
,
err
:=
ed
.
mediumer
.
GetMedium
(
ed
.
GetPath
());
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
,
""
)
}
}
func
(
ed
*
emptyDir
)
GetPath
()
string
{
func
(
ed
*
emptyDir
)
GetPath
()
string
{
...
@@ -111,8 +195,19 @@ func (ed *emptyDir) GetPath() string {
...
@@ -111,8 +195,19 @@ func (ed *emptyDir) GetPath() string {
return
ed
.
plugin
.
host
.
GetPodVolumeDir
(
ed
.
podUID
,
volume
.
EscapePluginName
(
name
),
ed
.
volName
)
return
ed
.
plugin
.
host
.
GetPodVolumeDir
(
ed
.
podUID
,
volume
.
EscapePluginName
(
name
),
ed
.
volName
)
}
}
// TearDown simply d
elete
s everything in the directory.
// TearDown simply d
iscard
s everything in the directory.
func
(
ed
*
emptyDir
)
TearDown
()
error
{
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
)
}
}
func
(
ed
*
emptyDir
)
teardownDefault
()
error
{
tmpDir
,
err
:=
volume
.
RenameDirectory
(
ed
.
GetPath
(),
ed
.
volName
+
".deleting~"
)
tmpDir
,
err
:=
volume
.
RenameDirectory
(
ed
.
GetPath
(),
ed
.
volName
+
".deleting~"
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -123,3 +218,16 @@ func (ed *emptyDir) TearDown() error {
...
@@ -123,3 +218,16 @@ func (ed *emptyDir) TearDown() error {
}
}
return
nil
return
nil
}
}
func
(
ed
*
emptyDir
)
teardownTmpfs
()
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
{
return
err
}
if
err
:=
os
.
RemoveAll
(
ed
.
GetPath
());
err
!=
nil
{
return
err
}
return
nil
}
pkg/kubelet/volume/empty_dir/empty_dir_linux.go
0 → 100644
View file @
efcde725
/*
Copyright 2015 Google Inc. 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
empty_dir
import
(
"fmt"
"syscall"
)
// Defined by Linux - the type number for tmpfs mounts.
const
linuxTmpfsMagic
=
0x01021994
// realMediumer implements mediumer in terms of syscalls.
type
realMediumer
struct
{}
func
(
m
*
realMediumer
)
GetMedium
(
path
string
)
(
storageMedium
,
error
)
{
buf
:=
syscall
.
Statfs_t
{}
if
err
:=
syscall
.
Statfs
(
path
,
&
buf
);
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"statfs(%q): %v"
,
path
,
err
)
}
if
buf
.
Type
==
linuxTmpfsMagic
{
return
mediumMemory
,
nil
}
return
mediumUnknown
,
nil
}
pkg/kubelet/volume/empty_dir/empty_dir_test.go
View file @
efcde725
...
@@ -18,21 +18,33 @@ package empty_dir
...
@@ -18,21 +18,33 @@ package empty_dir
import
(
import
(
"os"
"os"
"path"
"testing"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
)
)
func
TestCanSupport
(
t
*
testing
.
T
)
{
// The dir where volumes will be stored.
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
:=
volume
.
PluginMgr
{}
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
})
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
basePath
,
nil
})
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/empty-dir"
)
plug
,
err
:=
plugMgr
.
FindPluginByName
(
plugName
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Can't find the plugin by name"
)
t
.
Errorf
(
"Can't find the plugin by name"
)
}
}
return
plug
}
func
TestCanSupport
(
t
*
testing
.
T
)
{
plug
:=
makePluginUnderTest
(
t
,
"kubernetes.io/empty-dir"
)
if
plug
.
Name
()
!=
"kubernetes.io/empty-dir"
{
if
plug
.
Name
()
!=
"kubernetes.io/empty-dir"
{
t
.
Errorf
(
"Wrong name: %s"
,
plug
.
Name
())
t
.
Errorf
(
"Wrong name: %s"
,
plug
.
Name
())
}
}
...
@@ -44,19 +56,83 @@ func TestCanSupport(t *testing.T) {
...
@@ -44,19 +56,83 @@ func TestCanSupport(t *testing.T) {
}
}
}
}
type
fakeMediumer
struct
{
typeToReturn
storageMedium
}
func
(
fake
*
fakeMediumer
)
GetMedium
(
path
string
)
(
storageMedium
,
error
)
{
return
fake
.
typeToReturn
,
nil
}
func
TestPlugin
(
t
*
testing
.
T
)
{
func
TestPlugin
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plug
:=
makePluginUnderTest
(
t
,
"kubernetes.io/empty-dir"
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
})
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/empty-dir"
)
spec
:=
&
api
.
Volume
{
Name
:
"vol1"
,
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{
Medium
:
api
.
StorageTypeDefault
}},
}
mounter
:=
mount
.
FakeMounter
{}
mediumer
:=
fakeMediumer
{}
builder
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newBuilderInternal
(
spec
,
&
api
.
ObjectReference
{
UID
:
types
.
UID
(
"poduid"
)},
&
mounter
,
&
mediumer
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Can't find the plugin by name"
)
t
.
Errorf
(
"Failed to make a new Builder: %v"
,
err
)
}
if
builder
==
nil
{
t
.
Errorf
(
"Got a nil Builder: %v"
)
}
volPath
:=
builder
.
GetPath
()
if
volPath
!=
path
.
Join
(
basePath
,
"pods/poduid/volumes/kubernetes.io~empty-dir/vol1"
)
{
t
.
Errorf
(
"Got unexpected path: %s"
,
volPath
)
}
if
err
:=
builder
.
SetUp
();
err
!=
nil
{
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
}
if
_
,
err
:=
os
.
Stat
(
volPath
);
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
t
.
Errorf
(
"SetUp() failed, volume path not created: %s"
,
volPath
)
}
else
{
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
}
}
if
len
(
mounter
.
Log
)
!=
0
{
t
.
Errorf
(
"Expected 0 mounter calls, got %#v"
,
mounter
.
Log
)
}
}
mounter
.
ResetLog
()
cleaner
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newCleanerInternal
(
"vol1"
,
types
.
UID
(
"poduid"
),
&
mounter
,
&
fakeMediumer
{})
if
err
!=
nil
{
t
.
Errorf
(
"Failed to make a new Cleaner: %v"
,
err
)
}
if
cleaner
==
nil
{
t
.
Errorf
(
"Got a nil Cleaner: %v"
)
}
if
err
:=
cleaner
.
TearDown
();
err
!=
nil
{
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
}
if
_
,
err
:=
os
.
Stat
(
volPath
);
err
==
nil
{
t
.
Errorf
(
"TearDown() failed, volume path still exists: %s"
,
volPath
)
}
else
if
!
os
.
IsNotExist
(
err
)
{
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
}
if
len
(
mounter
.
Log
)
!=
0
{
t
.
Errorf
(
"Expected 0 mounter calls, got %#v"
,
mounter
.
Log
)
}
mounter
.
ResetLog
()
}
func
TestPluginTmpfs
(
t
*
testing
.
T
)
{
plug
:=
makePluginUnderTest
(
t
,
"kubernetes.io/empty-dir"
)
spec
:=
&
api
.
Volume
{
spec
:=
&
api
.
Volume
{
Name
:
"vol1"
,
Name
:
"vol1"
,
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}},
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{
Medium
:
api
.
StorageTypeMemory
}},
}
}
builder
,
err
:=
plug
.
NewBuilder
(
spec
,
&
api
.
ObjectReference
{
UID
:
types
.
UID
(
"poduid"
)})
mounter
:=
mount
.
FakeMounter
{}
mediumer
:=
fakeMediumer
{}
builder
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newBuilderInternal
(
spec
,
&
api
.
ObjectReference
{
UID
:
types
.
UID
(
"poduid"
)},
&
mounter
,
&
mediumer
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Failed to make a new Builder: %v"
,
err
)
t
.
Errorf
(
"Failed to make a new Builder: %v"
,
err
)
}
}
...
@@ -64,23 +140,31 @@ func TestPlugin(t *testing.T) {
...
@@ -64,23 +140,31 @@ func TestPlugin(t *testing.T) {
t
.
Errorf
(
"Got a nil Builder: %v"
)
t
.
Errorf
(
"Got a nil Builder: %v"
)
}
}
p
ath
:=
builder
.
GetPath
()
volP
ath
:=
builder
.
GetPath
()
if
path
!=
"/tmp/fake/pods/poduid/volumes/kubernetes.io~empty-dir/vol1"
{
if
volPath
!=
path
.
Join
(
basePath
,
"pods/poduid/volumes/kubernetes.io~empty-dir/vol1"
)
{
t
.
Errorf
(
"Got unexpected path: %s"
,
p
ath
)
t
.
Errorf
(
"Got unexpected path: %s"
,
volP
ath
)
}
}
if
err
:=
builder
.
SetUp
();
err
!=
nil
{
if
err
:=
builder
.
SetUp
();
err
!=
nil
{
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
}
}
if
_
,
err
:=
os
.
Stat
(
p
ath
);
err
!=
nil
{
if
_
,
err
:=
os
.
Stat
(
volP
ath
);
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
if
os
.
IsNotExist
(
err
)
{
t
.
Errorf
(
"SetUp() failed, volume path not created: %s"
,
p
ath
)
t
.
Errorf
(
"SetUp() failed, volume path not created: %s"
,
volP
ath
)
}
else
{
}
else
{
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
}
}
}
}
if
len
(
mounter
.
Log
)
!=
1
{
t
.
Errorf
(
"Expected 1 mounter call, got %#v"
,
mounter
.
Log
)
}
else
{
if
mounter
.
Log
[
0
]
.
Action
!=
mount
.
FakeActionMount
||
mounter
.
Log
[
0
]
.
FSType
!=
"tmpfs"
{
t
.
Errorf
(
"Unexpected mounter action: %#v"
,
mounter
.
Log
[
0
])
}
}
mounter
.
ResetLog
()
cleaner
,
err
:=
plug
.
NewCleaner
(
"vol1"
,
types
.
UID
(
"poduid"
)
)
cleaner
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newCleanerInternal
(
"vol1"
,
types
.
UID
(
"poduid"
),
&
mounter
,
&
fakeMediumer
{
mediumMemory
}
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Failed to make a new Cleaner: %v"
,
err
)
t
.
Errorf
(
"Failed to make a new Cleaner: %v"
,
err
)
}
}
...
@@ -91,21 +175,24 @@ func TestPlugin(t *testing.T) {
...
@@ -91,21 +175,24 @@ func TestPlugin(t *testing.T) {
if
err
:=
cleaner
.
TearDown
();
err
!=
nil
{
if
err
:=
cleaner
.
TearDown
();
err
!=
nil
{
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
t
.
Errorf
(
"Expected success, got: %v"
,
err
)
}
}
if
_
,
err
:=
os
.
Stat
(
p
ath
);
err
==
nil
{
if
_
,
err
:=
os
.
Stat
(
volP
ath
);
err
==
nil
{
t
.
Errorf
(
"TearDown() failed, volume path still exists: %s"
,
p
ath
)
t
.
Errorf
(
"TearDown() failed, volume path still exists: %s"
,
volP
ath
)
}
else
if
!
os
.
IsNotExist
(
err
)
{
}
else
if
!
os
.
IsNotExist
(
err
)
{
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
t
.
Errorf
(
"SetUp() failed: %v"
,
err
)
}
}
if
len
(
mounter
.
Log
)
!=
1
{
t
.
Errorf
(
"Expected 1 mounter call, got %#v"
,
mounter
.
Log
)
}
else
{
if
mounter
.
Log
[
0
]
.
Action
!=
mount
.
FakeActionUnmount
{
t
.
Errorf
(
"Unexpected mounter action: %#v"
,
mounter
.
Log
[
0
])
}
}
mounter
.
ResetLog
()
}
}
func
TestPluginBackCompat
(
t
*
testing
.
T
)
{
func
TestPluginBackCompat
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plug
:=
makePluginUnderTest
(
t
,
"kubernetes.io/empty-dir"
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
})
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"kubernetes.io/empty-dir"
)
if
err
!=
nil
{
t
.
Errorf
(
"Can't find the plugin by name"
)
}
spec
:=
&
api
.
Volume
{
spec
:=
&
api
.
Volume
{
Name
:
"vol1"
,
Name
:
"vol1"
,
}
}
...
@@ -117,20 +204,15 @@ func TestPluginBackCompat(t *testing.T) {
...
@@ -117,20 +204,15 @@ func TestPluginBackCompat(t *testing.T) {
t
.
Errorf
(
"Got a nil Builder: %v"
)
t
.
Errorf
(
"Got a nil Builder: %v"
)
}
}
p
ath
:=
builder
.
GetPath
()
volP
ath
:=
builder
.
GetPath
()
if
path
!=
"/tmp/fake/pods/poduid/volumes/kubernetes.io~empty-dir/vol1"
{
if
volPath
!=
path
.
Join
(
basePath
,
"pods/poduid/volumes/kubernetes.io~empty-dir/vol1"
)
{
t
.
Errorf
(
"Got unexpected path: %s"
,
p
ath
)
t
.
Errorf
(
"Got unexpected path: %s"
,
volP
ath
)
}
}
}
}
func
TestPluginLegacy
(
t
*
testing
.
T
)
{
func
TestPluginLegacy
(
t
*
testing
.
T
)
{
plugMgr
:=
volume
.
PluginMgr
{}
plug
:=
makePluginUnderTest
(
t
,
"empty"
)
plugMgr
.
InitPlugins
(
ProbeVolumePlugins
(),
&
volume
.
FakeHost
{
"/tmp/fake"
,
nil
})
plug
,
err
:=
plugMgr
.
FindPluginByName
(
"empty"
)
if
err
!=
nil
{
t
.
Errorf
(
"Can't find the plugin by name"
)
}
if
plug
.
Name
()
!=
"empty"
{
if
plug
.
Name
()
!=
"empty"
{
t
.
Errorf
(
"Wrong name: %s"
,
plug
.
Name
())
t
.
Errorf
(
"Wrong name: %s"
,
plug
.
Name
())
}
}
...
@@ -138,11 +220,12 @@ func TestPluginLegacy(t *testing.T) {
...
@@ -138,11 +220,12 @@ func TestPluginLegacy(t *testing.T) {
t
.
Errorf
(
"Expected false"
)
t
.
Errorf
(
"Expected false"
)
}
}
if
_
,
err
:=
plug
.
NewBuilder
(
&
api
.
Volume
{
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}}},
&
api
.
ObjectReference
{
UID
:
types
.
UID
(
"poduid"
)});
err
==
nil
{
spec
:=
api
.
Volume
{
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}}}
if
_
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newBuilderInternal
(
&
spec
,
&
api
.
ObjectReference
{
UID
:
types
.
UID
(
"poduid"
)},
&
mount
.
FakeMounter
{},
&
fakeMediumer
{});
err
==
nil
{
t
.
Errorf
(
"Expected failiure"
)
t
.
Errorf
(
"Expected failiure"
)
}
}
cleaner
,
err
:=
plug
.
NewCleaner
(
"vol1"
,
types
.
UID
(
"poduid"
)
)
cleaner
,
err
:=
plug
.
(
*
emptyDirPlugin
)
.
newCleanerInternal
(
"vol1"
,
types
.
UID
(
"poduid"
),
&
mount
.
FakeMounter
{},
&
fakeMediumer
{}
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Failed to make a new Cleaner: %v"
,
err
)
t
.
Errorf
(
"Failed to make a new Cleaner: %v"
,
err
)
}
}
...
...
pkg/kubelet/volume/empty_dir/empty_dir_unsupported.go
0 → 100644
View file @
efcde725
// +build !linux
/*
Copyright 2015 Google Inc. 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
empty_dir
// realMediumer pretends to implement mediumer.
type
realMediumer
struct
{}
func
(
m
*
realMediumer
)
GetMedium
(
path
string
)
(
storageMedium
,
error
)
{
return
mediumUnknown
,
nil
}
pkg/util/mount/fake.go
View file @
efcde725
...
@@ -16,16 +16,35 @@ limitations under the License.
...
@@ -16,16 +16,35 @@ limitations under the License.
package
mount
package
mount
// FakeMounter implements mount.Interface.
// FakeMounter implements mount.Interface
for tests
.
type
FakeMounter
struct
{
type
FakeMounter
struct
{
MountPoints
[]
MountPoint
MountPoints
[]
MountPoint
Log
[]
FakeAction
}
// Values for FakeAction.Action
const
FakeActionMount
=
"mount"
const
FakeActionUnmount
=
"unmount"
// FakeAction objects are logged every time a fake mount or unmount is called.
type
FakeAction
struct
{
Action
string
// "mount" or "unmount"
Target
string
// applies to both mount and unmount actions
Source
string
// applies only to "mount" actions
FSType
string
// applies only to "mount" actions
}
func
(
f
*
FakeMounter
)
ResetLog
()
{
f
.
Log
=
[]
FakeAction
{}
}
}
func
(
f
*
FakeMounter
)
Mount
(
source
string
,
target
string
,
fstype
string
,
flags
uintptr
,
data
string
)
error
{
func
(
f
*
FakeMounter
)
Mount
(
source
string
,
target
string
,
fstype
string
,
flags
uintptr
,
data
string
)
error
{
f
.
Log
=
append
(
f
.
Log
,
FakeAction
{
Action
:
FakeActionMount
,
Target
:
target
,
Source
:
source
,
FSType
:
fstype
})
return
nil
return
nil
}
}
func
(
f
*
FakeMounter
)
Unmount
(
target
string
,
flags
int
)
error
{
func
(
f
*
FakeMounter
)
Unmount
(
target
string
,
flags
int
)
error
{
f
.
Log
=
append
(
f
.
Log
,
FakeAction
{
Action
:
FakeActionUnmount
,
Target
:
target
})
return
nil
return
nil
}
}
...
...
pkg/util/mount/mount_linux_test.go
View file @
efcde725
...
@@ -94,7 +94,7 @@ func slicesEqual(a, b []string) bool {
...
@@ -94,7 +94,7 @@ func slicesEqual(a, b []string) bool {
func
TestGetMountRefs
(
t
*
testing
.
T
)
{
func
TestGetMountRefs
(
t
*
testing
.
T
)
{
fm
:=
&
FakeMounter
{
fm
:=
&
FakeMounter
{
[]
MountPoint
{
MountPoints
:
[]
MountPoint
{
{
Device
:
"/dev/sdb"
,
Path
:
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd"
},
{
Device
:
"/dev/sdb"
,
Path
:
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd"
},
{
Device
:
"/dev/sdb"
,
Path
:
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod"
},
{
Device
:
"/dev/sdb"
,
Path
:
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod"
},
{
Device
:
"/dev/sdc"
,
Path
:
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2"
},
{
Device
:
"/dev/sdc"
,
Path
:
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2"
},
...
...
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