mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-19 00:31:00 +00:00
Add Keepterminatedpodvolumes as a annotation on node
and lets make sure that controller respects it and doesn't detaches mounted volumes.
This commit is contained in:
parent
9a1a9cbe08
commit
951a36aac7
@ -281,11 +281,7 @@ func (adc *attachDetachController) populateActualStateOfWorld() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
adc.processVolumesInUse(nodeName, node.Status.VolumesInUse, true /* forceUnmount */)
|
adc.processVolumesInUse(nodeName, node.Status.VolumesInUse, true /* forceUnmount */)
|
||||||
if _, exists := node.Annotations[volumehelper.ControllerManagedAttachAnnotation]; exists {
|
adc.addNodeToDswp(node, types.NodeName(node.Name))
|
||||||
// Node specifies annotation indicating it should be managed by
|
|
||||||
// attach detach controller. Add it to desired state of world.
|
|
||||||
adc.desiredStateOfWorld.AddNode(types.NodeName(node.Name)) // Needed for DesiredStateOfWorld population
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -385,13 +381,13 @@ func (adc *attachDetachController) podAdd(obj interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if volumehelper.IsPodTerminated(pod, pod.Status) {
|
volumeActionFlag := util.DetermineVolumeAction(
|
||||||
util.ProcessPodVolumes(pod, false, /* addVolumes */
|
pod,
|
||||||
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
|
adc.desiredStateOfWorld,
|
||||||
} else {
|
true /* default volume action */)
|
||||||
util.ProcessPodVolumes(pod, true, /* addVolumes */
|
|
||||||
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
|
util.ProcessPodVolumes(pod, volumeActionFlag, /* addVolumes */
|
||||||
}
|
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDesiredStateOfWorld returns desired state of world associated with controller
|
// GetDesiredStateOfWorld returns desired state of world associated with controller
|
||||||
@ -409,13 +405,12 @@ func (adc *attachDetachController) podUpdate(oldObj, newObj interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
addPodFlag := true
|
volumeActionFlag := util.DetermineVolumeAction(
|
||||||
|
pod,
|
||||||
|
adc.desiredStateOfWorld,
|
||||||
|
true /* default volume action */)
|
||||||
|
|
||||||
if volumehelper.IsPodTerminated(pod, pod.Status) {
|
util.ProcessPodVolumes(pod, volumeActionFlag, /* addVolumes */
|
||||||
addPodFlag = false
|
|
||||||
}
|
|
||||||
|
|
||||||
util.ProcessPodVolumes(pod, addPodFlag, /* addVolumes */
|
|
||||||
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
|
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,11 +448,7 @@ func (adc *attachDetachController) nodeUpdate(oldObj, newObj interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodeName := types.NodeName(node.Name)
|
nodeName := types.NodeName(node.Name)
|
||||||
if _, exists := node.Annotations[volumehelper.ControllerManagedAttachAnnotation]; exists {
|
adc.addNodeToDswp(node, nodeName)
|
||||||
// Node specifies annotation indicating it should be managed by attach
|
|
||||||
// detach controller. Add it to desired state of world.
|
|
||||||
adc.desiredStateOfWorld.AddNode(nodeName)
|
|
||||||
}
|
|
||||||
adc.processVolumesInUse(nodeName, node.Status.VolumesInUse, false /* forceUnmount */)
|
adc.processVolumesInUse(nodeName, node.Status.VolumesInUse, false /* forceUnmount */)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,3 +550,17 @@ func (adc *attachDetachController) GetSecretFunc() func(namespace, name string)
|
|||||||
return nil, fmt.Errorf("GetSecret unsupported in attachDetachController")
|
return nil, fmt.Errorf("GetSecret unsupported in attachDetachController")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (adc *attachDetachController) addNodeToDswp(node *v1.Node, nodeName types.NodeName) {
|
||||||
|
if _, exists := node.Annotations[volumehelper.ControllerManagedAttachAnnotation]; exists {
|
||||||
|
keepTerminatedPodVolumes := false
|
||||||
|
|
||||||
|
if t, ok := node.Annotations[volumehelper.KeepTerminatedPodVolumesAnnotation]; ok {
|
||||||
|
keepTerminatedPodVolumes = (t == "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node specifies annotation indicating it should be managed by attach
|
||||||
|
// detach controller. Add it to desired state of world.
|
||||||
|
adc.desiredStateOfWorld.AddNode(nodeName, keepTerminatedPodVolumes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -46,7 +46,9 @@ type DesiredStateOfWorld interface {
|
|||||||
// AddNode adds the given node to the list of nodes managed by the attach/
|
// AddNode adds the given node to the list of nodes managed by the attach/
|
||||||
// detach controller.
|
// detach controller.
|
||||||
// If the node already exists this is a no-op.
|
// If the node already exists this is a no-op.
|
||||||
AddNode(nodeName k8stypes.NodeName)
|
// keepTerminatedPodVolumes is a property of the node that determines
|
||||||
|
// if for terminated pods volumes should be mounted and attached.
|
||||||
|
AddNode(nodeName k8stypes.NodeName, keepTerminatedPodVolumes bool)
|
||||||
|
|
||||||
// AddPod adds the given pod to the list of pods that reference the
|
// AddPod adds the given pod to the list of pods that reference the
|
||||||
// specified volume and is scheduled to the specified node.
|
// specified volume and is scheduled to the specified node.
|
||||||
@ -95,6 +97,10 @@ type DesiredStateOfWorld interface {
|
|||||||
// GetPodToAdd generates and returns a map of pods based on the current desired
|
// GetPodToAdd generates and returns a map of pods based on the current desired
|
||||||
// state of world
|
// state of world
|
||||||
GetPodToAdd() map[types.UniquePodName]PodToAdd
|
GetPodToAdd() map[types.UniquePodName]PodToAdd
|
||||||
|
|
||||||
|
// GetKeepTerminatedPodVolumesForNode determines if node wants volumes to be
|
||||||
|
// mounted and attached for terminated pods
|
||||||
|
GetKeepTerminatedPodVolumesForNode(k8stypes.NodeName) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// VolumeToAttach represents a volume that should be attached to a node.
|
// VolumeToAttach represents a volume that should be attached to a node.
|
||||||
@ -144,6 +150,10 @@ type nodeManaged struct {
|
|||||||
// attached to this node. The key in the map is the name of the volume and
|
// attached to this node. The key in the map is the name of the volume and
|
||||||
// the value is a pod object containing more information about the volume.
|
// the value is a pod object containing more information about the volume.
|
||||||
volumesToAttach map[v1.UniqueVolumeName]volumeToAttach
|
volumesToAttach map[v1.UniqueVolumeName]volumeToAttach
|
||||||
|
|
||||||
|
// keepTerminatedPodVolumes determines if for terminated pods(on this node) - volumes
|
||||||
|
// should be kept mounted and attached.
|
||||||
|
keepTerminatedPodVolumes bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// The volume object represents a volume that should be attached to a node.
|
// The volume object represents a volume that should be attached to a node.
|
||||||
@ -173,14 +183,15 @@ type pod struct {
|
|||||||
podObj *v1.Pod
|
podObj *v1.Pod
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dsw *desiredStateOfWorld) AddNode(nodeName k8stypes.NodeName) {
|
func (dsw *desiredStateOfWorld) AddNode(nodeName k8stypes.NodeName, keepTerminatedPodVolumes bool) {
|
||||||
dsw.Lock()
|
dsw.Lock()
|
||||||
defer dsw.Unlock()
|
defer dsw.Unlock()
|
||||||
|
|
||||||
if _, nodeExists := dsw.nodesManaged[nodeName]; !nodeExists {
|
if _, nodeExists := dsw.nodesManaged[nodeName]; !nodeExists {
|
||||||
dsw.nodesManaged[nodeName] = nodeManaged{
|
dsw.nodesManaged[nodeName] = nodeManaged{
|
||||||
nodeName: nodeName,
|
nodeName: nodeName,
|
||||||
volumesToAttach: make(map[v1.UniqueVolumeName]volumeToAttach),
|
volumesToAttach: make(map[v1.UniqueVolumeName]volumeToAttach),
|
||||||
|
keepTerminatedPodVolumes: keepTerminatedPodVolumes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,6 +324,21 @@ func (dsw *desiredStateOfWorld) VolumeExists(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetKeepTerminatedPodVolumesForNode determines if node wants volumes to be
|
||||||
|
// mounted and attached for terminated pods
|
||||||
|
func (dsw *desiredStateOfWorld) GetKeepTerminatedPodVolumesForNode(nodeName k8stypes.NodeName) bool {
|
||||||
|
dsw.RLock()
|
||||||
|
defer dsw.RUnlock()
|
||||||
|
|
||||||
|
if nodeName == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if node, ok := dsw.nodesManaged[nodeName]; ok {
|
||||||
|
return node.keepTerminatedPodVolumes
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (dsw *desiredStateOfWorld) GetVolumesToAttach() []VolumeToAttach {
|
func (dsw *desiredStateOfWorld) GetVolumesToAttach() []VolumeToAttach {
|
||||||
dsw.RLock()
|
dsw.RLock()
|
||||||
defer dsw.RUnlock()
|
defer dsw.RUnlock()
|
||||||
|
@ -35,7 +35,7 @@ func Test_AddNode_Positive_NewNode(t *testing.T) {
|
|||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
nodeExists := dsw.NodeExists(nodeName)
|
nodeExists := dsw.NodeExists(nodeName)
|
||||||
@ -60,7 +60,7 @@ func Test_AddNode_Positive_ExistingNode(t *testing.T) {
|
|||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
nodeExists := dsw.NodeExists(nodeName)
|
nodeExists := dsw.NodeExists(nodeName)
|
||||||
@ -69,7 +69,7 @@ func Test_AddNode_Positive_ExistingNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
nodeExists = dsw.NodeExists(nodeName)
|
nodeExists = dsw.NodeExists(nodeName)
|
||||||
@ -94,7 +94,7 @@ func Test_AddPod_Positive_NewPodNodeExistsVolumeDoesntExist(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -142,7 +142,7 @@ func Test_AddPod_Positive_NewPodNodeExistsVolumeExists(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -215,7 +215,7 @@ func Test_AddPod_Positive_PodExistsNodeExistsVolumeExists(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -319,7 +319,7 @@ func Test_DeleteNode_Positive_NodeExists(t *testing.T) {
|
|||||||
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
err := dsw.DeleteNode(nodeName)
|
err := dsw.DeleteNode(nodeName)
|
||||||
@ -375,7 +375,7 @@ func Test_DeleteNode_Negative_NodeExistsHasChildVolumes(t *testing.T) {
|
|||||||
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
podName := "pod-uid"
|
podName := "pod-uid"
|
||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
@ -419,7 +419,7 @@ func Test_DeletePod_Positive_PodExistsNodeExistsVolumeExists(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolumeName, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volumeSpec, nodeName)
|
generatedVolumeName, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volumeSpec, nodeName)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -467,7 +467,7 @@ func Test_DeletePod_Positive_2PodsExistNodeExistsVolumesExist(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolumeName1, pod1AddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volumeSpec, nodeName)
|
generatedVolumeName1, pod1AddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volumeSpec, nodeName)
|
||||||
if pod1AddErr != nil {
|
if pod1AddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -528,7 +528,7 @@ func Test_DeletePod_Positive_PodDoesNotExist(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolumeName, pod1AddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volumeSpec, nodeName)
|
generatedVolumeName, pod1AddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volumeSpec, nodeName)
|
||||||
if pod1AddErr != nil {
|
if pod1AddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -576,7 +576,7 @@ func Test_DeletePod_Positive_NodeDoesNotExist(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
node1Name := k8stypes.NodeName("node1-name")
|
node1Name := k8stypes.NodeName("node1-name")
|
||||||
dsw.AddNode(node1Name)
|
dsw.AddNode(node1Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolumeName, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volumeSpec, node1Name)
|
generatedVolumeName, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volumeSpec, node1Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -631,7 +631,7 @@ func Test_DeletePod_Positive_VolumeDoesNotExist(t *testing.T) {
|
|||||||
volume1Name := v1.UniqueVolumeName("volume1-name")
|
volume1Name := v1.UniqueVolumeName("volume1-name")
|
||||||
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volume1Spec, nodeName)
|
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(podName), controllervolumetesting.NewPod(podName, podName), volume1Spec, nodeName)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -705,7 +705,7 @@ func Test_NodeExists_Positive_NodeDoesntExist(t *testing.T) {
|
|||||||
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
nodeExists := dsw.NodeExists(nodeName)
|
nodeExists := dsw.NodeExists(nodeName)
|
||||||
@ -729,7 +729,7 @@ func Test_VolumeExists_Positive_VolumeExistsNodeExists(t *testing.T) {
|
|||||||
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
podName := "pod-uid"
|
podName := "pod-uid"
|
||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
@ -759,7 +759,7 @@ func Test_VolumeExists_Positive_VolumeDoesntExistNodeExists(t *testing.T) {
|
|||||||
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
podName := "pod-uid"
|
podName := "pod-uid"
|
||||||
volume1Name := v1.UniqueVolumeName("volume1-name")
|
volume1Name := v1.UniqueVolumeName("volume1-name")
|
||||||
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
||||||
@ -836,8 +836,8 @@ func Test_GetVolumesToAttach_Positive_TwoNodes(t *testing.T) {
|
|||||||
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
dsw := NewDesiredStateOfWorld(volumePluginMgr)
|
||||||
node1Name := k8stypes.NodeName("node1-name")
|
node1Name := k8stypes.NodeName("node1-name")
|
||||||
node2Name := k8stypes.NodeName("node2-name")
|
node2Name := k8stypes.NodeName("node2-name")
|
||||||
dsw.AddNode(node1Name)
|
dsw.AddNode(node1Name, false /*keepTerminatedPodVolumes*/)
|
||||||
dsw.AddNode(node2Name)
|
dsw.AddNode(node2Name, false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
volumesToAttach := dsw.GetVolumesToAttach()
|
volumesToAttach := dsw.GetVolumesToAttach()
|
||||||
@ -859,7 +859,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesOneVolumeEach(t *testing.T) {
|
|||||||
pod1Name := "pod1-uid"
|
pod1Name := "pod1-uid"
|
||||||
volume1Name := v1.UniqueVolumeName("volume1-name")
|
volume1Name := v1.UniqueVolumeName("volume1-name")
|
||||||
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
||||||
dsw.AddNode(node1Name)
|
dsw.AddNode(node1Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -871,7 +871,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesOneVolumeEach(t *testing.T) {
|
|||||||
pod2Name := "pod2-uid"
|
pod2Name := "pod2-uid"
|
||||||
volume2Name := v1.UniqueVolumeName("volume2-name")
|
volume2Name := v1.UniqueVolumeName("volume2-name")
|
||||||
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
||||||
dsw.AddNode(node2Name)
|
dsw.AddNode(node2Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume2Name, podAddErr := dsw.AddPod(types.UniquePodName(pod2Name), controllervolumetesting.NewPod(pod2Name, pod2Name), volume2Spec, node2Name)
|
generatedVolume2Name, podAddErr := dsw.AddPod(types.UniquePodName(pod2Name), controllervolumetesting.NewPod(pod2Name, pod2Name), volume2Spec, node2Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -904,7 +904,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesOneVolumeEachExtraPod(t *testing.T
|
|||||||
pod1Name := "pod1-uid"
|
pod1Name := "pod1-uid"
|
||||||
volume1Name := v1.UniqueVolumeName("volume1-name")
|
volume1Name := v1.UniqueVolumeName("volume1-name")
|
||||||
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
||||||
dsw.AddNode(node1Name)
|
dsw.AddNode(node1Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -916,7 +916,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesOneVolumeEachExtraPod(t *testing.T
|
|||||||
pod2Name := "pod2-uid"
|
pod2Name := "pod2-uid"
|
||||||
volume2Name := v1.UniqueVolumeName("volume2-name")
|
volume2Name := v1.UniqueVolumeName("volume2-name")
|
||||||
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
||||||
dsw.AddNode(node2Name)
|
dsw.AddNode(node2Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume2Name, podAddErr := dsw.AddPod(types.UniquePodName(pod2Name), controllervolumetesting.NewPod(pod2Name, pod2Name), volume2Spec, node2Name)
|
generatedVolume2Name, podAddErr := dsw.AddPod(types.UniquePodName(pod2Name), controllervolumetesting.NewPod(pod2Name, pod2Name), volume2Spec, node2Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -958,7 +958,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesThreeVolumes(t *testing.T) {
|
|||||||
pod1Name := "pod1-uid"
|
pod1Name := "pod1-uid"
|
||||||
volume1Name := v1.UniqueVolumeName("volume1-name")
|
volume1Name := v1.UniqueVolumeName("volume1-name")
|
||||||
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
|
||||||
dsw.AddNode(node1Name)
|
dsw.AddNode(node1Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
generatedVolume1Name, podAddErr := dsw.AddPod(types.UniquePodName(pod1Name), controllervolumetesting.NewPod(pod1Name, pod1Name), volume1Spec, node1Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -970,7 +970,7 @@ func Test_GetVolumesToAttach_Positive_TwoNodesThreeVolumes(t *testing.T) {
|
|||||||
pod2aName := "pod2a-name"
|
pod2aName := "pod2a-name"
|
||||||
volume2Name := v1.UniqueVolumeName("volume2-name")
|
volume2Name := v1.UniqueVolumeName("volume2-name")
|
||||||
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
|
||||||
dsw.AddNode(node2Name)
|
dsw.AddNode(node2Name, false /*keepTerminatedPodVolumes*/)
|
||||||
generatedVolume2Name1, podAddErr := dsw.AddPod(types.UniquePodName(pod2aName), controllervolumetesting.NewPod(pod2aName, pod2aName), volume2Spec, node2Name)
|
generatedVolume2Name1, podAddErr := dsw.AddPod(types.UniquePodName(pod2aName), controllervolumetesting.NewPod(pod2aName, pod2aName), volume2Spec, node2Name)
|
||||||
if podAddErr != nil {
|
if podAddErr != nil {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
|
@ -127,7 +127,12 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() {
|
|||||||
glog.Errorf("podLister Get failed for pod %q (UID %q) with %v", dswPodKey, dswPodUID, err)
|
glog.Errorf("podLister Get failed for pod %q (UID %q) with %v", dswPodKey, dswPodUID, err)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
if !volumehelper.IsPodTerminated(informerPod, informerPod.Status) {
|
volumeActionFlag := util.DetermineVolumeAction(
|
||||||
|
informerPod,
|
||||||
|
dswp.desiredStateOfWorld,
|
||||||
|
true /* default volume action */)
|
||||||
|
|
||||||
|
if volumeActionFlag {
|
||||||
informerPodUID := volumehelper.GetUniquePodName(informerPod)
|
informerPodUID := volumehelper.GetUniquePodName(informerPod)
|
||||||
// Check whether the unique identifier of the pod from dsw matches the one retrieved from pod informer
|
// Check whether the unique identifier of the pod from dsw matches the one retrieved from pod informer
|
||||||
if informerPodUID == dswPodUID {
|
if informerPodUID == dswPodUID {
|
||||||
|
@ -84,7 +84,7 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//add the given node to the list of nodes managed by dsw
|
//add the given node to the list of nodes managed by dsw
|
||||||
dswp.desiredStateOfWorld.AddNode(k8stypes.NodeName(pod.Spec.NodeName))
|
dswp.desiredStateOfWorld.AddNode(k8stypes.NodeName(pod.Spec.NodeName), false /*keepTerminatedPodVolumes*/)
|
||||||
|
|
||||||
dswp.findAndAddActivePods()
|
dswp.findAndAddActivePods()
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ func Test_Run_Positive_OneDesiredVolumeAttach(t *testing.T) {
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -134,7 +134,7 @@ func Test_Run_Positive_OneDesiredVolumeAttachThenDetachWithUnmountedVolume(t *te
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -201,7 +201,7 @@ func Test_Run_Positive_OneDesiredVolumeAttachThenDetachWithMountedVolume(t *test
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
@ -268,7 +268,7 @@ func Test_Run_Negative_OneDesiredVolumeAttachThenDetachWithUnmountedVolumeUpdate
|
|||||||
volumeName := v1.UniqueVolumeName("volume-name")
|
volumeName := v1.UniqueVolumeName("volume-name")
|
||||||
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
|
||||||
nodeName := k8stypes.NodeName("node-name")
|
nodeName := k8stypes.NodeName("node-name")
|
||||||
dsw.AddNode(nodeName)
|
dsw.AddNode(nodeName, false /*keepTerminatedPodVolumes*/)
|
||||||
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
volumeExists := dsw.VolumeExists(volumeName, nodeName)
|
||||||
if volumeExists {
|
if volumeExists {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
|
@ -159,6 +159,23 @@ func getPVSpecFromCache(name string, pvcReadOnly bool, expectedClaimUID types.UI
|
|||||||
return volume.NewSpecFromPersistentVolume(clonedPV, pvcReadOnly), nil
|
return volume.NewSpecFromPersistentVolume(clonedPV, pvcReadOnly), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DetermineVolumeAction returns true if volume and pod needs to be added to dswp
|
||||||
|
// and it returns false if volume and pod needs to be removed from dswp
|
||||||
|
func DetermineVolumeAction(pod *v1.Pod, desiredStateOfWorld cache.DesiredStateOfWorld, defaultAction bool) bool {
|
||||||
|
if pod == nil || len(pod.Spec.Volumes) <= 0 {
|
||||||
|
return defaultAction
|
||||||
|
}
|
||||||
|
nodeName := types.NodeName(pod.Spec.NodeName)
|
||||||
|
keepTerminatedPodVolume := desiredStateOfWorld.GetKeepTerminatedPodVolumesForNode(nodeName)
|
||||||
|
|
||||||
|
if volumehelper.IsPodTerminated(pod, pod.Status) {
|
||||||
|
// if pod is terminate we let kubelet policy dictate if volume
|
||||||
|
// should be detached or not
|
||||||
|
return keepTerminatedPodVolume
|
||||||
|
}
|
||||||
|
return defaultAction
|
||||||
|
}
|
||||||
|
|
||||||
// ProcessPodVolumes processes the volumes in the given pod and adds them to the
|
// ProcessPodVolumes processes the volumes in the given pod and adds them to the
|
||||||
// desired state of the world if addVolumes is true, otherwise it removes them.
|
// desired state of the world if addVolumes is true, otherwise it removes them.
|
||||||
func ProcessPodVolumes(pod *v1.Pod, addVolumes bool, desiredStateOfWorld cache.DesiredStateOfWorld, volumePluginMgr *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister) {
|
func ProcessPodVolumes(pod *v1.Pod, addVolumes bool, desiredStateOfWorld cache.DesiredStateOfWorld, volumePluginMgr *volume.VolumePluginMgr, pvcLister corelisters.PersistentVolumeClaimLister, pvLister corelisters.PersistentVolumeLister) {
|
||||||
|
@ -246,6 +246,14 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) {
|
|||||||
glog.Infof("Controller attach/detach is disabled for this node; Kubelet will attach and detach volumes")
|
glog.Infof("Controller attach/detach is disabled for this node; Kubelet will attach and detach volumes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if kl.kubeletConfiguration.KeepTerminatedPodVolumes {
|
||||||
|
if node.Annotations == nil {
|
||||||
|
node.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
glog.Infof("Setting node annotation to keep pod volumes of terminated pods attached to the node")
|
||||||
|
node.Annotations[volumehelper.KeepTerminatedPodVolumesAnnotation] = "true"
|
||||||
|
}
|
||||||
|
|
||||||
// @question: should this be place after the call to the cloud provider? which also applies labels
|
// @question: should this be place after the call to the cloud provider? which also applies labels
|
||||||
for k, v := range kl.nodeLabels {
|
for k, v := range kl.nodeLabels {
|
||||||
if cv, found := node.ObjectMeta.Labels[k]; found {
|
if cv, found := node.ObjectMeta.Labels[k]; found {
|
||||||
|
@ -33,6 +33,10 @@ const (
|
|||||||
// managed by the attach/detach controller
|
// managed by the attach/detach controller
|
||||||
ControllerManagedAttachAnnotation string = "volumes.kubernetes.io/controller-managed-attach-detach"
|
ControllerManagedAttachAnnotation string = "volumes.kubernetes.io/controller-managed-attach-detach"
|
||||||
|
|
||||||
|
// KeepTerminatedPodVolumesAnnotation is the key of the annotation on Node
|
||||||
|
// that decides if pod volumes are unmounted when pod is terminated
|
||||||
|
KeepTerminatedPodVolumesAnnotation string = "volumes.kubernetes.io/keep-terminated-pod-volumes"
|
||||||
|
|
||||||
// VolumeGidAnnotationKey is the of the annotation on the PersistentVolume
|
// VolumeGidAnnotationKey is the of the annotation on the PersistentVolume
|
||||||
// object that specifies a supplemental GID.
|
// object that specifies a supplemental GID.
|
||||||
VolumeGidAnnotationKey = "pv.beta.kubernetes.io/gid"
|
VolumeGidAnnotationKey = "pv.beta.kubernetes.io/gid"
|
||||||
|
@ -150,8 +150,8 @@ func TestPodDeletionWithDswp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPodUpdateWithWithADC(t *testing.T) {
|
func TestPodUpdateWithWithADC(t *testing.T) {
|
||||||
_, server := framework.RunAMaster(nil)
|
_, server, closeFn := framework.RunAMaster(nil)
|
||||||
defer server.Close()
|
defer closeFn()
|
||||||
namespaceName := "test-pod-update"
|
namespaceName := "test-pod-update"
|
||||||
|
|
||||||
node := &v1.Node{
|
node := &v1.Node{
|
||||||
@ -220,6 +220,78 @@ func TestPodUpdateWithWithADC(t *testing.T) {
|
|||||||
close(stopCh)
|
close(stopCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPodUpdateWithKeepTerminatedPodVolumes(t *testing.T) {
|
||||||
|
_, server, closeFn := framework.RunAMaster(nil)
|
||||||
|
defer closeFn()
|
||||||
|
namespaceName := "test-pod-update"
|
||||||
|
|
||||||
|
node := &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node-sandbox",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
volumehelper.ControllerManagedAttachAnnotation: "true",
|
||||||
|
volumehelper.KeepTerminatedPodVolumesAnnotation: "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ns := framework.CreateTestingNamespace(namespaceName, server, t)
|
||||||
|
defer framework.DeleteTestingNamespace(ns, server, t)
|
||||||
|
|
||||||
|
testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod)
|
||||||
|
|
||||||
|
pod := fakePodWithVol(namespaceName)
|
||||||
|
podStopCh := make(chan struct{})
|
||||||
|
|
||||||
|
if _, err := testClient.Core().Nodes().Create(node); err != nil {
|
||||||
|
t.Fatalf("Failed to created node : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go informers.Core().V1().Nodes().Informer().Run(podStopCh)
|
||||||
|
|
||||||
|
if _, err := testClient.Core().Pods(ns.Name).Create(pod); err != nil {
|
||||||
|
t.Errorf("Failed to create pod : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
podInformer := informers.Core().V1().Pods().Informer()
|
||||||
|
go podInformer.Run(podStopCh)
|
||||||
|
|
||||||
|
// start controller loop
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
go informers.Core().V1().PersistentVolumeClaims().Informer().Run(stopCh)
|
||||||
|
go informers.Core().V1().PersistentVolumes().Informer().Run(stopCh)
|
||||||
|
go ctrl.Run(stopCh)
|
||||||
|
|
||||||
|
waitToObservePods(t, podInformer, 1)
|
||||||
|
podKey, err := cache.MetaNamespaceKeyFunc(pod)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("MetaNamespaceKeyFunc failed with : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = podInformer.GetStore().GetByKey(podKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Pod not found in Pod Informer cache : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForPodsInDSWP(t, ctrl.GetDesiredStateOfWorld())
|
||||||
|
|
||||||
|
pod.Status.Phase = v1.PodSucceeded
|
||||||
|
|
||||||
|
if _, err := testClient.Core().Pods(ns.Name).UpdateStatus(pod); err != nil {
|
||||||
|
t.Errorf("Failed to update pod : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(20 * time.Second)
|
||||||
|
podsToAdd := ctrl.GetDesiredStateOfWorld().GetPodToAdd()
|
||||||
|
if len(podsToAdd) == 0 {
|
||||||
|
t.Fatalf("The pod should not be removed if KeepTerminatedPodVolumesAnnotation is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
close(podStopCh)
|
||||||
|
close(stopCh)
|
||||||
|
}
|
||||||
|
|
||||||
// wait for the podInformer to observe the pods. Call this function before
|
// wait for the podInformer to observe the pods. Call this function before
|
||||||
// running the RC manager to prevent the rc manager from creating new pods
|
// running the RC manager to prevent the rc manager from creating new pods
|
||||||
// rather than adopting the existing ones.
|
// rather than adopting the existing ones.
|
||||||
|
Loading…
Reference in New Issue
Block a user