123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- /*
- Copyright 2016 The Kubernetes Authors.
- 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 operationexecutor
- import (
- "strconv"
- "testing"
- "time"
- "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/types"
- "k8s.io/apimachinery/pkg/util/uuid"
- "k8s.io/kubernetes/pkg/util/mount"
- "k8s.io/kubernetes/pkg/volume"
- volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
- )
- const (
- numVolumesToMount = 2
- numAttachableVolumesToUnmount = 2
- numNonAttachableVolumesToUnmount = 2
- numDevicesToUnmount = 2
- numVolumesToAttach = 2
- numVolumesToDetach = 2
- numVolumesToVerifyAttached = 2
- numVolumesToVerifyControllerAttached = 2
- numVolumesToMap = 2
- numAttachableVolumesToUnmap = 2
- numNonAttachableVolumesToUnmap = 2
- numDevicesToUnmap = 2
- )
- var _ OperationGenerator = &fakeOperationGenerator{}
- func TestOperationExecutor_MountVolume_ConcurrentMountForNonAttachableAndNonDevicemountablePlugins(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToMount)
- secretName := "secret-volume"
- volumeName := v1.UniqueVolumeName(secretName)
- // Act
- for i := range volumesToMount {
- podName := "pod-" + strconv.Itoa((i + 1))
- pod := getTestPodWithSecret(podName, secretName)
- volumesToMount[i] = VolumeToMount{
- Pod: pod,
- VolumeName: volumeName,
- PluginIsAttachable: false, // this field determines whether the plugin is attachable
- PluginIsDeviceMountable: false, // this field determines whether the plugin is devicemountable
- ReportedInUse: true,
- }
- oe.MountVolume(0 /* waitForAttachTimeOut */, volumesToMount[i], nil /* actualStateOfWorldMounterUpdater */, false /* isRemount */)
- }
- // Assert
- if !isOperationRunConcurrently(ch, quit, numVolumesToMount) {
- t.Fatalf("Unable to start mount operations in Concurrent for non-attachable volumes")
- }
- }
- func TestOperationExecutor_MountVolume_ConcurrentMountForAttachablePlugins(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToAttach)
- pdName := "pd-volume"
- volumeName := v1.UniqueVolumeName(pdName)
- // Act
- for i := range volumesToMount {
- podName := "pod-" + strconv.Itoa((i + 1))
- pod := getTestPodWithGCEPD(podName, pdName)
- volumesToMount[i] = VolumeToMount{
- Pod: pod,
- VolumeName: volumeName,
- PluginIsAttachable: true, // this field determines whether the plugin is attachable
- ReportedInUse: true,
- }
- oe.MountVolume(0 /* waitForAttachTimeout */, volumesToMount[i], nil /* actualStateOfWorldMounterUpdater */, false /* isRemount */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Mount operations should not start concurrently for attachable volumes")
- }
- }
- func TestOperationExecutor_MountVolume_ConcurrentMountForDeviceMountablePlugins(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToAttach)
- pdName := "pd-volume"
- volumeName := v1.UniqueVolumeName(pdName)
- // Act
- for i := range volumesToMount {
- podName := "pod-" + strconv.Itoa((i + 1))
- pod := getTestPodWithGCEPD(podName, pdName)
- volumesToMount[i] = VolumeToMount{
- Pod: pod,
- VolumeName: volumeName,
- PluginIsDeviceMountable: true, // this field determines whether the plugin is devicemountable
- ReportedInUse: true,
- }
- oe.MountVolume(0 /* waitForAttachTimeout */, volumesToMount[i], nil /* actualStateOfWorldMounterUpdater */, false /* isRemount */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Mount operations should not start concurrently for devicemountable volumes")
- }
- }
- func TestOperationExecutor_UnmountVolume_ConcurrentUnmountForAllPlugins(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToUnmount := make([]MountedVolume, numAttachableVolumesToUnmount+numNonAttachableVolumesToUnmount)
- pdName := "pd-volume"
- secretName := "secret-volume"
- // Act
- for i := 0; i < numNonAttachableVolumesToUnmount+numAttachableVolumesToUnmount; i++ {
- podName := "pod-" + strconv.Itoa(i+1)
- if i < numNonAttachableVolumesToUnmount {
- pod := getTestPodWithSecret(podName, secretName)
- volumesToUnmount[i] = MountedVolume{
- PodName: volumetypes.UniquePodName(podName),
- VolumeName: v1.UniqueVolumeName(secretName),
- PodUID: pod.UID,
- }
- } else {
- pod := getTestPodWithGCEPD(podName, pdName)
- volumesToUnmount[i] = MountedVolume{
- PodName: volumetypes.UniquePodName(podName),
- VolumeName: v1.UniqueVolumeName(pdName),
- PodUID: pod.UID,
- }
- }
- oe.UnmountVolume(volumesToUnmount[i], nil /* actualStateOfWorldMounterUpdater */, "" /*podsDir*/)
- }
- // Assert
- if !isOperationRunConcurrently(ch, quit, numNonAttachableVolumesToUnmount+numAttachableVolumesToUnmount) {
- t.Fatalf("Unable to start unmount operations concurrently for volume plugins")
- }
- }
- func TestOperationExecutor_UnmountDeviceConcurrently(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- attachedVolumes := make([]AttachedVolume, numDevicesToUnmount)
- pdName := "pd-volume"
- // Act
- for i := range attachedVolumes {
- attachedVolumes[i] = AttachedVolume{
- VolumeName: v1.UniqueVolumeName(pdName),
- NodeName: "node-name",
- }
- oe.UnmountDevice(attachedVolumes[i], nil /* actualStateOfWorldMounterUpdater */, nil /* mount.Interface */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Unmount device operations should not start concurrently")
- }
- }
- func TestOperationExecutor_AttachVolumeConcurrently(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToAttach := make([]VolumeToAttach, numVolumesToAttach)
- pdName := "pd-volume"
- // Act
- for i := range volumesToAttach {
- volumesToAttach[i] = VolumeToAttach{
- VolumeName: v1.UniqueVolumeName(pdName),
- NodeName: "node",
- }
- oe.AttachVolume(volumesToAttach[i], nil /* actualStateOfWorldAttacherUpdater */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Attach volume operations should not start concurrently")
- }
- }
- func TestOperationExecutor_DetachVolumeConcurrently(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- attachedVolumes := make([]AttachedVolume, numVolumesToDetach)
- pdName := "pd-volume"
- // Act
- for i := range attachedVolumes {
- attachedVolumes[i] = AttachedVolume{
- VolumeName: v1.UniqueVolumeName(pdName),
- NodeName: "node",
- }
- oe.DetachVolume(attachedVolumes[i], true /* verifySafeToDetach */, nil /* actualStateOfWorldAttacherUpdater */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("DetachVolume operations should not run concurrently")
- }
- }
- func TestOperationExecutor_VerifyVolumesAreAttachedConcurrently(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- // Act
- for i := 0; i < numVolumesToVerifyAttached; i++ {
- oe.VerifyVolumesAreAttachedPerNode(nil /* attachedVolumes */, "node-name", nil /* actualStateOfWorldAttacherUpdater */)
- }
- // Assert
- if !isOperationRunConcurrently(ch, quit, numVolumesToVerifyAttached) {
- t.Fatalf("VerifyVolumesAreAttached operation is not being run concurrently")
- }
- }
- func TestOperationExecutor_VerifyControllerAttachedVolumeConcurrently(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToVerifyControllerAttached)
- pdName := "pd-volume"
- // Act
- for i := range volumesToMount {
- volumesToMount[i] = VolumeToMount{
- VolumeName: v1.UniqueVolumeName(pdName),
- }
- oe.VerifyControllerAttachedVolume(volumesToMount[i], types.NodeName("node-name"), nil /* actualStateOfWorldMounterUpdater */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("VerifyControllerAttachedVolume should not run concurrently")
- }
- }
- func TestOperationExecutor_MountVolume_ConcurrentMountForNonAttachablePlugins_VolumeMode_Block(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToMap)
- secretName := "secret-volume"
- volumeName := v1.UniqueVolumeName(secretName)
- volumeMode := v1.PersistentVolumeBlock
- tmpSpec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{VolumeMode: &volumeMode}}}
- // Act
- for i := range volumesToMount {
- podName := "pod-" + strconv.Itoa((i + 1))
- pod := getTestPodWithSecret(podName, secretName)
- volumesToMount[i] = VolumeToMount{
- Pod: pod,
- VolumeName: volumeName,
- PluginIsAttachable: false, // this field determines whether the plugin is attachable
- ReportedInUse: true,
- VolumeSpec: tmpSpec,
- }
- oe.MountVolume(0 /* waitForAttachTimeOut */, volumesToMount[i], nil /* actualStateOfWorldMounterUpdater */, false)
- }
- // Assert
- if !isOperationRunConcurrently(ch, quit, numVolumesToMap) {
- t.Fatalf("Unable to start map operations in Concurrent for non-attachable volumes")
- }
- }
- func TestOperationExecutor_MountVolume_ConcurrentMountForAttachablePlugins_VolumeMode_Block(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToMount := make([]VolumeToMount, numVolumesToAttach)
- pdName := "pd-volume"
- volumeName := v1.UniqueVolumeName(pdName)
- volumeMode := v1.PersistentVolumeBlock
- tmpSpec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{VolumeMode: &volumeMode}}}
- // Act
- for i := range volumesToMount {
- podName := "pod-" + strconv.Itoa((i + 1))
- pod := getTestPodWithGCEPD(podName, pdName)
- volumesToMount[i] = VolumeToMount{
- Pod: pod,
- VolumeName: volumeName,
- PluginIsAttachable: true, // this field determines whether the plugin is attachable
- ReportedInUse: true,
- VolumeSpec: tmpSpec,
- }
- oe.MountVolume(0 /* waitForAttachTimeout */, volumesToMount[i], nil /* actualStateOfWorldMounterUpdater */, false)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Map operations should not start concurrently for attachable volumes")
- }
- }
- func TestOperationExecutor_UnmountVolume_ConcurrentUnmountForAllPlugins_VolumeMode_Block(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- volumesToUnmount := make([]MountedVolume, numAttachableVolumesToUnmap+numNonAttachableVolumesToUnmap)
- pdName := "pd-volume"
- secretName := "secret-volume"
- volumeMode := v1.PersistentVolumeBlock
- tmpSpec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{VolumeMode: &volumeMode}}}
- // Act
- for i := 0; i < numNonAttachableVolumesToUnmap+numAttachableVolumesToUnmap; i++ {
- podName := "pod-" + strconv.Itoa(i+1)
- if i < numNonAttachableVolumesToUnmap {
- pod := getTestPodWithSecret(podName, secretName)
- volumesToUnmount[i] = MountedVolume{
- PodName: volumetypes.UniquePodName(podName),
- VolumeName: v1.UniqueVolumeName(secretName),
- PodUID: pod.UID,
- VolumeSpec: tmpSpec,
- }
- } else {
- pod := getTestPodWithGCEPD(podName, pdName)
- volumesToUnmount[i] = MountedVolume{
- PodName: volumetypes.UniquePodName(podName),
- VolumeName: v1.UniqueVolumeName(pdName),
- PodUID: pod.UID,
- VolumeSpec: tmpSpec,
- }
- }
- oe.UnmountVolume(volumesToUnmount[i], nil /* actualStateOfWorldMounterUpdater */, "" /* podsDir */)
- }
- // Assert
- if !isOperationRunConcurrently(ch, quit, numNonAttachableVolumesToUnmap+numAttachableVolumesToUnmap) {
- t.Fatalf("Unable to start unmap operations concurrently for volume plugins")
- }
- }
- func TestOperationExecutor_UnmountDeviceConcurrently_VolumeMode_Block(t *testing.T) {
- // Arrange
- ch, quit, oe := setup()
- attachedVolumes := make([]AttachedVolume, numDevicesToUnmap)
- pdName := "pd-volume"
- volumeMode := v1.PersistentVolumeBlock
- tmpSpec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{VolumeMode: &volumeMode}}}
- // Act
- for i := range attachedVolumes {
- attachedVolumes[i] = AttachedVolume{
- VolumeName: v1.UniqueVolumeName(pdName),
- NodeName: "node-name",
- VolumeSpec: tmpSpec,
- }
- oe.UnmountDevice(attachedVolumes[i], nil /* actualStateOfWorldMounterUpdater */, nil /* mount.Interface */)
- }
- // Assert
- if !isOperationRunSerially(ch, quit) {
- t.Fatalf("Unmap device operations should not start concurrently")
- }
- }
- type fakeOperationGenerator struct {
- ch chan interface{}
- quit chan interface{}
- }
- func newFakeOperationGenerator(ch chan interface{}, quit chan interface{}) OperationGenerator {
- return &fakeOperationGenerator{
- ch: ch,
- quit: quit,
- }
- }
- func (fopg *fakeOperationGenerator) GenerateMountVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater, isRemount bool) volumetypes.GeneratedOperations {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }
- }
- func (fopg *fakeOperationGenerator) GenerateUnmountVolumeFunc(volumeToUnmount MountedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater, podsDir string) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateAttachVolumeFunc(volumeToAttach VolumeToAttach, actualStateOfWorld ActualStateOfWorldAttacherUpdater) volumetypes.GeneratedOperations {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }
- }
- func (fopg *fakeOperationGenerator) GenerateDetachVolumeFunc(volumeToDetach AttachedVolume, verifySafeToDetach bool, actualStateOfWorld ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateVolumesAreAttachedFunc(attachedVolumes []AttachedVolume, nodeName types.NodeName, actualStateOfWorld ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateUnmountDeviceFunc(deviceToDetach AttachedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater, mounter mount.Interface) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateVerifyControllerAttachedVolumeFunc(volumeToMount VolumeToMount, nodeName types.NodeName, actualStateOfWorld ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateExpandVolumeFunc(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateExpandInUseVolumeFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateBulkVolumeVerifyFunc(
- pluginNodeVolumes map[types.NodeName][]*volume.Spec,
- pluginNane string,
- volumeSpecMap map[*volume.Spec]v1.UniqueVolumeName,
- actualStateOfWorldAttacherUpdater ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateMapVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateUnmapVolumeFunc(volumeToUnmount MountedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GenerateUnmapDeviceFunc(deviceToDetach AttachedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater, mounter mount.Interface) (volumetypes.GeneratedOperations, error) {
- opFunc := func() (error, error) {
- startOperationAndBlock(fopg.ch, fopg.quit)
- return nil, nil
- }
- return volumetypes.GeneratedOperations{
- OperationFunc: opFunc,
- }, nil
- }
- func (fopg *fakeOperationGenerator) GetVolumePluginMgr() *volume.VolumePluginMgr {
- return nil
- }
- func getTestPodWithSecret(podName, secretName string) *v1.Pod {
- return &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: podName,
- UID: types.UID(podName),
- },
- Spec: v1.PodSpec{
- Volumes: []v1.Volume{
- {
- Name: secretName,
- VolumeSource: v1.VolumeSource{
- Secret: &v1.SecretVolumeSource{
- SecretName: secretName,
- },
- },
- },
- },
- Containers: []v1.Container{
- {
- Name: "secret-volume-test",
- Image: "k8s.gcr.io/mounttest:0.8",
- Args: []string{
- "--file_content=/etc/secret-volume/data-1",
- "--file_mode=/etc/secret-volume/data-1"},
- VolumeMounts: []v1.VolumeMount{
- {
- Name: secretName,
- MountPath: "/data",
- },
- },
- },
- },
- RestartPolicy: v1.RestartPolicyNever,
- },
- }
- }
- func getTestPodWithGCEPD(podName, pdName string) *v1.Pod {
- return &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: podName,
- UID: types.UID(podName + string(uuid.NewUUID())),
- },
- Spec: v1.PodSpec{
- Volumes: []v1.Volume{
- {
- Name: pdName,
- VolumeSource: v1.VolumeSource{
- GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
- PDName: pdName,
- FSType: "ext4",
- ReadOnly: false,
- },
- },
- },
- },
- Containers: []v1.Container{
- {
- Name: "pd-volume-test",
- Image: "k8s.gcr.io/mounttest:0.8",
- Args: []string{
- "--file_content=/etc/pd-volume/data-1",
- },
- VolumeMounts: []v1.VolumeMount{
- {
- Name: pdName,
- MountPath: "/data",
- },
- },
- },
- },
- RestartPolicy: v1.RestartPolicyNever,
- },
- }
- }
- func isOperationRunSerially(ch <-chan interface{}, quit chan<- interface{}) bool {
- defer close(quit)
- numOperationsStarted := 0
- loop:
- for {
- select {
- case <-ch:
- numOperationsStarted++
- if numOperationsStarted > 1 {
- return false
- }
- case <-time.After(5 * time.Second):
- break loop
- }
- }
- return true
- }
- func isOperationRunConcurrently(ch <-chan interface{}, quit chan<- interface{}, numOperationsToRun int) bool {
- defer close(quit)
- numOperationsStarted := 0
- loop:
- for {
- select {
- case <-ch:
- numOperationsStarted++
- if numOperationsStarted == numOperationsToRun {
- return true
- }
- case <-time.After(5 * time.Second):
- break loop
- }
- }
- return false
- }
- func setup() (chan interface{}, chan interface{}, OperationExecutor) {
- ch, quit := make(chan interface{}), make(chan interface{})
- return ch, quit, NewOperationExecutor(newFakeOperationGenerator(ch, quit))
- }
- // This function starts by writing to ch and blocks on the quit channel
- // until it is closed by the currently running test
- func startOperationAndBlock(ch chan<- interface{}, quit <-chan interface{}) {
- ch <- nil
- <-quit
- }
|