k8s.io/kubernetes@v1.29.3/pkg/controller/volume/attachdetach/cache/actual_state_of_world_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cache 18 19 import ( 20 "testing" 21 "time" 22 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/apimachinery/pkg/types" 25 "k8s.io/klog/v2/ktesting" 26 controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing" 27 volumetesting "k8s.io/kubernetes/pkg/volume/testing" 28 volumeutil "k8s.io/kubernetes/pkg/volume/util" 29 ) 30 31 // Calls AddVolumeNode() once with attached set to true. 32 // Verifies a single volume/node entry exists. 33 func Test_AddVolumeNode_Positive_NewVolumeNewNode(t *testing.T) { 34 // Arrange 35 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 36 asw := NewActualStateOfWorld(volumePluginMgr) 37 volumeName := v1.UniqueVolumeName("volume-name") 38 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 39 40 nodeName := types.NodeName("node-name") 41 devicePath := "fake/device/path" 42 43 // Act 44 logger, _ := ktesting.NewTestContext(t) 45 generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 46 47 // Assert 48 if err != nil { 49 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err) 50 } 51 52 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName) 53 if volumeNodeComboState != AttachStateAttached { 54 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState) 55 } 56 57 attachedVolumes := asw.GetAttachedVolumes() 58 if len(attachedVolumes) != 1 { 59 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 60 } 61 62 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 63 } 64 65 // Calls AddVolumeNode() once with attached set to false. 66 // Verifies a single volume/node entry exists. 67 // Then calls AddVolumeNode() with attached set to true 68 // Verifies volume is attached to the node according to asw. 69 func Test_AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached(t *testing.T) { 70 // Arrange 71 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 72 asw := NewActualStateOfWorld(volumePluginMgr) 73 volumeName := v1.UniqueVolumeName("volume-name") 74 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 75 76 nodeName := types.NodeName("node-name") 77 devicePath := "fake/device/path" 78 79 // Act 80 logger, _ := ktesting.NewTestContext(t) 81 generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, false) 82 83 // Assert 84 if err != nil { 85 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err) 86 } 87 88 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName) 89 if volumeNodeComboState != AttachStateUncertain { 90 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Uncertain'.", generatedVolumeName, nodeName, volumeNodeComboState) 91 } 92 93 allVolumes := asw.GetAttachedVolumes() 94 if len(allVolumes) != 1 { 95 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(allVolumes)) 96 } 97 verifyAttachedVolume(t, allVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 98 99 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 100 _, exists := reportAsAttachedVolumesMap[nodeName] 101 if exists { 102 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", nodeName) 103 } 104 105 volumesForNode := asw.GetAttachedVolumesForNode(nodeName) 106 if len(volumesForNode) != 1 { 107 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(volumesForNode)) 108 } 109 verifyAttachedVolume(t, volumesForNode, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 110 111 attachedVolumesMap := asw.GetAttachedVolumesPerNode() 112 _, exists = attachedVolumesMap[nodeName] 113 if exists { 114 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", nodeName) 115 } 116 117 nodes := asw.GetNodesForAttachedVolume(volumeName) 118 if len(nodes) > 0 { 119 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect no nodes returned.") 120 } 121 122 // Add the volume to the node second time with attached set to true 123 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 124 125 // Assert 126 if add2Err != nil { 127 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 128 } 129 130 if generatedVolumeName != generatedVolumeName2 { 131 t.Fatalf( 132 "Generated volume names for the same volume should be the same but they are not: %q and %q", 133 generatedVolumeName, 134 generatedVolumeName2) 135 } 136 137 volumeNodeComboState = asw.GetAttachState(generatedVolumeName, nodeName) 138 if volumeNodeComboState != AttachStateAttached { 139 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState) 140 } 141 142 attachedVolumes := asw.GetAttachedVolumes() 143 if len(attachedVolumes) != 1 { 144 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 145 } 146 147 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 148 149 nodes = asw.GetNodesForAttachedVolume(volumeName) 150 if len(nodes) != 1 { 151 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect one node returned.") 152 } 153 if nodes[0] != nodeName { 154 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect node %v, Actual node %v", nodeName, nodes[0]) 155 } 156 157 attachedVolumesMap = asw.GetAttachedVolumesPerNode() 158 _, exists = attachedVolumesMap[nodeName] 159 if !exists { 160 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q does not exist> Expect: <node does exist in the reportedAsAttached map", nodeName) 161 } 162 163 } 164 165 // Calls AddVolumeNode() once with attached set to false. 166 // Verifies a single volume/node entry exists. 167 // Then calls AddVolumeNode() to attach the volume to a different node with attached set to true 168 // Verifies volume is attached to the node according to asw. 169 func Test_AddVolumeNode_Positive_NewVolumeTwoNodesWithFalseAttached(t *testing.T) { 170 // Arrange 171 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 172 asw := NewActualStateOfWorld(volumePluginMgr) 173 volumeName := v1.UniqueVolumeName("volume-name") 174 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 175 176 node1Name := types.NodeName("node1-name") 177 node2Name := types.NodeName("node2-name") 178 devicePath := "fake/device/path" 179 180 // Act 181 logger, _ := ktesting.NewTestContext(t) 182 generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, false) 183 184 // Assert 185 if err != nil { 186 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err) 187 } 188 189 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, node1Name) 190 if volumeNodeComboState != AttachStateUncertain { 191 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Uncertain'.", generatedVolumeName, node1Name, volumeNodeComboState) 192 } 193 194 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true) 195 196 // Assert 197 if add2Err != nil { 198 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 199 } 200 201 if generatedVolumeName != generatedVolumeName2 { 202 t.Fatalf( 203 "Generated volume names for the same volume should be the same but they are not: %q and %q", 204 generatedVolumeName, 205 generatedVolumeName2) 206 } 207 208 volumeNodeComboState = asw.GetAttachState(generatedVolumeName, node2Name) 209 if volumeNodeComboState != AttachStateAttached { 210 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, node2Name, volumeNodeComboState) 211 } 212 213 attachedVolumes := asw.GetAttachedVolumes() 214 if len(attachedVolumes) != 2 { 215 t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes)) 216 } 217 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 218 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 219 220 volumesForNode := asw.GetAttachedVolumesForNode(node2Name) 221 if len(volumesForNode) != 1 { 222 t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(volumesForNode)) 223 } 224 verifyAttachedVolume(t, volumesForNode, generatedVolumeName, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 225 226 attachedVolumesMap := asw.GetAttachedVolumesPerNode() 227 attachedVolumesPerNode, exists := attachedVolumesMap[node2Name] 228 if !exists || len(attachedVolumesPerNode) != 1 { 229 t.Fatalf("AddVolumeNode_Positive_NewVolumeTwoNodesWithFalseAttached failed. Actual: <node %q does not exist> Expect: <node does exist in the reportedAsAttached map", node2Name) 230 } 231 232 nodes := asw.GetNodesForAttachedVolume(volumeName) 233 if len(nodes) != 1 { 234 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect one node returned.") 235 } 236 237 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 238 reportedVolumes, exists := reportAsAttachedVolumesMap[node2Name] 239 if !exists || len(reportedVolumes) != 1 { 240 t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", node2Name) 241 } 242 } 243 244 // Calls AddVolumeNode() twice. Second time use a different node name. 245 // Verifies two volume/node entries exist with the same volumeSpec. 246 func Test_AddVolumeNode_Positive_ExistingVolumeNewNode(t *testing.T) { 247 // Arrange 248 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 249 asw := NewActualStateOfWorld(volumePluginMgr) 250 volumeName := v1.UniqueVolumeName("volume-name") 251 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 252 node1Name := types.NodeName("node1-name") 253 node2Name := types.NodeName("node2-name") 254 devicePath := "fake/device/path" 255 256 // Act 257 logger, _ := ktesting.NewTestContext(t) 258 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true) 259 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true) 260 261 // Assert 262 if add1Err != nil { 263 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 264 } 265 if add2Err != nil { 266 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 267 } 268 269 if generatedVolumeName1 != generatedVolumeName2 { 270 t.Fatalf( 271 "Generated volume names for the same volume should be the same but they are not: %q and %q", 272 generatedVolumeName1, 273 generatedVolumeName2) 274 } 275 276 volumeNode1ComboState := asw.GetAttachState(generatedVolumeName1, node1Name) 277 if volumeNode1ComboState != AttachStateAttached { 278 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node1Name, volumeNode1ComboState) 279 } 280 281 volumeNode2ComboState := asw.GetAttachState(generatedVolumeName1, node2Name) 282 if volumeNode2ComboState != AttachStateAttached { 283 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node2Name, volumeNode2ComboState) 284 } 285 286 attachedVolumes := asw.GetAttachedVolumes() 287 if len(attachedVolumes) != 2 { 288 t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes)) 289 } 290 291 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 292 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 293 } 294 295 // Calls AddVolumeNode() twice. Uses the same volume and node both times. 296 // Verifies a single volume/node entry exists. 297 func Test_AddVolumeNode_Positive_ExistingVolumeExistingNode(t *testing.T) { 298 // Arrange 299 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 300 asw := NewActualStateOfWorld(volumePluginMgr) 301 volumeName := v1.UniqueVolumeName("volume-name") 302 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 303 nodeName := types.NodeName("node-name") 304 devicePath := "fake/device/path" 305 306 // Act 307 logger, _ := ktesting.NewTestContext(t) 308 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 309 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 310 311 // Assert 312 if add1Err != nil { 313 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 314 } 315 if add2Err != nil { 316 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 317 } 318 319 if generatedVolumeName1 != generatedVolumeName2 { 320 t.Fatalf( 321 "Generated volume names for the same volume should be the same but they are not: %q and %q", 322 generatedVolumeName1, 323 generatedVolumeName2) 324 } 325 326 volumeNodeComboState := asw.GetAttachState(generatedVolumeName1, nodeName) 327 if volumeNodeComboState != AttachStateAttached { 328 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, nodeName, volumeNodeComboState) 329 } 330 331 attachedVolumes := asw.GetAttachedVolumes() 332 if len(attachedVolumes) != 1 { 333 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 334 } 335 336 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 337 } 338 339 // Populates data struct with one volume/node entry. 340 // Calls DeleteVolumeNode() to delete volume/node. 341 // Verifies no volume/node entries exists. 342 func Test_DeleteVolumeNode_Positive_VolumeExistsNodeExists(t *testing.T) { 343 // Arrange 344 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 345 asw := NewActualStateOfWorld(volumePluginMgr) 346 volumeName := v1.UniqueVolumeName("volume-name") 347 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 348 nodeName := types.NodeName("node-name") 349 devicePath := "fake/device/path" 350 logger, _ := ktesting.NewTestContext(t) 351 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 352 if addErr != nil { 353 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 354 } 355 356 // Act 357 asw.DeleteVolumeNode(generatedVolumeName, nodeName) 358 359 // Assert 360 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName) 361 if volumeNodeComboState != AttachStateDetached { 362 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName, nodeName, volumeNodeComboState) 363 } 364 365 attachedVolumes := asw.GetAttachedVolumes() 366 if len(attachedVolumes) != 0 { 367 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 368 } 369 } 370 371 // Calls DeleteVolumeNode() to delete volume/node on empty data struct 372 // Verifies no volume/node entries exists. 373 func Test_DeleteVolumeNode_Positive_VolumeDoesntExistNodeDoesntExist(t *testing.T) { 374 // Arrange 375 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 376 asw := NewActualStateOfWorld(volumePluginMgr) 377 volumeName := v1.UniqueVolumeName("volume-name") 378 nodeName := types.NodeName("node-name") 379 380 // Act 381 asw.DeleteVolumeNode(volumeName, nodeName) 382 383 // Assert 384 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 385 if volumeNodeComboState != AttachStateDetached { 386 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", volumeName, nodeName, volumeNodeComboState) 387 } 388 389 attachedVolumes := asw.GetAttachedVolumes() 390 if len(attachedVolumes) != 0 { 391 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 392 } 393 } 394 395 // Populates data struct with two volume/node entries the second one using a 396 // different node. 397 // Calls DeleteVolumeNode() to delete first volume/node. 398 // Verifies only second volume/node entry exists. 399 func Test_DeleteVolumeNode_Positive_TwoNodesOneDeleted(t *testing.T) { 400 // Arrange 401 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 402 asw := NewActualStateOfWorld(volumePluginMgr) 403 volumeName := v1.UniqueVolumeName("volume-name") 404 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 405 node1Name := types.NodeName("node1-name") 406 node2Name := types.NodeName("node2-name") 407 devicePath := "fake/device/path" 408 logger, _ := ktesting.NewTestContext(t) 409 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true) 410 if add1Err != nil { 411 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 412 } 413 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true) 414 if add2Err != nil { 415 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 416 } 417 if generatedVolumeName1 != generatedVolumeName2 { 418 t.Fatalf( 419 "Generated volume names for the same volume should be the same but they are not: %q and %q", 420 generatedVolumeName1, 421 generatedVolumeName2) 422 } 423 424 // Act 425 asw.DeleteVolumeNode(generatedVolumeName1, node1Name) 426 427 // Assert 428 volumeNodeComboState := asw.GetAttachState(generatedVolumeName1, node1Name) 429 if volumeNodeComboState != AttachStateDetached { 430 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName1, node1Name, volumeNodeComboState) 431 } 432 433 volumeNodeComboState = asw.GetAttachState(generatedVolumeName1, node2Name) 434 if volumeNodeComboState != AttachStateAttached { 435 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node2Name, volumeNodeComboState) 436 } 437 438 attachedVolumes := asw.GetAttachedVolumes() 439 if len(attachedVolumes) != 1 { 440 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 441 } 442 443 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 444 } 445 446 // Populates data struct with one volume/node entry. 447 // Calls GetAttachState() to verify entry. 448 // Verifies the populated volume/node entry exists. 449 func Test_VolumeNodeExists_Positive_VolumeExistsNodeExists(t *testing.T) { 450 // Arrange 451 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 452 asw := NewActualStateOfWorld(volumePluginMgr) 453 volumeName := v1.UniqueVolumeName("volume-name") 454 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 455 nodeName := types.NodeName("node-name") 456 devicePath := "fake/device/path" 457 logger, _ := ktesting.NewTestContext(t) 458 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 459 if addErr != nil { 460 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 461 } 462 463 // Act 464 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName) 465 466 // Assert 467 if volumeNodeComboState != AttachStateAttached { 468 t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState) 469 } 470 471 attachedVolumes := asw.GetAttachedVolumes() 472 if len(attachedVolumes) != 1 { 473 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 474 } 475 476 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 477 } 478 479 // Populates data struct with one volume1/node1 entry. 480 // Calls GetAttachState() with volume1/node2. 481 // Verifies requested entry does not exist, but populated entry does. 482 func Test_VolumeNodeExists_Positive_VolumeExistsNodeDoesntExist(t *testing.T) { 483 // Arrange 484 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 485 asw := NewActualStateOfWorld(volumePluginMgr) 486 volumeName := v1.UniqueVolumeName("volume-name") 487 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 488 node1Name := types.NodeName("node1-name") 489 node2Name := types.NodeName("node2-name") 490 devicePath := "fake/device/path" 491 logger, _ := ktesting.NewTestContext(t) 492 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true) 493 if addErr != nil { 494 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 495 } 496 497 // Act 498 volumeNodeComboState := asw.GetAttachState(generatedVolumeName, node2Name) 499 500 // Assert 501 if volumeNodeComboState != AttachStateDetached { 502 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName, node2Name, volumeNodeComboState) 503 } 504 505 attachedVolumes := asw.GetAttachedVolumes() 506 if len(attachedVolumes) != 1 { 507 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 508 } 509 510 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 511 } 512 513 // Calls GetAttachState() on empty data struct. 514 // Verifies requested entry does not exist. 515 func Test_VolumeNodeExists_Positive_VolumeAndNodeDontExist(t *testing.T) { 516 // Arrange 517 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 518 asw := NewActualStateOfWorld(volumePluginMgr) 519 volumeName := v1.UniqueVolumeName("volume-name") 520 nodeName := types.NodeName("node-name") 521 522 // Act 523 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 524 525 // Assert 526 if volumeNodeComboState != AttachStateDetached { 527 t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", volumeName, nodeName, volumeNodeComboState) 528 } 529 530 attachedVolumes := asw.GetAttachedVolumes() 531 if len(attachedVolumes) != 0 { 532 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 533 } 534 } 535 536 // Calls GetAttachedVolumes() on empty data struct. 537 // Verifies no volume/node entries are returned. 538 func Test_GetAttachedVolumes_Positive_NoVolumesOrNodes(t *testing.T) { 539 // Arrange 540 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 541 asw := NewActualStateOfWorld(volumePluginMgr) 542 543 // Act 544 attachedVolumes := asw.GetAttachedVolumes() 545 546 // Assert 547 if len(attachedVolumes) != 0 { 548 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 549 } 550 } 551 552 // Populates data struct with one volume/node entry. 553 // Calls GetAttachedVolumes() to get list of entries. 554 // Verifies one volume/node entry is returned. 555 func Test_GetAttachedVolumes_Positive_OneVolumeOneNode(t *testing.T) { 556 // Arrange 557 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 558 asw := NewActualStateOfWorld(volumePluginMgr) 559 volumeName := v1.UniqueVolumeName("volume-name") 560 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 561 nodeName := types.NodeName("node-name") 562 devicePath := "fake/device/path" 563 logger, _ := ktesting.NewTestContext(t) 564 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 565 if addErr != nil { 566 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 567 } 568 569 // Act 570 attachedVolumes := asw.GetAttachedVolumes() 571 572 // Assert 573 if len(attachedVolumes) != 1 { 574 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 575 } 576 577 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 578 } 579 580 // Populates data struct with two volume/node entries (different node and volume). 581 // Calls GetAttachedVolumes() to get list of entries. 582 // Verifies both volume/node entries are returned. 583 func Test_GetAttachedVolumes_Positive_TwoVolumeTwoNodes(t *testing.T) { 584 // Arrange 585 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 586 asw := NewActualStateOfWorld(volumePluginMgr) 587 volume1Name := v1.UniqueVolumeName("volume1-name") 588 volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name) 589 node1Name := types.NodeName("node1-name") 590 devicePath := "fake/device/path" 591 logger, _ := ktesting.NewTestContext(t) 592 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volume1Name, volume1Spec, node1Name, devicePath, true) 593 if add1Err != nil { 594 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 595 } 596 volume2Name := v1.UniqueVolumeName("volume2-name") 597 volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name) 598 node2Name := types.NodeName("node2-name") 599 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volume2Name, volume2Spec, node2Name, devicePath, true) 600 if add2Err != nil { 601 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 602 } 603 604 // Act 605 attachedVolumes := asw.GetAttachedVolumes() 606 607 // Assert 608 if len(attachedVolumes) != 2 { 609 t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes)) 610 } 611 612 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volume1Name), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 613 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volume2Name), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 614 } 615 616 // Populates data struct with two volume/node entries (same volume different node). 617 // Calls GetAttachedVolumes() to get list of entries. 618 // Verifies both volume/node entries are returned. 619 func Test_GetAttachedVolumes_Positive_OneVolumeTwoNodes(t *testing.T) { 620 // Arrange 621 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 622 asw := NewActualStateOfWorld(volumePluginMgr) 623 volumeName := v1.UniqueVolumeName("volume-name") 624 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 625 node1Name := types.NodeName("node1-name") 626 devicePath := "fake/device/path" 627 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 628 if err != nil || plugin == nil { 629 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 630 } 631 uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) 632 if err != nil || plugin == nil { 633 t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err) 634 } 635 logger, _ := ktesting.NewTestContext(t) 636 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath, true) 637 if add1Err != nil { 638 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 639 } 640 node2Name := types.NodeName("node2-name") 641 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath, true) 642 if add2Err != nil { 643 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 644 } 645 646 if generatedVolumeName1 != generatedVolumeName2 { 647 t.Fatalf( 648 "Generated volume names for the same volume should be the same but they are not: %q and %q", 649 generatedVolumeName1, 650 generatedVolumeName2) 651 } 652 653 // Act 654 attachedVolumes := asw.GetAttachedVolumes() 655 656 // Assert 657 if len(attachedVolumes) != 2 { 658 t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes)) 659 } 660 661 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 662 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 663 } 664 665 // Populates data struct with one volume/node entry. 666 // Verifies mountedByNode is true and DetachRequestedTime is zero. 667 func Test_SetVolumeMountedByNode_Positive_Set(t *testing.T) { 668 // Arrange 669 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 670 asw := NewActualStateOfWorld(volumePluginMgr) 671 volumeName := v1.UniqueVolumeName("volume-name") 672 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 673 nodeName := types.NodeName("node-name") 674 devicePath := "fake/device/path" 675 logger, _ := ktesting.NewTestContext(t) 676 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 677 if addErr != nil { 678 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 679 } 680 681 // Act: do not mark -- test default value 682 683 // Assert 684 attachedVolumes := asw.GetAttachedVolumes() 685 if len(attachedVolumes) != 1 { 686 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 687 } 688 689 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 690 } 691 692 // Populates data struct with one volume/node entry. 693 // Calls SetVolumeMountedByNode twice, first setting mounted to true then false. 694 // Verifies mountedByNode is false. 695 func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSet(t *testing.T) { 696 // Arrange 697 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 698 asw := NewActualStateOfWorld(volumePluginMgr) 699 volumeName := v1.UniqueVolumeName("volume-name") 700 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 701 nodeName := types.NodeName("node-name") 702 devicePath := "fake/device/path" 703 logger, _ := ktesting.NewTestContext(t) 704 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 705 if addErr != nil { 706 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 707 } 708 709 // Act 710 setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */) 711 setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */) 712 713 // Assert 714 if setVolumeMountedErr1 != nil { 715 t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1) 716 } 717 if setVolumeMountedErr2 != nil { 718 t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2) 719 } 720 721 attachedVolumes := asw.GetAttachedVolumes() 722 if len(attachedVolumes) != 1 { 723 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 724 } 725 726 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 727 } 728 729 // Populates data struct with one volume/node entry. 730 // Calls SetVolumeMountedByNode once, setting mounted to false. 731 // Verifies mountedByNode is false because value is overwritten 732 func Test_SetVolumeMountedByNode_Positive_UnsetWithoutInitialSet(t *testing.T) { 733 // Arrange 734 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 735 asw := NewActualStateOfWorld(volumePluginMgr) 736 volumeName := v1.UniqueVolumeName("volume-name") 737 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 738 nodeName := types.NodeName("node-name") 739 devicePath := "fake/device/path" 740 logger, _ := ktesting.NewTestContext(t) 741 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 742 if addErr != nil { 743 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 744 } 745 746 attachedVolumes := asw.GetAttachedVolumes() 747 if len(attachedVolumes) != 1 { 748 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 749 } 750 751 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 752 753 // Act 754 setVolumeMountedErr := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */) 755 756 // Assert 757 if setVolumeMountedErr != nil { 758 t.Fatalf("SetVolumeMountedByNode failed. Expected <no error> Actual: <%v>", setVolumeMountedErr) 759 } 760 761 attachedVolumes = asw.GetAttachedVolumes() 762 if len(attachedVolumes) != 1 { 763 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 764 } 765 766 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 767 } 768 769 // Populates data struct with one volume/node entry. 770 // Calls SetVolumeMountedByNode twice, first setting mounted to true then false. 771 // Calls AddVolumeNode to readd the same volume/node. 772 // Verifies mountedByNode is false and detachRequestedTime is zero. 773 func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSetAddVolumeNodeNotReset(t *testing.T) { 774 // Arrange 775 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 776 asw := NewActualStateOfWorld(volumePluginMgr) 777 volumeName := v1.UniqueVolumeName("volume-name") 778 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 779 nodeName := types.NodeName("node-name") 780 devicePath := "fake/device/path" 781 logger, _ := ktesting.NewTestContext(t) 782 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 783 if addErr != nil { 784 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 785 } 786 787 // Act 788 setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */) 789 setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */) 790 generatedVolumeName, addErr = asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 791 792 // Assert 793 if setVolumeMountedErr1 != nil { 794 t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1) 795 } 796 if setVolumeMountedErr2 != nil { 797 t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2) 798 } 799 if addErr != nil { 800 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 801 } 802 803 attachedVolumes := asw.GetAttachedVolumes() 804 if len(attachedVolumes) != 1 { 805 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 806 } 807 808 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 809 } 810 811 // Populates data struct with one volume/node entry. 812 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 813 // Calls SetVolumeMountedByNode() twice, first setting mounted to true then false. 814 // Verifies mountedByNode is false and detachRequestedTime is NOT zero. 815 func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSetVerifyDetachRequestedTimePerserved(t *testing.T) { 816 // Arrange 817 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 818 asw := NewActualStateOfWorld(volumePluginMgr) 819 volumeName := v1.UniqueVolumeName("volume-name") 820 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 821 nodeName := types.NodeName("node-name") 822 devicePath := "fake/device/path" 823 logger, _ := ktesting.NewTestContext(t) 824 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 825 if addErr != nil { 826 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 827 } 828 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 829 if err != nil { 830 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 831 } 832 err = asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 833 if err != nil { 834 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", err) 835 } 836 expectedDetachRequestedTime := asw.GetAttachedVolumes()[0].DetachRequestedTime 837 838 // Act 839 setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */) 840 setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */) 841 842 // Assert 843 if setVolumeMountedErr1 != nil { 844 t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1) 845 } 846 if setVolumeMountedErr2 != nil { 847 t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2) 848 } 849 850 attachedVolumes := asw.GetAttachedVolumes() 851 if len(attachedVolumes) != 1 { 852 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 853 } 854 855 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 856 if !expectedDetachRequestedTime.Equal(attachedVolumes[0].DetachRequestedTime) { 857 t.Fatalf("DetachRequestedTime changed. Expected: <%v> Actual: <%v>", expectedDetachRequestedTime, attachedVolumes[0].DetachRequestedTime) 858 } 859 } 860 861 // Populates data struct with one volume/node entry. 862 // Verifies mountedByNode is true and detachRequestedTime is zero (default values). 863 func Test_RemoveVolumeFromReportAsAttached_Positive_Set(t *testing.T) { 864 // Arrange 865 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 866 asw := NewActualStateOfWorld(volumePluginMgr) 867 volumeName := v1.UniqueVolumeName("volume-name") 868 devicePath := "fake/device/path" 869 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 870 nodeName := types.NodeName("node-name") 871 logger, _ := ktesting.NewTestContext(t) 872 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 873 if addErr != nil { 874 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 875 } 876 877 // Act: do not mark -- test default value 878 879 // Assert 880 attachedVolumes := asw.GetAttachedVolumes() 881 if len(attachedVolumes) != 1 { 882 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 883 } 884 885 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 886 } 887 888 // Populates data struct with one volume/node entry. 889 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 890 // Verifies mountedByNode is true and detachRequestedTime is NOT zero. 891 func Test_RemoveVolumeFromReportAsAttached_Positive_Marked(t *testing.T) { 892 // Arrange 893 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 894 asw := NewActualStateOfWorld(volumePluginMgr) 895 volumeName := v1.UniqueVolumeName("volume-name") 896 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 897 nodeName := types.NodeName("node-name") 898 devicePath := "fake/device/path" 899 logger, _ := ktesting.NewTestContext(t) 900 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 901 if addErr != nil { 902 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 903 } 904 905 // Act 906 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 907 if err != nil { 908 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 909 } 910 markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 911 if markDesireToDetachErr != nil { 912 t.Fatalf("MarkDesireToDetach failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr) 913 } 914 915 // Assert 916 attachedVolumes := asw.GetAttachedVolumes() 917 if len(attachedVolumes) != 1 { 918 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 919 } 920 921 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 922 } 923 924 // Populates data struct with one volume/node entry. 925 // Calls MarkDesireToDetach() once on volume/node entry. 926 // Calls ResetDetachRequestTime() to reset the detach request time value back to 0. 927 // Verifies mountedByNode is true and detachRequestedTime is reset to zero. 928 func Test_MarkDesireToDetach_Positive_MarkedAddVolumeNodeReset(t *testing.T) { 929 // Arrange 930 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 931 asw := NewActualStateOfWorld(volumePluginMgr) 932 volumeName := v1.UniqueVolumeName("volume-name") 933 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 934 nodeName := types.NodeName("node-name") 935 devicePath := "fake/device/path" 936 logger, _ := ktesting.NewTestContext(t) 937 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 938 if addErr != nil { 939 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 940 } 941 942 // Act 943 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 944 if err != nil { 945 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 946 } 947 markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 948 // Reset detach request time to 0 949 asw.ResetDetachRequestTime(logger, generatedVolumeName, nodeName) 950 951 // Assert 952 if markDesireToDetachErr != nil { 953 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr) 954 } 955 if addErr != nil { 956 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 957 } 958 959 // Assert 960 attachedVolumes := asw.GetAttachedVolumes() 961 if len(attachedVolumes) != 1 { 962 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 963 } 964 965 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 966 } 967 968 // Populates data struct with one volume/node entry. 969 // Calls SetVolumeMountedByNode() twice, first setting mounted to true then false. 970 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 971 // Verifies mountedByNode is false and detachRequestedTime is NOT zero. 972 func Test_RemoveVolumeFromReportAsAttached_Positive_UnsetWithInitialSetVolumeMountedByNodePreserved(t *testing.T) { 973 // Arrange 974 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 975 asw := NewActualStateOfWorld(volumePluginMgr) 976 volumeName := v1.UniqueVolumeName("volume-name") 977 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 978 nodeName := types.NodeName("node-name") 979 devicePath := "fake/device/path" 980 logger, _ := ktesting.NewTestContext(t) 981 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 982 if addErr != nil { 983 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 984 } 985 setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */) 986 setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */) 987 if setVolumeMountedErr1 != nil { 988 t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1) 989 } 990 if setVolumeMountedErr2 != nil { 991 t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2) 992 } 993 994 // Act 995 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 996 if err != nil { 997 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 998 } 999 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1000 if removeVolumeDetachErr != nil { 1001 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1002 } 1003 1004 // Assert 1005 attachedVolumes := asw.GetAttachedVolumes() 1006 if len(attachedVolumes) != 1 { 1007 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1008 } 1009 1010 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 1011 } 1012 1013 // Populates data struct with one volume/node entry. 1014 // Calls RemoveVolumeFromReportAsAttached 1015 // Verifies there is no volume as reported as attached 1016 func Test_RemoveVolumeFromReportAsAttached(t *testing.T) { 1017 // Arrange 1018 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1019 asw := NewActualStateOfWorld(volumePluginMgr) 1020 volumeName := v1.UniqueVolumeName("volume-name") 1021 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1022 nodeName := types.NodeName("node-name") 1023 devicePath := "fake/device/path" 1024 logger, _ := ktesting.NewTestContext(t) 1025 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1026 if addErr != nil { 1027 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1028 } 1029 1030 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1031 if removeVolumeDetachErr != nil { 1032 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1033 } 1034 1035 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1036 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1037 if !exists { 1038 t.Fatalf("MarkDesireToDetach_UnmarkDesireToDetach failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1039 } 1040 if len(volumes) > 0 { 1041 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1042 } 1043 1044 } 1045 1046 // Populates data struct with one volume/node entry. 1047 // Calls RemoveVolumeFromReportAsAttached 1048 // Calls AddVolumeToReportAsAttached to add volume back as attached 1049 // Verifies there is one volume as reported as attached 1050 func Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive(t *testing.T) { 1051 // Arrange 1052 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1053 asw := NewActualStateOfWorld(volumePluginMgr) 1054 volumeName := v1.UniqueVolumeName("volume-name") 1055 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1056 nodeName := types.NodeName("node-name") 1057 devicePath := "fake/device/path" 1058 logger, _ := ktesting.NewTestContext(t) 1059 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1060 if addErr != nil { 1061 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1062 } 1063 1064 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1065 if removeVolumeDetachErr != nil { 1066 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1067 } 1068 1069 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1070 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1071 if !exists { 1072 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1073 } 1074 if len(volumes) > 0 { 1075 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1076 } 1077 1078 asw.AddVolumeToReportAsAttached(logger, generatedVolumeName, nodeName) 1079 reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger) 1080 volumes, exists = reportAsAttachedVolumesMap[nodeName] 1081 if !exists { 1082 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1083 } 1084 if len(volumes) != 1 { 1085 t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes)) 1086 } 1087 } 1088 1089 // Populates data struct with one volume/node entry. 1090 // Calls RemoveVolumeFromReportAsAttached 1091 // Calls DeleteVolumeNode 1092 // Calls AddVolumeNode 1093 // Verifies there is no volume as reported as attached 1094 func Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode(t *testing.T) { 1095 // Arrange 1096 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1097 asw := NewActualStateOfWorld(volumePluginMgr) 1098 volumeName := v1.UniqueVolumeName("volume-name") 1099 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1100 nodeName := types.NodeName("node-name") 1101 devicePath := "fake/device/path" 1102 logger, _ := ktesting.NewTestContext(t) 1103 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1104 if addErr != nil { 1105 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1106 } 1107 1108 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1109 if removeVolumeDetachErr != nil { 1110 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1111 } 1112 1113 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1114 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1115 if !exists { 1116 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1117 } 1118 if len(volumes) > 0 { 1119 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1120 } 1121 1122 asw.DeleteVolumeNode(generatedVolumeName, nodeName) 1123 1124 asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, "" /*device path*/, true) 1125 1126 reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger) 1127 volumes, exists = reportAsAttachedVolumesMap[nodeName] 1128 if !exists { 1129 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1130 } 1131 if len(volumes) != 1 { 1132 t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes)) 1133 } 1134 } 1135 1136 // Populates data struct with one volume/node entry. 1137 // Calls SetDetachRequestTime twice and sleep maxWaitTime (1 second) in between 1138 // The elapsed time returned from the first SetDetachRequestTime call should be smaller than maxWaitTime 1139 // The elapsed time returned from the second SetDetachRequestTime call should be larger than maxWaitTime 1140 func Test_SetDetachRequestTime_Positive(t *testing.T) { 1141 // Arrange 1142 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1143 asw := NewActualStateOfWorld(volumePluginMgr) 1144 volumeName := v1.UniqueVolumeName("volume-name") 1145 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1146 nodeName := types.NodeName("node-name") 1147 devicePath := "fake/device/path" 1148 logger, _ := ktesting.NewTestContext(t) 1149 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1150 if addErr != nil { 1151 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1152 } 1153 1154 maxWaitTime := 1 * time.Second 1155 etime, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 1156 if err != nil { 1157 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 1158 } 1159 if etime >= maxWaitTime { 1160 t.Logf("SetDetachRequestTim Expected: <elapsed time %v is smaller than maxWaitTime %v> Actual <elapsed time is larger than maxWaitTime>", etime, maxWaitTime) 1161 } 1162 // Sleep and call SetDetachRequestTime again 1163 time.Sleep(maxWaitTime) 1164 etime, err = asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 1165 if err != nil { 1166 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 1167 } 1168 if etime < maxWaitTime { 1169 t.Fatalf("SetDetachRequestTim Expected: <elapsed time %v is larger than maxWaitTime %v> Actual <elapsed time is smaller>", etime, maxWaitTime) 1170 } 1171 } 1172 1173 func Test_GetAttachedVolumesForNode_Positive_NoVolumesOrNodes(t *testing.T) { 1174 // Arrange 1175 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1176 asw := NewActualStateOfWorld(volumePluginMgr) 1177 node := types.NodeName("random") 1178 1179 // Act 1180 attachedVolumes := asw.GetAttachedVolumesForNode(node) 1181 1182 // Assert 1183 if len(attachedVolumes) != 0 { 1184 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 1185 } 1186 } 1187 1188 func Test_GetAttachedVolumesForNode_Positive_OneVolumeOneNode(t *testing.T) { 1189 // Arrange 1190 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1191 asw := NewActualStateOfWorld(volumePluginMgr) 1192 volumeName := v1.UniqueVolumeName("volume-name") 1193 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1194 nodeName := types.NodeName("node-name") 1195 devicePath := "fake/device/path" 1196 logger, _ := ktesting.NewTestContext(t) 1197 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1198 if addErr != nil { 1199 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1200 } 1201 1202 // Act 1203 attachedVolumes := asw.GetAttachedVolumesForNode(nodeName) 1204 1205 // Assert 1206 if len(attachedVolumes) != 1 { 1207 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1208 } 1209 1210 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1211 } 1212 1213 func Test_GetAttachedVolumesForNode_Positive_TwoVolumeTwoNodes(t *testing.T) { 1214 // Arrange 1215 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1216 asw := NewActualStateOfWorld(volumePluginMgr) 1217 volume1Name := v1.UniqueVolumeName("volume1-name") 1218 volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name) 1219 node1Name := types.NodeName("node1-name") 1220 devicePath := "fake/device/path" 1221 logger, _ := ktesting.NewTestContext(t) 1222 _, add1Err := asw.AddVolumeNode(logger, volume1Name, volume1Spec, node1Name, devicePath, true) 1223 if add1Err != nil { 1224 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1225 } 1226 volume2Name := v1.UniqueVolumeName("volume2-name") 1227 volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name) 1228 node2Name := types.NodeName("node2-name") 1229 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volume2Name, volume2Spec, node2Name, devicePath, true) 1230 if add2Err != nil { 1231 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1232 } 1233 1234 // Act 1235 attachedVolumes := asw.GetAttachedVolumesForNode(node2Name) 1236 1237 // Assert 1238 if len(attachedVolumes) != 1 { 1239 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1240 } 1241 1242 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volume2Name), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1243 } 1244 1245 func Test_GetAttachedVolumesForNode_Positive_OneVolumeTwoNodes(t *testing.T) { 1246 // Arrange 1247 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1248 asw := NewActualStateOfWorld(volumePluginMgr) 1249 volumeName := v1.UniqueVolumeName("volume-name") 1250 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1251 node1Name := types.NodeName("node1-name") 1252 devicePath := "fake/device/path" 1253 logger, _ := ktesting.NewTestContext(t) 1254 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1255 if err != nil || plugin == nil { 1256 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1257 } 1258 uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) 1259 if err != nil || plugin == nil { 1260 t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err) 1261 } 1262 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath, true) 1263 if add1Err != nil { 1264 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1265 } 1266 node2Name := types.NodeName("node2-name") 1267 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath, true) 1268 if add2Err != nil { 1269 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1270 } 1271 1272 if generatedVolumeName1 != generatedVolumeName2 { 1273 t.Fatalf( 1274 "Generated volume names for the same volume should be the same but they are not: %q and %q", 1275 generatedVolumeName1, 1276 generatedVolumeName2) 1277 } 1278 1279 // Act 1280 attachedVolumes := asw.GetAttachedVolumesForNode(node1Name) 1281 1282 // Assert 1283 if len(attachedVolumes) != 1 { 1284 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1285 } 1286 1287 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1288 } 1289 1290 func Test_OneVolumeTwoNodes_TwoDevicePaths(t *testing.T) { 1291 // Arrange 1292 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1293 asw := NewActualStateOfWorld(volumePluginMgr) 1294 volumeName := v1.UniqueVolumeName("volume-name") 1295 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1296 node1Name := types.NodeName("node1-name") 1297 devicePath1 := "fake/device/path1" 1298 logger, _ := ktesting.NewTestContext(t) 1299 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1300 if err != nil || plugin == nil { 1301 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1302 } 1303 uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) 1304 if err != nil || plugin == nil { 1305 t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err) 1306 } 1307 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath1, true) 1308 if add1Err != nil { 1309 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1310 } 1311 node2Name := types.NodeName("node2-name") 1312 devicePath2 := "fake/device/path2" 1313 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath2, true) 1314 if add2Err != nil { 1315 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1316 } 1317 1318 if generatedVolumeName1 != generatedVolumeName2 { 1319 t.Fatalf( 1320 "Generated volume names for the same volume should be the same but they are not: %q and %q", 1321 generatedVolumeName1, 1322 generatedVolumeName2) 1323 } 1324 1325 // Act 1326 attachedVolumes := asw.GetAttachedVolumesForNode(node2Name) 1327 1328 // Assert 1329 if len(attachedVolumes) != 1 { 1330 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1331 } 1332 1333 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volumeName), node2Name, devicePath2, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1334 } 1335 1336 // Test_SetNodeStatusUpdateNeededError expects the map nodesToUpdateStatusFor 1337 // to be empty if the SetNodeStatusUpdateNeeded is called on a node that 1338 // does not exist in the actual state of the world 1339 func Test_SetNodeStatusUpdateNeededError(t *testing.T) { 1340 // Arrange 1341 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1342 asw := NewActualStateOfWorld(volumePluginMgr) 1343 nodeName := types.NodeName("node-1") 1344 1345 // Act 1346 logger, _ := ktesting.NewTestContext(t) 1347 asw.SetNodeStatusUpdateNeeded(logger, nodeName) 1348 1349 // Assert 1350 nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor() 1351 if len(nodesToUpdateStatusFor) != 0 { 1352 t.Fatalf("nodesToUpdateStatusFor should be empty as nodeName does not exist") 1353 } 1354 } 1355 1356 // Test_updateNodeStatusUpdateNeeded expects statusUpdateNeeded to be properly updated if 1357 // updateNodeStatusUpdateNeeded is called on a node that exists in the actual state of the world 1358 func Test_updateNodeStatusUpdateNeeded(t *testing.T) { 1359 // Arrange 1360 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1361 asw := &actualStateOfWorld{ 1362 attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume), 1363 nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor), 1364 volumePluginMgr: volumePluginMgr, 1365 } 1366 nodeName := types.NodeName("node-1") 1367 nodeToUpdate := nodeToUpdateStatusFor{ 1368 nodeName: nodeName, 1369 statusUpdateNeeded: true, 1370 volumesToReportAsAttached: make(map[v1.UniqueVolumeName]v1.UniqueVolumeName), 1371 } 1372 asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate 1373 1374 // Act 1375 err := asw.updateNodeStatusUpdateNeeded(nodeName, false) 1376 1377 // Assert 1378 if err != nil { 1379 t.Fatalf("updateNodeStatusUpdateNeeded should not return error, but got: %v", err) 1380 } 1381 nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor() 1382 if nodesToUpdateStatusFor[nodeName].statusUpdateNeeded { 1383 t.Fatalf("nodesToUpdateStatusFor should be updated to: false, but got: true") 1384 } 1385 } 1386 1387 // Test_updateNodeStatusUpdateNeededError expects statusUpdateNeeded to report error if 1388 // updateNodeStatusUpdateNeeded is called on a node that does not exist in the actual state of the world 1389 func Test_updateNodeStatusUpdateNeededError(t *testing.T) { 1390 // Arrange 1391 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1392 asw := &actualStateOfWorld{ 1393 attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume), 1394 nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor), 1395 volumePluginMgr: volumePluginMgr, 1396 } 1397 nodeName := types.NodeName("node-1") 1398 1399 // Act 1400 err := asw.updateNodeStatusUpdateNeeded(nodeName, false) 1401 1402 // Assert 1403 if err == nil { 1404 t.Fatalf("updateNodeStatusUpdateNeeded should return error, but got nothing") 1405 } 1406 } 1407 1408 // Mark a volume as attached to a node. 1409 // Verify GetAttachState returns AttachedState 1410 // Verify GetAttachedVolumes return this volume 1411 func Test_MarkVolumeAsAttached(t *testing.T) { 1412 // Arrange 1413 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1414 asw := NewActualStateOfWorld(volumePluginMgr) 1415 volumeName := v1.UniqueVolumeName("volume-name") 1416 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1417 1418 nodeName := types.NodeName("node-name") 1419 devicePath := "fake/device/path" 1420 1421 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1422 if err != nil || plugin == nil { 1423 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1424 } 1425 1426 // Act 1427 logger, _ := ktesting.NewTestContext(t) 1428 err = asw.MarkVolumeAsAttached(logger, volumeName, volumeSpec, nodeName, devicePath) 1429 1430 // Assert 1431 if err != nil { 1432 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err) 1433 } 1434 1435 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 1436 if volumeNodeComboState != AttachStateAttached { 1437 t.Fatalf("asw says the volume: %q is not attached (%v) to node:%q, it should.", 1438 volumeName, AttachStateAttached, nodeName) 1439 } 1440 attachedVolumes := asw.GetAttachedVolumes() 1441 if len(attachedVolumes) != 1 { 1442 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1443 } 1444 verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1445 } 1446 1447 // Mark a volume as attachment as uncertain. 1448 // Verify GetAttachState returns UncertainState 1449 // Verify GetAttachedVolumes return this volume 1450 func Test_MarkVolumeAsUncertain(t *testing.T) { 1451 // Arrange 1452 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1453 asw := NewActualStateOfWorld(volumePluginMgr) 1454 volumeName := v1.UniqueVolumeName("volume-name") 1455 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1456 nodeName := types.NodeName("node-name") 1457 1458 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1459 if err != nil || plugin == nil { 1460 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1461 } 1462 1463 // Act 1464 logger, _ := ktesting.NewTestContext(t) 1465 err = asw.MarkVolumeAsUncertain(logger, volumeName, volumeSpec, nodeName) 1466 1467 // Assert 1468 if err != nil { 1469 t.Fatalf("MarkVolumeAsUncertain failed. Expected: <no error> Actual: <%v>", err) 1470 } 1471 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 1472 if volumeNodeComboState != AttachStateUncertain { 1473 t.Fatalf("asw says the volume: %q is attached (%v) to node:%q, it should not.", 1474 volumeName, volumeNodeComboState, nodeName) 1475 } 1476 attachedVolumes := asw.GetAttachedVolumes() 1477 if len(attachedVolumes) != 1 { 1478 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1479 } 1480 verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, "", true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1481 } 1482 1483 // Calls AddVolumeNode() once with attached set to true. 1484 // Verifies GetVolumesToReportAttachedForNode has an update for the node. 1485 // Call GetVolumesToReportAttachedForNode a second time for the node, verify it does not report 1486 // an update is needed any more 1487 // Then calls RemoveVolumeFromReportAsAttached() 1488 // Verifies GetVolumesToReportAttachedForNode reports an update is needed 1489 func Test_GetVolumesToReportAttachedForNode_Positive(t *testing.T) { 1490 // Arrange 1491 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1492 asw := NewActualStateOfWorld(volumePluginMgr) 1493 volumeName := v1.UniqueVolumeName("volume-name") 1494 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1495 1496 nodeName := types.NodeName("node-name") 1497 devicePath := "fake/device/path" 1498 1499 // Act 1500 logger, _ := ktesting.NewTestContext(t) 1501 generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1502 1503 // Assert 1504 if err != nil { 1505 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err) 1506 } 1507 1508 needsUpdate, attachedVolumes := asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1509 if !needsUpdate { 1510 t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q does not need an update> Expect: <node exists in the reportedAsAttached map and needs an update", nodeName) 1511 } 1512 if len(attachedVolumes) != 1 { 1513 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1514 } 1515 1516 needsUpdate, _ = asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1517 if needsUpdate { 1518 t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q needs an update> Expect: <node exists in the reportedAsAttached map and does not need an update", nodeName) 1519 } 1520 1521 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1522 if removeVolumeDetachErr != nil { 1523 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1524 } 1525 1526 needsUpdate, attachedVolumes = asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1527 if !needsUpdate { 1528 t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q does not need an update> Expect: <node exists in the reportedAsAttached map and needs an update", nodeName) 1529 } 1530 if len(attachedVolumes) != 0 { 1531 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 1532 } 1533 } 1534 1535 // Verifies GetVolumesToReportAttachedForNode reports no update needed for an unknown node. 1536 func Test_GetVolumesToReportAttachedForNode_UnknownNode(t *testing.T) { 1537 // Arrange 1538 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1539 asw := NewActualStateOfWorld(volumePluginMgr) 1540 nodeName := types.NodeName("node-name") 1541 logger, _ := ktesting.NewTestContext(t) 1542 needsUpdate, _ := asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1543 if needsUpdate { 1544 t.Fatalf("GetVolumesToReportAttachedForNode_UnknownNode failed. Actual: <node %q needs an update> Expect: <node does not exist in the reportedAsAttached map and does not need an update", nodeName) 1545 } 1546 } 1547 1548 func verifyAttachedVolume( 1549 t *testing.T, 1550 attachedVolumes []AttachedVolume, 1551 expectedVolumeName v1.UniqueVolumeName, 1552 expectedVolumeSpecName string, 1553 expectedNodeName types.NodeName, 1554 expectedDevicePath string, 1555 expectedMountedByNode, 1556 expectNonZeroDetachRequestedTime bool) { 1557 for _, attachedVolume := range attachedVolumes { 1558 if attachedVolume.VolumeName == expectedVolumeName && 1559 attachedVolume.VolumeSpec.Name() == expectedVolumeSpecName && 1560 attachedVolume.NodeName == expectedNodeName && 1561 attachedVolume.DevicePath == expectedDevicePath && 1562 attachedVolume.MountedByNode == expectedMountedByNode && 1563 attachedVolume.DetachRequestedTime.IsZero() == !expectNonZeroDetachRequestedTime { 1564 return 1565 } 1566 } 1567 1568 t.Fatalf( 1569 "attachedVolumes (%v) should contain the volume/node combo %q/%q with DevicePath=%q MountedByNode=%v and NonZeroDetachRequestedTime=%v. It does not.", 1570 attachedVolumes, 1571 expectedVolumeName, 1572 expectedNodeName, 1573 expectedDevicePath, 1574 expectedMountedByNode, 1575 expectNonZeroDetachRequestedTime) 1576 }