func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (volumeMap, error) { podVolumes := make(volumeMap) for i := range pod.Spec.Volumes { volSpec := &pod.Spec.Volumes[i] podRef, err := api.GetReference(pod) if err != nil { glog.Errorf("Error getting object reference for pod: %v", pod, err) return nil, err } rootContext, err := kl.getRootDirContext() if err != nil { return nil, err } // Try to use a plugin for this volume. internal := volume.NewSpecFromVolume(volSpec) builder, err := kl.newVolumeBuilderFromPlugins(internal, podRef, volume.VolumeOptions{rootContext}) 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 } err = builder.SetUp() if err != nil { return nil, err } podVolumes[volSpec.Name] = builder } return podVolumes, nil }
func TestName(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid") testVolumeName = "test_name" testNamespace = "test_metadata_namespace" testName = "test_metadata_name" ) volumeSpec := &api.Volume{ Name: testVolumeName, VolumeSource: api.VolumeSource{ Metadata: &api.MetadataVolumeSource{ Items: []api.MetadataFile{ {Name: "name_file_name", FieldRef: api.ObjectFieldSelector{ FieldPath: "metadata.name"}}}}, }, } fake := testclient.NewSimpleFake(&api.Pod{ ObjectMeta: api.ObjectMeta{ Name: testName, Namespace: testNamespace, }, }) pluginMgr := volume.VolumePluginMgr{} pluginMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t, fake)) plugin, err := pluginMgr.FindPluginByName(metadataPluginName) if err != nil { 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{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } var data []byte data, err = ioutil.ReadFile(path.Join(volumePath, "name_file_name")) if err != nil { t.Errorf(err.Error()) } if string(data) != testName { t.Errorf("Found `%s` expected %s", string(data), testName) } CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t) }
func TestPluginLegacy(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("gce-pd") if err != nil { t.Errorf("Can't find the plugin by name") } if plug.Name() != "gce-pd" { t.Errorf("Wrong name: %s", plug.Name()) } if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}) { t.Errorf("Expected false") } spec := &api.Volume{VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}} if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}); err == nil { t.Errorf("Expected failiure") } cleaner, err := plug.NewCleaner("vol1", types.UID("poduid")) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } }
func TestBuilderAndCleanerTypeAssert(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/aws-ebs") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{ VolumeID: "pd", FSType: "ext4", }, }, } builder, err := plug.(*awsElasticBlockStorePlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) if _, ok := builder.(volume.Cleaner); ok { t.Errorf("Volume Builder can be type-assert to Cleaner") } cleaner, err := plug.(*awsElasticBlockStorePlugin).newCleanerInternal("vol1", types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) if _, ok := cleaner.(volume.Builder); ok { t.Errorf("Volume Cleaner can be type-assert to Builder") } }
func TestPluginLegacy(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t)) plug, err := plugMgr.FindPluginByName("git") if err != nil { t.Errorf("Can't find the plugin by name") } if plug.Name() != "git" { t.Errorf("Wrong name: %s", plug.Name()) } if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}) { t.Errorf("Expected false") } spec := &api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}} pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} if _, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{""}, nil); err == nil { t.Errorf("Expected failiure") } cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } }
func TestPluginVolume(t *testing.T) { vol := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{"localhost", "/tmp", false}}, } doTestPlugin(t, volume.NewSpecFromVolume(vol)) }
func TestPluginVolume(t *testing.T) { vol := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{"ep", "vol", false}}, } doTestPlugin(t, volume.NewSpecFromVolume(vol)) }
func TestPlugin(t *testing.T) { plug := makePluginUnderTest(t, "kubernetes.io/empty-dir") spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumDefault}}, } mounter := mount.FakeMounter{} mountDetector := fakeMountDetector{} pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} builder, err := plug.(*emptyDirPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), pod, &mounter, &mountDetector, volume.VolumeOptions{""}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } 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, &fakeMountDetector{}) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } 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() }
// Test the case where the 'ready' file has been created and the pod volume dir // is a mountpoint. Mount should not be called. func TestPluginIdempotent(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid2") testVolumeName = "test_volume_name" testNamespace = "test_secret_namespace" testName = "test_secret_name" volumeSpec = volumeSpec(testVolumeName, testName) secret = secret(testNamespace, testName) client = testclient.NewSimpleFake(&secret) pluginMgr = volume.VolumePluginMgr{} rootDir, host = newTestHost(t, client) ) pluginMgr.InitPlugins(ProbeVolumePlugins(), host) plugin, err := pluginMgr.FindPluginByName(secretPluginName) if err != nil { t.Errorf("Can't find the plugin by name") } 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.MountPoints = []mount.MountPoint{ { Path: podVolumeDir, }, } util.SetReady(podMetadataDir) builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, mounter) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } if len(mounter.Log) != 0 { t.Errorf("Unexpected calls made to mounter: %v", mounter.Log) } if _, err := os.Stat(volumePath); err != nil { if !os.IsNotExist(err) { t.Errorf("SetUp() failed unexpectedly: %v", err) } } else { t.Errorf("volume path should not exist: %v", volumePath) } }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t)) plug, err := plugMgr.FindPluginByName("kubernetes.io/git-repo") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ GitRepo: &api.GitRepoVolumeSource{ Repository: "https://github.com/GoogleCloudPlatform/kubernetes.git", Revision: "2a30ce65c5ab586b98916d83385c5983edd353a1", }, }, } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{""}, mount.New()) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } path := builder.GetPath() if !strings.HasSuffix(path, "pods/poduid/volumes/kubernetes.io~git-repo/vol1") { t.Errorf("Got unexpected path: %s", path) } testSetUp(plug, builder, t) if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), mount.New()) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", path) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/cephfs") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ CephFS: &api.CephFSVolumeSource{ Monitors: []string{"a", "b"}, User: "******", SecretRef: nil, SecretFile: "/etc/ceph/user.secret", }, }, } builder, err := plug.(*cephfsPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), &mount.FakeMounter{}, "secrets") volumePath := builder.GetPath() if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder: %v") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~cephfs/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } cleaner, err := plug.(*cephfsPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{}) 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(volumePath); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", volumePath) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } }
// Test the case where the plugin's ready file exists, but the volume dir is not a // mountpoint, which is the state the system will be in after reboot. The dir // should be mounter and the secret data written to it. func TestPluginReboot(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid3") testVolumeName = "test_volume_name" testNamespace = "test_secret_namespace" testName = "test_secret_name" volumeSpec = volumeSpec(testVolumeName, testName) secret = secret(testNamespace, testName) client = testclient.NewSimpleFake(&secret) pluginMgr = volume.VolumePluginMgr{} rootDir, host = newTestHost(t, client) ) pluginMgr.InitPlugins(ProbeVolumePlugins(), host) plugin, err := pluginMgr.FindPluginByName(secretPluginName) if err != nil { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid3/plugins/kubernetes.io~secret/test_volume_name", rootDir) util.SetReady(podMetadataDir) volumePath := builder.GetPath() if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid3/volumes/kubernetes.io~secret/test_volume_name")) { t.Errorf("Got unexpected path: %s", volumePath) } err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } doTestSecretDataInVolume(volumePath, secret, t) doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) }
func TestPluginVolume(t *testing.T) { vol := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ RBD: &api.RBDVolumeSource{ CephMonitors: []string{"a", "b"}, RBDImage: "bar", FSType: "ext4", }, }, } doTestPlugin(t, volume.NewSpecFromVolume(vol)) }
func TestPluginVolume(t *testing.T) { vol := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ ISCSI: &api.ISCSIVolumeSource{ TargetPortal: "127.0.0.1:3260", IQN: "iqn.2014-12.server:storage.target01", FSType: "ext4", Lun: 0, }, }, } doTestPlugin(t, volume.NewSpecFromVolume(vol)) }
func TestPluginBackCompat(t *testing.T) { plug := makePluginUnderTest(t, "kubernetes.io/empty-dir") spec := &api.Volume{ Name: "vol1", } builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, volume.VolumeOptions{""}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volPath := builder.GetPath() if volPath != path.Join(basePath, "pods/poduid/volumes/kubernetes.io~empty-dir/vol1") { t.Errorf("Got unexpected path: %s", volPath) } }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/host-path") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/vol1"}}, } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}, nil) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } path := builder.GetPath() if path != "/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"), nil) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } }
func TestPluginLegacy(t *testing.T) { plug := makePluginUnderTest(t, "empty") if plug.Name() != "empty" { t.Errorf("Wrong name: %s", plug.Name()) } if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}) { t.Errorf("Expected false") } spec := api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}} if _, err := plug.(*emptyDirPlugin).newBuilderInternal(volume.NewSpecFromVolume(&spec), &api.ObjectReference{UID: types.UID("poduid")}, &mount.FakeMounter{}, &fakeMountDetector{}, volume.VolumeOptions{""}); err == nil { t.Errorf("Expected failiure") } cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{}, &fakeMountDetector{}) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } }
func TestPluginTmpfs(t *testing.T) { plug := makePluginUnderTest(t, "kubernetes.io/empty-dir") spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageTypeMemory}}, } mounter := mount.FakeMounter{} mountDetector := fakeMountDetector{} builder, err := plug.(*emptyDirPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, &mounter, &mountDetector, volume.VolumeOptions{""}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } 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) != 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.(*emptyDirPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mounter, &fakeMountDetector{mediumMemory, true}) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } 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) != 1 { t.Errorf("Expected 1 mounter call, got %d (%v)", len(mounter.Log), mounter.Log) } else { if mounter.Log[0].Action != mount.FakeActionUnmount { t.Errorf("Unexpected mounter action: %#v", mounter.Log[0]) } } mounter.ResetLog() }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/iscsi") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ ISCSI: &api.ISCSIVolumeSource{ TargetPortal: "127.0.0.1:3260", IQN: "iqn.2014-12.server:storage.target01", FSType: "ext4", Lun: 0, }, }, } fakeManager := &fakeDiskManager{} fakeMounter := &mount.FakeMounter{} builder, err := plug.(*ISCSIPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder: %v") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~iscsi/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } if !fakeManager.attachCalled { t.Errorf("Attach was not called") } fakeManager = &fakeDiskManager{} cleaner, err := plug.(*ISCSIPlugin).newCleanerInternal("vol1", types.UID("poduid"), fakeManager, fakeMounter) 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(path); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", path) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } if !fakeManager.detachCalled { t.Errorf("Detach was not called") } }
func TestPlugin(t *testing.T) { var ( testPodUID = "test_pod_uid" testVolumeName = "test_volume_name" testNamespace = "test_secret_namespace" testName = "test_secret_name" ) volumeSpec := &api.Volume{ Name: testVolumeName, VolumeSource: api.VolumeSource{ Secret: &api.SecretVolumeSource{ SecretName: testName, }, }, } secret := api.Secret{ ObjectMeta: api.ObjectMeta{ Namespace: testNamespace, Name: testName, }, Data: map[string][]byte{ "data-1": []byte("value-1"), "data-2": []byte("value-2"), "data-3": []byte("value-3"), }, } client := testclient.NewSimpleFake(&secret) pluginMgr := volume.VolumePluginMgr{} pluginMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t, client)) plugin, err := pluginMgr.FindPluginByName(secretPluginName) if err != nil { t.Errorf("Can't find the plugin by name") } builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), &api.ObjectReference{UID: types.UID(testPodUID)}, volume.VolumeOptions{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid/volumes/kubernetes.io~secret/test_volume_name")) { t.Errorf("Got unexpected path: %s", volumePath) } err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } for key, value := range secret.Data { secretDataHostPath := path.Join(volumePath, key) if _, err := os.Stat(secretDataHostPath); err != nil { t.Fatalf("SetUp() failed, couldn't find secret data on disk: %v", secretDataHostPath) } else { actualSecretBytes, err := ioutil.ReadFile(secretDataHostPath) if err != nil { t.Fatalf("Couldn't read secret data from: %v", secretDataHostPath) } actualSecretValue := string(actualSecretBytes) if string(value) != actualSecretValue { t.Errorf("Unexpected value; expected %q, got %q", value, actualSecretValue) } } } cleaner, err := plugin.NewCleaner(testVolumeName, types.UID(testPodUID)) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", volumePath) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/gce-pd") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{ PDName: "pd", FSType: "ext4", }, }, } fakeManager := &fakePDManager{} fakeMounter := &mount.FakeMounter{} builder, err := plug.(*gcePersistentDiskPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~gce-pd/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } if !fakeManager.attachCalled { t.Errorf("Attach watch not called") } fakeManager = &fakePDManager{} cleaner, err := plug.(*gcePersistentDiskPlugin).newCleanerInternal("vol1", types.UID("poduid"), fakeManager, fakeMounter) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", path) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } if !fakeManager.detachCalled { t.Errorf("Detach watch not called") } }
func TestWriteWithUnixPath(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid") testVolumeName = "test_write_with_unix_path" testNamespace = "test_metadata_namespace" testName = "test_metadata_name" ) labels := map[string]string{ "key1": "value1", "key2": "value2"} annotations := map[string]string{ "a1": "value1", "a2": "value2"} fake := testclient.NewSimpleFake(&api.Pod{ ObjectMeta: api.ObjectMeta{ Name: testName, Namespace: testNamespace, Labels: labels, }, }) pluginMgr := volume.VolumePluginMgr{} pluginMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t, fake)) plugin, err := pluginMgr.FindPluginByName(metadataPluginName) volumeSpec := &api.Volume{ Name: testVolumeName, VolumeSource: api.VolumeSource{ Metadata: &api.MetadataVolumeSource{ Items: []api.MetadataFile{ {Name: "this/is/mine/labels", FieldRef: api.ObjectFieldSelector{ FieldPath: "metadata.labels"}}, {Name: "this/is/yours/annotations", FieldRef: api.ObjectFieldSelector{ FieldPath: "metadata.annotations"}}, }}}, } if err != nil { 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{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } var data []byte data, err = ioutil.ReadFile(path.Join(volumePath, "this/is/mine/labels")) if err != nil { t.Errorf(err.Error()) } if sortLines(string(data)) != sortLines(formatMap(labels)) { t.Errorf("Found `%s` expected %s", data, formatMap(labels)) } data, err = ioutil.ReadFile(path.Join(volumePath, "this/is/yours/annotations")) if err != nil { t.Errorf(err.Error()) } if sortLines(string(data)) != sortLines(formatMap(annotations)) { t.Errorf("Found `%s` expected %s", data, formatMap(annotations)) } CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t) }
func TestWriteTwiceWithUpdate(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid") testVolumeName = "test_write_twice_with_update" testNamespace = "test_metadata_namespace" testName = "test_metadata_name" ) labels := map[string]string{ "key1": "value1", "key2": "value2"} fake := testclient.NewSimpleFake(&api.Pod{ ObjectMeta: api.ObjectMeta{ Name: testName, Namespace: testNamespace, Labels: labels, }, }) pluginMgr := volume.VolumePluginMgr{} pluginMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t, fake)) plugin, err := pluginMgr.FindPluginByName(metadataPluginName) volumeSpec := &api.Volume{ Name: testVolumeName, VolumeSource: api.VolumeSource{ Metadata: &api.MetadataVolumeSource{ Items: []api.MetadataFile{ {Name: "labels", FieldRef: api.ObjectFieldSelector{ FieldPath: "metadata.labels"}}}}, }, } if err != nil { 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{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } var currentTarget string if currentTarget, err = os.Readlink(path.Join(volumePath, ".current")); err != nil { t.Errorf("labels file should be a link... %s\n", err.Error()) } var data []byte data, err = ioutil.ReadFile(path.Join(volumePath, "labels")) if err != nil { t.Errorf(err.Error()) } if sortLines(string(data)) != sortLines(formatMap(labels)) { t.Errorf("Found `%s` expected %s", data, formatMap(labels)) } newLabels := map[string]string{ "key1": "value1", "key2": "value2", "key3": "value3"} // Now update the labels pod.ObjectMeta.Labels = newLabels err = builder.SetUp() // now re-run Setup if err != nil { t.Errorf("Failed to re-setup volume: %v", err) } // get the link of the link var currentTarget2 string if currentTarget2, err = os.Readlink(path.Join(volumePath, ".current")); err != nil { t.Errorf(".current should be a link... %s\n", err.Error()) } if currentTarget2 == currentTarget { t.Errorf("Got and update between the two Setup... Target link should NOT be the same\n") } data, err = ioutil.ReadFile(path.Join(volumePath, "labels")) if err != nil { t.Errorf(err.Error()) } if sortLines(string(data)) != sortLines(formatMap(newLabels)) { t.Errorf("Found `%s` expected %s", data, formatMap(newLabels)) } CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t) }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/aws-ebs") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{ AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{ VolumeID: "pd", FSType: "ext4", }, }, } builder, err := plug.(*awsElasticBlockStorePlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~aws-ebs/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", path) } else { t.Errorf("SetUp() failed: %v", err) } } cleaner, err := plug.(*awsElasticBlockStorePlugin).newCleanerInternal("vol1", types.UID("poduid"), &fakePDManager{}, &mount.FakeMounter{}) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", path) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/glusterfs") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{"ep", "vol", false}}, } ep := &api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "foo"}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}}}} var fcmd exec.FakeCmd fcmd = exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // mount func() ([]byte, error) { return []byte{}, nil }, }, } fake := exec.FakeExec{ CommandScript: []exec.FakeCommandAction{ func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, }, } builder, err := plug.(*glusterfsPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), ep, &api.ObjectReference{UID: types.UID("poduid")}, &mount.FakeMounter{}, &fake) volumePath := builder.GetPath() if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder: %v") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~glusterfs/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } cleaner, err := plug.(*glusterfsPlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{}) 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(volumePath); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", volumePath) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } }
// doTestPlugin sets up a volume and tears it back down. func doTestPlugin(t *testing.T, config pluginTestConfig) { basePath, err := ioutil.TempDir("/tmp", "emptydir_volume_test") if err != nil { t.Fatalf("can't make a temp rootdir") } var ( volumePath = path.Join(basePath, "pods/poduid/volumes/kubernetes.io~empty-dir/test-volume") metadataDir = path.Join(basePath, "pods/poduid/plugins/kubernetes.io~empty-dir/test-volume") plug = makePluginUnderTest(t, "kubernetes.io/empty-dir", basePath) volumeName = "test-volume" spec = &api.Volume{ Name: volumeName, VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: config.medium}}, } mounter = mount.FakeMounter{} mountDetector = fakeMountDetector{} pod = &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} fakeChconRnr = &fakeChconRunner{} ) // Set up the SELinux options on the pod if config.SELinuxOptions != nil { pod.Spec = api.PodSpec{ Containers: []api.Container{ { SecurityContext: &api.SecurityContext{ SELinuxOptions: config.SELinuxOptions, }, VolumeMounts: []api.VolumeMount{ { Name: volumeName, }, }, }, }, } } if config.idempotent { mounter.MountPoints = []mount.MountPoint{ { Path: volumePath, }, } util.SetReady(metadataDir) } builder, err := plug.(*emptyDirPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), pod, &mounter, &mountDetector, volume.VolumeOptions{config.rootContext}, fakeChconRnr) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volPath := builder.GetPath() if volPath != volumePath { t.Errorf("Got unexpected path: %s", volPath) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } // Stat the directory and check the permission bits fileinfo, err := os.Stat(volPath) if !config.idempotent { if err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volPath) } else { t.Errorf("SetUp() failed: %v", err) } } if e, a := perm, fileinfo.Mode().Perm(); e != a { t.Errorf("Unexpected file mode for %v: expected: %v, got: %v", volPath, e, a) } } else if err == nil { // If this test is for idempotency and we were able // to stat the volume path, it's an error. t.Errorf("Volume directory was created unexpectedly") } // Check the number of chcons during setup if e, a := config.expectedChcons, len(fakeChconRnr.requests); e != a { t.Errorf("Expected %v chcon calls, got %v", e, a) } if config.expectedChcons == 1 { if e, a := config.expectedSELinuxContext, fakeChconRnr.requests[0].context; e != a { t.Errorf("Unexpected chcon context argument; expected: %v, got: %v", e, a) } if e, a := volPath, fakeChconRnr.requests[0].dir; e != a { t.Errorf("Unexpected chcon path argument: expected: %v, got: %v", e, a) } } // Check the number of mounts performed during setup if e, a := config.expectedSetupMounts, len(mounter.Log); e != a { t.Errorf("Expected %v mounter calls during setup, got %v", e, a) } else if config.expectedSetupMounts == 1 && (mounter.Log[0].Action != mount.FakeActionMount || mounter.Log[0].FSType != "tmpfs") { t.Errorf("Unexpected mounter action during setup: %#v", mounter.Log[0]) } mounter.ResetLog() // Make a cleaner for the volume teardownMedium := mediumUnknown if config.medium == api.StorageMediumMemory { teardownMedium = mediumMemory } cleanerMountDetector := &fakeMountDetector{medium: teardownMedium, isMount: config.shouldBeMountedBeforeTeardown} cleaner, err := plug.(*emptyDirPlugin).newCleanerInternal(volumeName, types.UID("poduid"), &mounter, cleanerMountDetector) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } // Tear down the volume 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) } // Check the number of mounter calls during tardown if e, a := config.expectedTeardownMounts, len(mounter.Log); e != a { t.Errorf("Expected %v mounter calls during teardown, got %v", e, a) } else if config.expectedTeardownMounts == 1 && mounter.Log[0].Action != mount.FakeActionUnmount { t.Errorf("Unexpected mounter action during teardown: %#v", mounter.Log[0]) } mounter.ResetLog() }
func TestPlugin(t *testing.T) { plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", nil, nil)) plug, err := plugMgr.FindPluginByName("kubernetes.io/nfs") if err != nil { t.Errorf("Can't find the plugin by name") } spec := &api.Volume{ Name: "vol1", VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{"localhost", "/tmp", false}}, } fake := &fakeNFSMounter{} builder, err := plug.(*nfsPlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), &api.ObjectReference{UID: types.UID("poduid")}, fake) volumePath := builder.GetPath() if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } path := builder.GetPath() if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~nfs/vol1" { t.Errorf("Got unexpected path: %s", path) } if err := builder.SetUp(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } if builder.(*nfs).readOnly { t.Errorf("The volume source should not be read-only and it is.") } if len(fake.FakeMounter.Log) != 1 { t.Errorf("Mount was not called exactly one time. It was called %d times.", len(fake.FakeMounter.Log)) } else { if fake.FakeMounter.Log[0].Action != mount.FakeActionMount { t.Errorf("Unexpected mounter action: %#v", fake.FakeMounter.Log[0]) } } fake.FakeMounter.ResetLog() cleaner, err := plug.(*nfsPlugin).newCleanerInternal("vol1", types.UID("poduid"), fake) if err != nil { t.Errorf("Failed to make a new Cleaner: %v", err) } if cleaner == nil { t.Errorf("Got a nil Cleaner") } if err := cleaner.TearDown(); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err == nil { t.Errorf("TearDown() failed, volume path still exists: %s", volumePath) } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } if len(fake.FakeMounter.Log) != 1 { t.Errorf("Unmount was not called exactly one time. It was called %d times.", len(fake.FakeMounter.Log)) } else { if fake.FakeMounter.Log[0].Action != mount.FakeActionUnmount { t.Errorf("Unexpected mounter action: %#v", fake.FakeMounter.Log[0]) } } fake.FakeMounter.ResetLog() }