Merge pull request #24696 from saad-ali/attachControllerSkeleton

Automatic merge from submit-queue

Add data structure for storing attach detach controller state.

This PR introduces the data structure for maintaining the in-memory state for the new attach/detach controller (#20262).
pull/6/head
k8s-merge-robot 2016-05-08 23:44:38 -07:00
commit 2f1a9dd65c
3 changed files with 1010 additions and 0 deletions

View File

@ -0,0 +1,19 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package volume implements a controller to manage volume attach and detach
// operations.
package volume

View File

@ -0,0 +1,412 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package cache implements a data structure used by the attach/detach controller
to keep track of volumes, the nodes they are attached to, and the pods that
reference them. It is thread-safe.
*/
package cache
import (
"fmt"
"sync"
)
// AttachDetachVolumeCache defines the set of operations the volume cache
// supports.
type AttachDetachVolumeCache interface {
// AddVolume adds the given volume to the list of volumes managed by the
// attach detach controller.
// If the volume already exists, this is a no-op.
AddVolume(volumeName string)
// AddNode adds the given node to the list of nodes the specified volume is
// attached to.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// If the node already exists for the specified volume, this is a no-op.
AddNode(nodeName, volumeName string) error
// AddPod adds the given pod to the list of pods that are scheduled to
// the specified node and referencing the specified volume.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// If the pod already exists for the specified volume, this is a no-op.
AddPod(podName, nodeName, volumeName string) error
// DeleteVolume removes the given volume from the list of volumes managed
// by the attach detach controller.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// All attachedNodes must be deleted from the volume before it is deleted.
// If the specified volume contains 1 or more attachedNodes, an error is
// returned.
DeleteVolume(volumeName string) error
// DeleteNode removes the given node from the list of nodes the specified
// volume is attached to.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// All scheduledPods must be deleted from the node before it is deleted.
// If the specified node contains 1 or more scheduledPods, an error is
// returned.
DeleteNode(nodeName, volumeName string) error
// DeletePod removes the given pod from the list of pods that are scheduled
// to the specified node and referencing the specified volume.
// If no pod with the name podName exists for the specified volume/node, an
// error is returned.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
DeletePod(podName, nodeName, volumeName string) error
// VolumeExists returns true if the volume with the specified name exists
// in the list of volumes managed by the attach detach controller.
VolumeExists(volumeName string) bool
// NodeExists returns true if the node with the specified name exists in
// the list of nodes the specified volume is attached to.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
NodeExists(nodeName, volumeName string) (bool, error)
// PodExists returns true if the pod with the specified name exists in the
// list of pods that are scheduled to the specified node and referencing
// the specified volume.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
PodExists(podName, nodeName, volumeName string) (bool, error)
}
// NewAttachDetachVolumeCache returns a new instance of the
// AttachDetachVolumeCache.
func NewAttachDetachVolumeCache() AttachDetachVolumeCache {
return &attachDetachVolumeCache{
volumesManaged: make(map[string]volume),
}
}
type attachDetachVolumeCache struct {
// volumesManaged is a map containing the set of volumes managed by the
// attach/detach controller. The key in this map is the name of the unique
// volume identifier and the value is a volume object containing more
// information about the volume.
volumesManaged map[string]volume
sync.RWMutex
}
// The volume object represents a volume that is being tracked by the attach
// detach controller.
type volume struct {
// name contains the unique identifer for this volume.
name string
// attachedNodes is a map containing the set of nodes this volume has
// succesfully been attached to. The key in this map is the name of the
// node and the value is a node object containing more information about
// the node.
attachedNodes map[string]node
}
// The node object represents a node that a volume is attached to.
type node struct {
// name contains the name of this node.
name string
// scheduledPods is a map containing the set of pods that are scheduled to
// this node and referencing the underlying volume. The key in the map is
// the name of the pod and the value is a pod object containing more
// information about the pod.
scheduledPods map[string]pod
}
// The pod object represents a pod that is scheduled to a node and referncing
// the underlying volume.
type pod struct {
// name contains the name of this pod.
name string
}
// AddVolume adds the given volume to the list of volumes managed by the attach
// detach controller.
// If the volume already exists, this is a no-op.
func (vc *attachDetachVolumeCache) AddVolume(volumeName string) {
vc.Lock()
defer vc.Unlock()
if _, exists := vc.volumesManaged[volumeName]; !exists {
vc.volumesManaged[volumeName] = volume{
name: volumeName,
attachedNodes: make(map[string]node),
}
}
}
// AddNode adds the given node to the list of nodes the specified volume is
// attached to.
// If no volume with the name volumeName exists in the list of managed volumes,
// an error is returned.
// If the node already exists for the specified volume, this is a no-op.
func (vc *attachDetachVolumeCache) AddNode(nodeName, volumeName string) error {
vc.Lock()
defer vc.Unlock()
vol, volExists := vc.volumesManaged[volumeName]
if !volExists {
return fmt.Errorf(
"failed to add node %q to volume %q--no volume with that name exists in the list of managed volumes",
nodeName,
volumeName)
}
if _, nodeExists := vol.attachedNodes[nodeName]; !nodeExists {
vc.volumesManaged[volumeName].attachedNodes[nodeName] = node{
name: nodeName,
scheduledPods: make(map[string]pod),
}
}
return nil
}
// AddPod adds the given pod to the list of pods that are scheduled to the
// specified node and referencing the specified volume.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// If the pod already exists for the specified volume, this is a no-op.
func (vc *attachDetachVolumeCache) AddPod(podName, nodeName, volumeName string) error {
vc.Lock()
defer vc.Unlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return fmt.Errorf(
"failed to add pod %q to node %q volume %q--no volume with that name exists in the list of managed volumes",
podName,
nodeName,
volumeName)
}
nodeObj, nodeExists := volObj.attachedNodes[nodeName]
if !nodeExists {
return fmt.Errorf(
"failed to add pod %q to node %q volume %q--no node with that name exists in the list of attached nodes for that volume",
podName,
nodeName,
volumeName)
}
if _, podExists := nodeObj.scheduledPods[podName]; !podExists {
vc.volumesManaged[volumeName].attachedNodes[nodeName].scheduledPods[podName] =
pod{
name: podName,
}
}
return nil
}
// DeleteVolume removes the given volume from the list of volumes managed by
// the attach detach controller.
// If no volume with the name volumeName exists in the list of managed volumes,
// an error is returned.
// All attachedNodes must be deleted from the volume before it is deleted.
// If the specified volume contains 1 or more attachedNodes, an error is
// returned.
func (vc *attachDetachVolumeCache) DeleteVolume(volumeName string) error {
vc.Lock()
defer vc.Unlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return fmt.Errorf(
"failed to delete volume %q--no volume with that name exists in the list of managed volumes",
volumeName)
}
if len(volObj.attachedNodes) > 0 {
return fmt.Errorf(
"failed to remove volume %q from list of managed volumes--the volume still contains %v nodes in its list of attached nodes",
volumeName,
len(volObj.attachedNodes))
}
delete(
vc.volumesManaged,
volumeName)
return nil
}
// DeleteNode removes the given node from the list of nodes the specified
// volume is attached to.
// If no node with the name nodeName exists in the list of attached nodes, an
// error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
// All scheduledPods must be deleted from the node before it is deleted.
// If the specified node contains 1 or more scheduledPods, an error is
// returned.
func (vc *attachDetachVolumeCache) DeleteNode(nodeName, volumeName string) error {
vc.Lock()
defer vc.Unlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return fmt.Errorf(
"failed to delete node %q from volume %q--no volume with that name exists in the list of managed volumes",
nodeName,
volumeName)
}
nodeObj, nodeExists := volObj.attachedNodes[nodeName]
if !nodeExists {
return fmt.Errorf(
"failed to delete node %q from volume %q--no node with the that name exists in the list of attached nodes for that volume",
nodeName,
volumeName)
}
if len(nodeObj.scheduledPods) > 0 {
return fmt.Errorf(
"failed to remove node %q from volume %q--the node still contains %v pods in its list of scheduled pods",
nodeName,
volumeName,
len(nodeObj.scheduledPods))
}
delete(
vc.volumesManaged[volumeName].attachedNodes,
nodeName)
return nil
}
// DeletePod removes the given pod from the list of pods that are scheduled
// to the specified node and referencing the specified volume.
// If no pod with the name podName exists for the specified volume/node, an
// error is returned.
// If no node with the name nodeName exists in the list of attached nodes,
// an error is returned.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
func (vc *attachDetachVolumeCache) DeletePod(podName, nodeName, volumeName string) error {
vc.Lock()
defer vc.Unlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return fmt.Errorf(
"failed to delete pod %q from node %q volume %q--no volume with that name exists in the list of managed volumes",
podName,
nodeName,
volumeName)
}
nodeObj, nodeExists := volObj.attachedNodes[nodeName]
if !nodeExists {
return fmt.Errorf(
"failed to delete pod %q from node %q volume %q--no node with that name exists in the list of attached nodes for that volume",
podName,
nodeName,
volumeName)
}
if _, podExists := nodeObj.scheduledPods[podName]; !podExists {
return fmt.Errorf(
"failed to delete pod %q from node %q volume %q--no pod with that name exists in the list of scheduled pods under that node/volume",
podName,
nodeName,
volumeName)
}
delete(
vc.volumesManaged[volumeName].attachedNodes[nodeName].scheduledPods,
podName)
return nil
}
// VolumeExists returns true if the volume with the specified name exists in
// the list of volumes managed by the attach detach controller.
func (vc *attachDetachVolumeCache) VolumeExists(volumeName string) bool {
vc.RLock()
defer vc.RUnlock()
_, volExists := vc.volumesManaged[volumeName]
return volExists
}
// NodeExists returns true if the node with the specified name exists in the
// list of nodes the specified volume is attached to.
// If no volume with the name volumeName exists in the list of managed
// volumes, an error is returned.
func (vc *attachDetachVolumeCache) NodeExists(nodeName, volumeName string) (bool, error) {
vc.RLock()
defer vc.RUnlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return false,
fmt.Errorf(
"failed to check if node %q exists under volume %q--no volume with that name exists in the list of managed volumes",
nodeName,
volumeName)
}
_, nodeExists := volObj.attachedNodes[nodeName]
return nodeExists, nil
}
// PodExists returns true if the pod with the specified name exists in the list
// of pods that are scheduled to the specified node and referencing the
// specified volume.
// If no node with the name nodeName exists in the list of attached nodes, an
// error is returned.
// If no volume with the name volumeName exists in the list of managed volumes,
// an error is returned.
func (vc *attachDetachVolumeCache) PodExists(podName, nodeName, volumeName string) (bool, error) {
vc.RLock()
defer vc.RUnlock()
volObj, volExists := vc.volumesManaged[volumeName]
if !volExists {
return false,
fmt.Errorf(
"failed to check if node %q exists under volume %q--no volume with that name exists in the list of managed volumes",
nodeName,
volumeName)
}
nodeObj, nodeExists := volObj.attachedNodes[nodeName]
if !nodeExists {
return false, fmt.Errorf(
"failed to check if pod %q exists under node %q volume %q--no node with that name exists in the list of attached nodes for that volume",
podName,
nodeName,
volumeName)
}
_, podExists := nodeObj.scheduledPods[podName]
return podExists, nil
}

View File

@ -0,0 +1,579 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cache
import "testing"
func Test_AddVolume_Positive_NewVolume(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
// Act
vc.AddVolume(volumeName)
// Assert
volumeExists := vc.VolumeExists(volumeName)
if !volumeExists {
t.Fatalf("Added volume %q does not exist, it should.", volumeName)
}
}
func Test_AddVolume_Positive_ExistingVolume(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
vc.AddVolume(volumeName)
// Act
vc.AddVolume(volumeName)
// Assert
volumeExists := vc.VolumeExists(volumeName)
if !volumeExists {
t.Fatalf("Added volume %q does not exist, it should.", volumeName)
}
}
func Test_AddNode_Positive_NewNodeVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
vc.AddVolume(volumeName)
// Act
nodeErr := vc.AddNode(nodeName, volumeName)
// Assert
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
nodeExists, nodeExistsErr := vc.NodeExists(nodeName, volumeName)
if nodeExistsErr != nil {
t.Fatalf("NodeExists failed. Expected: <no error> Actual: <%v>", nodeExistsErr)
}
if !nodeExists {
t.Fatalf("Added node %q does not exist, it should.", nodeName)
}
}
func Test_AddNode_Positive_NodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
vc.AddVolume(volumeName)
nodeErr1 := vc.AddNode(nodeName, volumeName)
if nodeErr1 != nil {
t.Fatalf("First call to AddNode failed. Expected: <no error> Actual: <%v>", nodeErr1)
}
// Act
nodeErr2 := vc.AddNode(nodeName, volumeName)
// Assert
if nodeErr2 != nil {
t.Fatalf("Second call to AddNode failed. Expected: <no error> Actual: <%v>", nodeErr2)
}
nodeExists, nodeExistsErr := vc.NodeExists(nodeName, volumeName)
if nodeExistsErr != nil {
t.Fatalf("NodeExists failed. Expected: <no error> Actual: <%v>", nodeExistsErr)
}
if !nodeExists {
t.Fatalf("Added node %q does not exist, it should.", nodeName)
}
}
func Test_AddNode_Negative_NewNodeVolumeDoesntExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
// Act
nodeErr := vc.AddNode(nodeName, volumeName)
// Assert
if nodeErr == nil {
t.Fatalf("AddNode did not fail. Expected: <\"failed to add node...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
nodeExists, nodeExistsErr := vc.NodeExists(nodeName, volumeName)
if nodeExistsErr == nil {
t.Fatalf("NodeExists did not fail. Expected: <failed to check if node...no volume with that name exists in the list of managed volumes> Actual: <no error>")
}
if nodeExists {
t.Fatalf("Added node %q exists, it should not.", nodeName)
}
}
func Test_AddPod_Positive_NewPodNodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
nodeErr := vc.AddNode(nodeName, volumeName)
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
// Act
podErr := vc.AddPod(podName, nodeName, volumeName)
// Assert
if podErr != nil {
t.Fatalf("AddPod failed. Expected: <no error> Actual: <%v>", podErr)
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr != nil {
t.Fatalf("PodExists failed. Expected: <no error> Actual: <%v>", podExistsErr)
}
if !podExists {
t.Fatalf("Added pod %q does not exist, it should.", podName)
}
}
func Test_AddPod_Positive_PodExistsNodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
nodeErr := vc.AddNode(nodeName, volumeName)
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
podErr1 := vc.AddPod(podName, nodeName, volumeName)
if podErr1 != nil {
t.Fatalf("AddPod failed. Expected: <no error> Actual: <%v>", podErr1)
}
// Act
podErr2 := vc.AddPod(podName, nodeName, volumeName)
// Assert
if podErr2 != nil {
t.Fatalf("AddPod failed. Expected: <no error> Actual: <%v>", podErr2)
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr != nil {
t.Fatalf("PodExists failed. Expected: <no error> Actual: <%v>", podExistsErr)
}
if !podExists {
t.Fatalf("Added pod %q does not exist, it should.", podName)
}
}
func Test_AddPod_Negative_NewPodNodeDoesntExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
// Act
podErr := vc.AddPod(podName, nodeName, volumeName)
// Assert
if podErr == nil {
t.Fatalf("AddPod did not fail. Expected: <\"failed to add pod...no node with that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\"failed to check if pod exists...no node with that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
if podExists {
t.Fatalf("Added pod %q exists, it should not.", podName)
}
}
func Test_AddPod_Negative_NewPodNodeDoesntExistsVolumeDoesntExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
// Act
podErr := vc.AddPod(podName, nodeName, volumeName)
// Assert
if podErr == nil {
t.Fatalf("AddPod did not fail. Expected: <\"failed to add pod...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\"failed to check if node...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
if podExists {
t.Fatalf("Added pod %q exists, it should not.", podName)
}
}
func Test_VolumeExists_Positive_NonExistantVolume(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
notAddedVolumeName := "volume-not-added-name"
// Act
notAddedVolumeExists := vc.VolumeExists(notAddedVolumeName)
// Assert
if notAddedVolumeExists {
t.Fatalf("Not added volume %q exists, it should not.", notAddedVolumeName)
}
}
func Test_NodeExists_Positive_NonExistantNodeVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
notAddedNodeName := "node-not-added-name"
vc.AddVolume(volumeName)
// Act
notAddedNodeExists, notAddedNodeExistsErr := vc.NodeExists(notAddedNodeName, volumeName)
// Assert
if notAddedNodeExistsErr != nil {
t.Fatalf("NodeExists failed. Expected: <no error> Actual: <%v>", notAddedNodeExistsErr)
}
if notAddedNodeExists {
t.Fatalf("Not added node %q exists, it should not.", notAddedNodeName)
}
}
func Test_NodeExists_Negative_NonExistantNodeVolumeDoesntExist(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
notAddedNodeName := "node-not-added-name"
// Act
notAddedNodeExists, notAddedNodeExistsErr := vc.NodeExists(notAddedNodeName, volumeName)
// Assert
if notAddedNodeExistsErr == nil {
t.Fatalf("NodeExists did not fail. Expected: <failed to check if node...no volume with that name exists in the list of managed volumes> Actual: <no error>")
}
if notAddedNodeExists {
t.Fatalf("Added node %q exists, it should not.", notAddedNodeName)
}
}
func Test_PodExists_Positive_NonExistantPodNodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
notAddedPodName := "pod-not-added-name"
vc.AddVolume(volumeName)
addNodeErr := vc.AddNode(nodeName, volumeName)
if addNodeErr != nil {
t.Fatalf("AddNode for node %q failed. Expected: <no error> Actual: <%v>", nodeName, addNodeErr)
}
// Act
notAddedPodExists, notAddedPodExistsErr := vc.PodExists(notAddedPodName, nodeName, volumeName)
// Assert
if notAddedPodExistsErr != nil {
t.Fatalf("PodExists failed. Expected: <no error> Actual: <%v>", notAddedPodExistsErr)
}
if notAddedPodExists {
t.Fatalf("Not added pod %q exists, it should not.", notAddedPodName)
}
}
func Test_PodExists_Negative_NonExistantPodNodeDoesntExistVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
notAddedPodName := "pod-not-added-name"
vc.AddVolume(volumeName)
// Act
notAddedPodExists, notAddedPodExistsErr := vc.PodExists(notAddedPodName, nodeName, volumeName)
// Assert
if notAddedPodExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\"failed to check if pod exists...no node with that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
if notAddedPodExists {
t.Fatalf("Added pod %q exists, it should not.", notAddedPodName)
}
}
func Test_PodExists_Negative_NonExistantPodNodeDoesntExistVolumeDoesntExist(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
notAddedPodName := "pod-not-added-name"
// Act
notAddedPodExists, notAddedPodExistsErr := vc.PodExists(notAddedPodName, nodeName, volumeName)
// Assert
if notAddedPodExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\"failed to check if node...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
if notAddedPodExists {
t.Fatalf("Added pod %q exists, it should not.", notAddedPodName)
}
}
func Test_DeleteVolume_Positive_VolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
vc.AddVolume(volumeName)
// Act
deleteVolumeErr := vc.DeleteVolume(volumeName)
// Assert
if deleteVolumeErr != nil {
t.Fatalf("DeleteVolume failed. Expected: <no error> Actual: <%v>", deleteVolumeErr)
}
volumeExists := vc.VolumeExists(volumeName)
if volumeExists {
t.Fatalf("Deleted volume %q still exists, it should not.", volumeName)
}
}
func Test_DeleteVolume_Negative_VolumeDoesntExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
notAddedVolumeName := "volume-not-added-name"
// Act
deleteVolumeErr := vc.DeleteVolume(notAddedVolumeName)
// Assert
if deleteVolumeErr == nil {
t.Fatalf("DeleteVolume did not fail. Expected: <\"failed to delete volume...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
notAddedVolumeExists := vc.VolumeExists(notAddedVolumeName)
if notAddedVolumeExists {
t.Fatalf("Not added volume %q exists, it should not.", notAddedVolumeName)
}
}
func Test_DeleteNode_Positive_NodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
vc.AddVolume(volumeName)
nodeErr := vc.AddNode(nodeName, volumeName)
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
// Act
deleteNodeErr := vc.DeleteNode(nodeName, volumeName)
// Assert
if deleteNodeErr != nil {
t.Fatalf("DeleteNode failed. Expected: <no error> Actual: <%v>", deleteNodeErr)
}
nodeExists, nodeExistsErr := vc.NodeExists(nodeName, volumeName)
if nodeExistsErr != nil {
t.Fatalf("NodeExists failed. Expected: <no error> Actual: <%v>", nodeExistsErr)
}
if nodeExists {
t.Fatalf("Deleted node %q still exists, it should not.", nodeName)
}
}
func Test_DeleteNode_Negative_NodeDoesntExistVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
notAddedNodeName := "node-not-added-name"
vc.AddVolume(volumeName)
// Act
deleteNodeErr := vc.DeleteNode(notAddedNodeName, volumeName)
// Assert
if deleteNodeErr == nil {
t.Fatalf("DeleteNode did not fail. Expected: <\"failed to delete node...no node with the that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
notAddedNodeExists, notAddedNodeExistsErr := vc.NodeExists(notAddedNodeName, volumeName)
if notAddedNodeExistsErr != nil {
t.Fatalf("NodeExists failed. Expected: <no error> Actual: <%v>", notAddedNodeExistsErr)
}
if notAddedNodeExists {
t.Fatalf("Not added node %q exists, it should not.", notAddedNodeName)
}
}
func Test_DeleteNode_Negative_NodeDoesntExistVolumeDoesntExist(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
notAddedNodeName := "node-not-added-name"
// Act
deleteNodeErr := vc.DeleteNode(notAddedNodeName, volumeName)
// Assert
if deleteNodeErr == nil {
t.Fatalf("DeleteNode did not fail. Expected: <\"failed to delete node...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
notAddedNodeExists, notAddedNodeExistsErr := vc.NodeExists(notAddedNodeName, volumeName)
if notAddedNodeExistsErr == nil {
t.Fatalf("NodeExists did not fail. Expected: <\failed to check if node...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
if notAddedNodeExists {
t.Fatalf("Not added node %q exists, it should not.", notAddedNodeName)
}
}
func Test_DeletePod_Positive_PodExistsNodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
nodeErr := vc.AddNode(nodeName, volumeName)
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
podErr := vc.AddPod(podName, nodeName, volumeName)
if podErr != nil {
t.Fatalf("AddPod failed. Expected: <no error> Actual: <%v>", podErr)
}
// Act
deletePodErr := vc.DeletePod(podName, nodeName, volumeName)
// Assert
if deletePodErr != nil {
t.Fatalf("DeletePod failed. Expected: <no error> Actual: <%v>", podName)
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr != nil {
t.Fatalf("PodExists failed. Expected: <no error> Actual: <%v>", podExistsErr)
}
if podExists {
t.Fatalf("Deleted pod %q still exists, it should not.", podName)
}
}
func Test_DeletePod_Positive_PodDoesntExistNodeExistsVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
nodeErr := vc.AddNode(nodeName, volumeName)
if nodeErr != nil {
t.Fatalf("AddNode failed. Expected: <no error> Actual: <%v>", nodeErr)
}
// Act
deletePodErr := vc.DeletePod(podName, nodeName, volumeName)
// Assert
if deletePodErr == nil {
t.Fatalf("DeletePod did not fail. Expected: <\"failed to delete pod...no pod with that name exists in the list of scheduled pods under that node/volume\"> Actual: <no error>")
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr != nil {
t.Fatalf("PodExists failed. Expected: <no error> Actual: <%v>", podExistsErr)
}
if podExists {
t.Fatalf("Deleted pod %q still exists, it should not.", podName)
}
}
func Test_DeletePod_Positive_PodDoesntExistNodeDoesntExistVolumeExists(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
vc.AddVolume(volumeName)
// Act
deletePodErr := vc.DeletePod(podName, nodeName, volumeName)
// Assert
if deletePodErr == nil {
t.Fatalf("DeletePod did not fail. Expected: <\"failed to delete pod...no node with that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\failed to check if pod...no node with that name exists in the list of attached nodes for that volume\"> Actual: <no error>")
}
if podExists {
t.Fatalf("Deleted pod %q still exists, it should not.", podName)
}
}
func Test_DeletePod_Positive_PodDoesntExistNodeDoesntExistVolumeDoesntExist(t *testing.T) {
// Arrange
vc := NewAttachDetachVolumeCache()
volumeName := "volume-name"
nodeName := "node-name"
podName := "pod-name"
// Act
deletePodErr := vc.DeletePod(podName, nodeName, volumeName)
// Assert
if deletePodErr == nil {
t.Fatalf("DeletePod did not fail. Expected: <\"failed to delete pod...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
podExists, podExistsErr := vc.PodExists(podName, nodeName, volumeName)
if podExistsErr == nil {
t.Fatalf("PodExists did not fail. Expected: <\failed to check if pod...no volume with that name exists in the list of managed volumes\"> Actual: <no error>")
}
if podExists {
t.Fatalf("Deleted pod %q still exists, it should not.", podName)
}
}
/*
t.Fatalf("%q", notAddedNodeExistsErr)
*/