mirror of https://github.com/k3s-io/k3s
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
commit
2f1a9dd65c
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
*/
|
Loading…
Reference in New Issue