mirror of https://github.com/k3s-io/k3s
Retool mount detection for tests
parent
1725c23eb2
commit
b42652cd3d
|
@ -82,10 +82,10 @@ 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.
|
// Inject real implementations here, test through the internal function.
|
||||||
return plugin.newBuilderInternal(spec, podRef, plugin.mounter, &realMediumer{})
|
return plugin.newBuilderInternal(spec, podRef, plugin.mounter, &realMountDetector{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.ObjectReference, mounter mount.Interface, mediumer mediumer) (volume.Builder, error) {
|
func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.ObjectReference, mounter mount.Interface, mountDetector mountDetector) (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")
|
||||||
|
@ -99,7 +99,7 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.O
|
||||||
volName: spec.Name,
|
volName: spec.Name,
|
||||||
medium: medium,
|
medium: medium,
|
||||||
mounter: mounter,
|
mounter: mounter,
|
||||||
mediumer: mediumer,
|
mountDetector: mountDetector,
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
legacyMode: false,
|
legacyMode: false,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -107,10 +107,10 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.O
|
||||||
|
|
||||||
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.
|
// Inject real implementations here, test through the internal function.
|
||||||
return plugin.newCleanerInternal(volName, podUID, plugin.mounter, &realMediumer{})
|
return plugin.newCleanerInternal(volName, podUID, plugin.mounter, &realMountDetector{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface, mediumer mediumer) (volume.Cleaner, error) {
|
func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface, mountDetector mountDetector) (volume.Cleaner, error) {
|
||||||
legacy := false
|
legacy := false
|
||||||
if plugin.legacyMode {
|
if plugin.legacyMode {
|
||||||
legacy = true
|
legacy = true
|
||||||
|
@ -120,16 +120,21 @@ func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UI
|
||||||
volName: volName,
|
volName: volName,
|
||||||
medium: api.StorageTypeDefault, // might be changed later
|
medium: api.StorageTypeDefault, // might be changed later
|
||||||
mounter: mounter,
|
mounter: mounter,
|
||||||
mediumer: mediumer,
|
mountDetector: mountDetector,
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
legacyMode: legacy,
|
legacyMode: legacy,
|
||||||
}
|
}
|
||||||
return ed, nil
|
return ed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mediumer abstracts how to find what storageMedium a path is backed by.
|
// mountDetector abstracts how to find what kind of mount a path is backed by.
|
||||||
type mediumer interface {
|
type mountDetector interface {
|
||||||
GetMedium(path string) (storageMedium, error)
|
// GetMountMedium determines what type of medium a given path is backed
|
||||||
|
// by and whether that path is a mount point. For example, if this
|
||||||
|
// returns (mediumMemory, false, nil), the caller knows that the path is
|
||||||
|
// on a memory FS (tmpfs on Linux) but is not the root mountpoint of
|
||||||
|
// that tmpfs.
|
||||||
|
GetMountMedium(path string) (storageMedium, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageMedium int
|
type storageMedium int
|
||||||
|
@ -146,7 +151,7 @@ type emptyDir struct {
|
||||||
volName string
|
volName string
|
||||||
medium api.StorageType
|
medium api.StorageType
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
mediumer mediumer
|
mountDetector mountDetector
|
||||||
plugin *emptyDirPlugin
|
plugin *emptyDirPlugin
|
||||||
legacyMode bool
|
legacyMode bool
|
||||||
}
|
}
|
||||||
|
@ -183,9 +188,11 @@ func (ed *emptyDir) setupTmpfs(dir string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Make SetUp idempotent.
|
// Make SetUp idempotent.
|
||||||
if medium, err := ed.mediumer.GetMedium(dir); err != nil {
|
medium, isMnt, err := ed.mountDetector.GetMountMedium(dir)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if medium == mediumMemory {
|
}
|
||||||
|
if isMnt && medium == mediumMemory {
|
||||||
return nil // current state is what we expect
|
return nil // current state is what we expect
|
||||||
}
|
}
|
||||||
return ed.mounter.Mount("tmpfs", dir, "tmpfs", 0, "")
|
return ed.mounter.Mount("tmpfs", dir, "tmpfs", 0, "")
|
||||||
|
@ -207,19 +214,17 @@ func (ed *emptyDir) TearDown() error {
|
||||||
// TearDownAt simply discards everything in the directory.
|
// TearDownAt simply discards everything in the directory.
|
||||||
func (ed *emptyDir) TearDownAt(dir string) error {
|
func (ed *emptyDir) TearDownAt(dir string) error {
|
||||||
// Figure out the medium.
|
// Figure out the medium.
|
||||||
if medium, err := ed.mediumer.GetMedium(dir); err != nil {
|
medium, isMnt, err := ed.mountDetector.GetMountMedium(dir)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
}
|
||||||
switch medium {
|
if isMnt && medium == mediumMemory {
|
||||||
case mediumMemory:
|
|
||||||
ed.medium = api.StorageTypeMemory
|
ed.medium = api.StorageTypeMemory
|
||||||
return ed.teardownTmpfs(dir)
|
return ed.teardownTmpfs(dir)
|
||||||
default:
|
}
|
||||||
// assume StorageTypeDefault
|
// assume StorageTypeDefault
|
||||||
return ed.teardownDefault(dir)
|
return ed.teardownDefault(dir)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ed *emptyDir) teardownDefault(dir string) error {
|
func (ed *emptyDir) teardownDefault(dir string) error {
|
||||||
tmpDir, err := volume.RenameDirectory(dir, ed.volName+".deleting~")
|
tmpDir, err := volume.RenameDirectory(dir, ed.volName+".deleting~")
|
||||||
|
|
|
@ -19,21 +19,27 @@ package empty_dir
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defined by Linux - the type number for tmpfs mounts.
|
// Defined by Linux - the type number for tmpfs mounts.
|
||||||
const linuxTmpfsMagic = 0x01021994
|
const linuxTmpfsMagic = 0x01021994
|
||||||
|
|
||||||
// realMediumer implements mediumer in terms of syscalls.
|
// realMountDetector implements mountDetector in terms of syscalls.
|
||||||
type realMediumer struct{}
|
type realMountDetector struct{}
|
||||||
|
|
||||||
func (m *realMediumer) GetMedium(path string) (storageMedium, error) {
|
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
||||||
|
isMnt, err := mount.IsMountPoint(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, fmt.Errorf("IsMountPoint(%q): %v", path, err)
|
||||||
|
}
|
||||||
buf := syscall.Statfs_t{}
|
buf := syscall.Statfs_t{}
|
||||||
if err := syscall.Statfs(path, &buf); err != nil {
|
if err := syscall.Statfs(path, &buf); err != nil {
|
||||||
return 0, fmt.Errorf("statfs(%q): %v", path, err)
|
return 0, false, fmt.Errorf("statfs(%q): %v", path, err)
|
||||||
}
|
}
|
||||||
if buf.Type == linuxTmpfsMagic {
|
if buf.Type == linuxTmpfsMagic {
|
||||||
return mediumMemory, nil
|
return mediumMemory, isMnt, nil
|
||||||
}
|
}
|
||||||
return mediumUnknown, nil
|
return mediumUnknown, isMnt, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,13 @@ func TestCanSupport(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeMediumer struct {
|
type fakeMountDetector struct {
|
||||||
typeToReturn storageMedium
|
medium storageMedium
|
||||||
|
isMount bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fake *fakeMediumer) GetMedium(path string) (storageMedium, error) {
|
func (fake *fakeMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
||||||
return fake.typeToReturn, nil
|
return fake.medium, fake.isMount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPlugin(t *testing.T) {
|
func TestPlugin(t *testing.T) {
|
||||||
|
@ -72,8 +73,8 @@ func TestPlugin(t *testing.T) {
|
||||||
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageTypeDefault}},
|
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageTypeDefault}},
|
||||||
}
|
}
|
||||||
mounter := mount.FakeMounter{}
|
mounter := mount.FakeMounter{}
|
||||||
mediumer := fakeMediumer{}
|
mountDetector := fakeMountDetector{}
|
||||||
builder, err := plug.(*emptyDirPlugin).newBuilderInternal(spec, &api.ObjectReference{UID: types.UID("poduid")}, &mounter, &mediumer)
|
builder, err := plug.(*emptyDirPlugin).newBuilderInternal(spec, &api.ObjectReference{UID: types.UID("poduid")}, &mounter, &mountDetector)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +102,7 @@ func TestPlugin(t *testing.T) {
|
||||||
}
|
}
|
||||||
mounter.ResetLog()
|
mounter.ResetLog()
|
||||||
|
|
||||||
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mounter, &fakeMediumer{})
|
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mounter, &fakeMountDetector{})
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -131,8 +132,8 @@ func TestPluginTmpfs(t *testing.T) {
|
||||||
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageTypeMemory}},
|
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageTypeMemory}},
|
||||||
}
|
}
|
||||||
mounter := mount.FakeMounter{}
|
mounter := mount.FakeMounter{}
|
||||||
mediumer := fakeMediumer{}
|
mountDetector := fakeMountDetector{}
|
||||||
builder, err := plug.(*emptyDirPlugin).newBuilderInternal(spec, &api.ObjectReference{UID: types.UID("poduid")}, &mounter, &mediumer)
|
builder, err := plug.(*emptyDirPlugin).newBuilderInternal(spec, &api.ObjectReference{UID: types.UID("poduid")}, &mounter, &mountDetector)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +165,7 @@ func TestPluginTmpfs(t *testing.T) {
|
||||||
}
|
}
|
||||||
mounter.ResetLog()
|
mounter.ResetLog()
|
||||||
|
|
||||||
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mounter, &fakeMediumer{mediumMemory})
|
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mounter, &fakeMountDetector{mediumMemory, true})
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -181,7 +182,7 @@ func TestPluginTmpfs(t *testing.T) {
|
||||||
t.Errorf("SetUp() failed: %v", err)
|
t.Errorf("SetUp() failed: %v", err)
|
||||||
}
|
}
|
||||||
if len(mounter.Log) != 1 {
|
if len(mounter.Log) != 1 {
|
||||||
t.Errorf("Expected 1 mounter call, got %#v", mounter.Log)
|
t.Errorf("Expected 1 mounter call, got %d (%v)", len(mounter.Log), mounter.Log)
|
||||||
} else {
|
} else {
|
||||||
if mounter.Log[0].Action != mount.FakeActionUnmount {
|
if mounter.Log[0].Action != mount.FakeActionUnmount {
|
||||||
t.Errorf("Unexpected mounter action: %#v", mounter.Log[0])
|
t.Errorf("Unexpected mounter action: %#v", mounter.Log[0])
|
||||||
|
@ -221,11 +222,11 @@ func TestPluginLegacy(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}
|
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 {
|
if _, err := plug.(*emptyDirPlugin).newBuilderInternal(&spec, &api.ObjectReference{UID: types.UID("poduid")}, &mount.FakeMounter{}, &fakeMountDetector{}); err == nil {
|
||||||
t.Errorf("Expected failiure")
|
t.Errorf("Expected failiure")
|
||||||
}
|
}
|
||||||
|
|
||||||
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{}, &fakeMediumer{})
|
cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{}, &fakeMountDetector{})
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ limitations under the License.
|
||||||
|
|
||||||
package empty_dir
|
package empty_dir
|
||||||
|
|
||||||
// realMediumer pretends to implement mediumer.
|
// realMountDetector pretends to implement mediumer.
|
||||||
type realMediumer struct{}
|
type realMountDetector struct{}
|
||||||
|
|
||||||
func (m *realMediumer) GetMedium(path string) (storageMedium, error) {
|
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
||||||
return mediumUnknown, nil
|
return mediumUnknown, false, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue