k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/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_SetVolumesMountedByNode_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 SetVolumesMountedByNode twice, first setting mounted to true then false. 694 // Verifies mountedByNode is false. 695 func Test_SetVolumesMountedByNode_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 asw.SetVolumesMountedByNode(logger, []v1.UniqueVolumeName{generatedVolumeName}, nodeName) 711 asw.SetVolumesMountedByNode(logger, nil, nodeName) 712 713 attachedVolumes := asw.GetAttachedVolumes() 714 if len(attachedVolumes) != 1 { 715 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 716 } 717 718 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 719 } 720 721 // Populates data struct with one volume/node entry. 722 // Calls SetVolumesMountedByNode once, setting mounted to false. 723 // Verifies mountedByNode is false because value is overwritten 724 func Test_SetVolumesMountedByNode_Positive_UnsetWithoutInitialSet(t *testing.T) { 725 // Arrange 726 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 727 asw := NewActualStateOfWorld(volumePluginMgr) 728 volumeName := v1.UniqueVolumeName("volume-name") 729 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 730 nodeName := types.NodeName("node-name") 731 devicePath := "fake/device/path" 732 logger, _ := ktesting.NewTestContext(t) 733 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 734 if addErr != nil { 735 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 736 } 737 738 attachedVolumes := asw.GetAttachedVolumes() 739 if len(attachedVolumes) != 1 { 740 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 741 } 742 743 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 744 745 // Act 746 asw.SetVolumesMountedByNode(logger, nil, nodeName) 747 748 // Assert 749 attachedVolumes = asw.GetAttachedVolumes() 750 if len(attachedVolumes) != 1 { 751 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 752 } 753 754 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 755 } 756 757 // Populates data struct with one volume/node entry. 758 // Calls SetVolumesMountedByNode twice, first setting mounted to true then false. 759 // Calls AddVolumeNode to readd the same volume/node. 760 // Verifies mountedByNode is false and detachRequestedTime is zero. 761 func Test_SetVolumesMountedByNode_Positive_UnsetWithInitialSetAddVolumeNodeNotReset(t *testing.T) { 762 // Arrange 763 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 764 asw := NewActualStateOfWorld(volumePluginMgr) 765 volumeName := v1.UniqueVolumeName("volume-name") 766 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 767 nodeName := types.NodeName("node-name") 768 devicePath := "fake/device/path" 769 logger, _ := ktesting.NewTestContext(t) 770 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 771 if addErr != nil { 772 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 773 } 774 775 // Act 776 asw.SetVolumesMountedByNode(logger, []v1.UniqueVolumeName{generatedVolumeName}, nodeName) 777 asw.SetVolumesMountedByNode(logger, nil, nodeName) 778 generatedVolumeName, addErr = asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 779 780 // Assert 781 if addErr != nil { 782 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 783 } 784 785 attachedVolumes := asw.GetAttachedVolumes() 786 if len(attachedVolumes) != 1 { 787 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 788 } 789 790 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 791 } 792 793 // Populates data struct with one volume/node entry. 794 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 795 // Calls SetVolumesMountedByNode() twice, first setting mounted to true then false. 796 // Verifies mountedByNode is false and detachRequestedTime is NOT zero. 797 func Test_SetVolumesMountedByNode_Positive_UnsetWithInitialSetVerifyDetachRequestedTimePerserved(t *testing.T) { 798 // Arrange 799 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 800 asw := NewActualStateOfWorld(volumePluginMgr) 801 volumeName := v1.UniqueVolumeName("volume-name") 802 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 803 nodeName := types.NodeName("node-name") 804 devicePath := "fake/device/path" 805 logger, _ := ktesting.NewTestContext(t) 806 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 807 if addErr != nil { 808 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 809 } 810 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 811 if err != nil { 812 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 813 } 814 err = asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 815 if err != nil { 816 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", err) 817 } 818 expectedDetachRequestedTime := asw.GetAttachedVolumes()[0].DetachRequestedTime 819 820 // Act 821 asw.SetVolumesMountedByNode(logger, []v1.UniqueVolumeName{generatedVolumeName}, nodeName) 822 asw.SetVolumesMountedByNode(logger, nil, nodeName) 823 824 // Assert 825 attachedVolumes := asw.GetAttachedVolumes() 826 if len(attachedVolumes) != 1 { 827 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 828 } 829 830 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 831 if !expectedDetachRequestedTime.Equal(attachedVolumes[0].DetachRequestedTime) { 832 t.Fatalf("DetachRequestedTime changed. Expected: <%v> Actual: <%v>", expectedDetachRequestedTime, attachedVolumes[0].DetachRequestedTime) 833 } 834 } 835 836 // Populates data struct with one volume/node entry. 837 // Verifies mountedByNode is true and detachRequestedTime is zero (default values). 838 func Test_RemoveVolumeFromReportAsAttached_Positive_Set(t *testing.T) { 839 // Arrange 840 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 841 asw := NewActualStateOfWorld(volumePluginMgr) 842 volumeName := v1.UniqueVolumeName("volume-name") 843 devicePath := "fake/device/path" 844 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 845 nodeName := types.NodeName("node-name") 846 logger, _ := ktesting.NewTestContext(t) 847 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 848 if addErr != nil { 849 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 850 } 851 852 // Act: do not mark -- test default value 853 854 // Assert 855 attachedVolumes := asw.GetAttachedVolumes() 856 if len(attachedVolumes) != 1 { 857 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 858 } 859 860 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 861 } 862 863 // Populates data struct with one volume/node entry. 864 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 865 // Verifies mountedByNode is true and detachRequestedTime is NOT zero. 866 func Test_RemoveVolumeFromReportAsAttached_Positive_Marked(t *testing.T) { 867 // Arrange 868 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 869 asw := NewActualStateOfWorld(volumePluginMgr) 870 volumeName := v1.UniqueVolumeName("volume-name") 871 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 872 nodeName := types.NodeName("node-name") 873 devicePath := "fake/device/path" 874 logger, _ := ktesting.NewTestContext(t) 875 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 876 if addErr != nil { 877 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 878 } 879 880 // Act 881 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 882 if err != nil { 883 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 884 } 885 markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 886 if markDesireToDetachErr != nil { 887 t.Fatalf("MarkDesireToDetach failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr) 888 } 889 890 // Assert 891 attachedVolumes := asw.GetAttachedVolumes() 892 if len(attachedVolumes) != 1 { 893 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 894 } 895 896 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 897 } 898 899 // Populates data struct with one volume/node entry. 900 // Calls MarkDesireToDetach() once on volume/node entry. 901 // Calls ResetDetachRequestTime() to reset the detach request time value back to 0. 902 // Verifies mountedByNode is true and detachRequestedTime is reset to zero. 903 func Test_MarkDesireToDetach_Positive_MarkedAddVolumeNodeReset(t *testing.T) { 904 // Arrange 905 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 906 asw := NewActualStateOfWorld(volumePluginMgr) 907 volumeName := v1.UniqueVolumeName("volume-name") 908 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 909 nodeName := types.NodeName("node-name") 910 devicePath := "fake/device/path" 911 logger, _ := ktesting.NewTestContext(t) 912 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 913 if addErr != nil { 914 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 915 } 916 917 // Act 918 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 919 if err != nil { 920 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 921 } 922 markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 923 // Reset detach request time to 0 924 asw.ResetDetachRequestTime(logger, generatedVolumeName, nodeName) 925 926 // Assert 927 if markDesireToDetachErr != nil { 928 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr) 929 } 930 if addErr != nil { 931 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 932 } 933 934 // Assert 935 attachedVolumes := asw.GetAttachedVolumes() 936 if len(attachedVolumes) != 1 { 937 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 938 } 939 940 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 941 } 942 943 // Populates data struct with one volume/node entry. 944 // Calls SetVolumesMountedByNode() twice, first setting mounted to true then false. 945 // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry. 946 // Verifies mountedByNode is false and detachRequestedTime is NOT zero. 947 func Test_RemoveVolumeFromReportAsAttached_Positive_UnsetWithInitialSetVolumesMountedByNodePreserved(t *testing.T) { 948 // Arrange 949 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 950 asw := NewActualStateOfWorld(volumePluginMgr) 951 volumeName := v1.UniqueVolumeName("volume-name") 952 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 953 nodeName := types.NodeName("node-name") 954 devicePath := "fake/device/path" 955 logger, _ := ktesting.NewTestContext(t) 956 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 957 if addErr != nil { 958 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 959 } 960 asw.SetVolumesMountedByNode(logger, []v1.UniqueVolumeName{generatedVolumeName}, nodeName) 961 asw.SetVolumesMountedByNode(logger, nil, nodeName) 962 // Act 963 _, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 964 if err != nil { 965 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 966 } 967 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 968 if removeVolumeDetachErr != nil { 969 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 970 } 971 972 // Assert 973 attachedVolumes := asw.GetAttachedVolumes() 974 if len(attachedVolumes) != 1 { 975 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 976 } 977 978 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */) 979 } 980 981 // Populates data struct with one volume/node entry. 982 // Calls RemoveVolumeFromReportAsAttached 983 // Verifies there is no volume as reported as attached 984 func Test_RemoveVolumeFromReportAsAttached(t *testing.T) { 985 // Arrange 986 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 987 asw := NewActualStateOfWorld(volumePluginMgr) 988 volumeName := v1.UniqueVolumeName("volume-name") 989 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 990 nodeName := types.NodeName("node-name") 991 devicePath := "fake/device/path" 992 logger, _ := ktesting.NewTestContext(t) 993 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 994 if addErr != nil { 995 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 996 } 997 998 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 999 if removeVolumeDetachErr != nil { 1000 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1001 } 1002 1003 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1004 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1005 if !exists { 1006 t.Fatalf("MarkDesireToDetach_UnmarkDesireToDetach failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1007 } 1008 if len(volumes) > 0 { 1009 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1010 } 1011 1012 } 1013 1014 // Populates data struct with one volume/node entry. 1015 // Calls RemoveVolumeFromReportAsAttached 1016 // Calls AddVolumeToReportAsAttached to add volume back as attached 1017 // Verifies there is one volume as reported as attached 1018 func Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive(t *testing.T) { 1019 // Arrange 1020 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1021 asw := NewActualStateOfWorld(volumePluginMgr) 1022 volumeName := v1.UniqueVolumeName("volume-name") 1023 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1024 nodeName := types.NodeName("node-name") 1025 devicePath := "fake/device/path" 1026 logger, _ := ktesting.NewTestContext(t) 1027 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1028 if addErr != nil { 1029 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1030 } 1031 1032 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1033 if removeVolumeDetachErr != nil { 1034 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1035 } 1036 1037 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1038 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1039 if !exists { 1040 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1041 } 1042 if len(volumes) > 0 { 1043 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1044 } 1045 1046 asw.AddVolumeToReportAsAttached(logger, generatedVolumeName, nodeName) 1047 reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger) 1048 volumes, exists = reportAsAttachedVolumesMap[nodeName] 1049 if !exists { 1050 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1051 } 1052 if len(volumes) != 1 { 1053 t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes)) 1054 } 1055 } 1056 1057 // Populates data struct with one volume/node entry. 1058 // Calls RemoveVolumeFromReportAsAttached 1059 // Calls DeleteVolumeNode 1060 // Calls AddVolumeNode 1061 // Verifies there is no volume as reported as attached 1062 func Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode(t *testing.T) { 1063 // Arrange 1064 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1065 asw := NewActualStateOfWorld(volumePluginMgr) 1066 volumeName := v1.UniqueVolumeName("volume-name") 1067 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1068 nodeName := types.NodeName("node-name") 1069 devicePath := "fake/device/path" 1070 logger, _ := ktesting.NewTestContext(t) 1071 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1072 if addErr != nil { 1073 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1074 } 1075 1076 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1077 if removeVolumeDetachErr != nil { 1078 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1079 } 1080 1081 reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger) 1082 volumes, exists := reportAsAttachedVolumesMap[nodeName] 1083 if !exists { 1084 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1085 } 1086 if len(volumes) > 0 { 1087 t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes)) 1088 } 1089 1090 asw.DeleteVolumeNode(generatedVolumeName, nodeName) 1091 1092 asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, "" /*device path*/, true) 1093 1094 reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger) 1095 volumes, exists = reportAsAttachedVolumesMap[nodeName] 1096 if !exists { 1097 t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName) 1098 } 1099 if len(volumes) != 1 { 1100 t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes)) 1101 } 1102 } 1103 1104 // Populates data struct with one volume/node entry. 1105 // Calls SetDetachRequestTime twice and sleep maxWaitTime (1 second) in between 1106 // The elapsed time returned from the first SetDetachRequestTime call should be smaller than maxWaitTime 1107 // The elapsed time returned from the second SetDetachRequestTime call should be larger than maxWaitTime 1108 func Test_SetDetachRequestTime_Positive(t *testing.T) { 1109 // Arrange 1110 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1111 asw := NewActualStateOfWorld(volumePluginMgr) 1112 volumeName := v1.UniqueVolumeName("volume-name") 1113 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1114 nodeName := types.NodeName("node-name") 1115 devicePath := "fake/device/path" 1116 logger, _ := ktesting.NewTestContext(t) 1117 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1118 if addErr != nil { 1119 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1120 } 1121 1122 maxWaitTime := 1 * time.Second 1123 etime, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 1124 if err != nil { 1125 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 1126 } 1127 if etime >= maxWaitTime { 1128 t.Logf("SetDetachRequestTim Expected: <elapsed time %v is smaller than maxWaitTime %v> Actual <elapsed time is larger than maxWaitTime>", etime, maxWaitTime) 1129 } 1130 // Sleep and call SetDetachRequestTime again 1131 time.Sleep(maxWaitTime) 1132 etime, err = asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName) 1133 if err != nil { 1134 t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err) 1135 } 1136 if etime < maxWaitTime { 1137 t.Fatalf("SetDetachRequestTim Expected: <elapsed time %v is larger than maxWaitTime %v> Actual <elapsed time is smaller>", etime, maxWaitTime) 1138 } 1139 } 1140 1141 func Test_GetAttachedVolumesForNode_Positive_NoVolumesOrNodes(t *testing.T) { 1142 // Arrange 1143 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1144 asw := NewActualStateOfWorld(volumePluginMgr) 1145 node := types.NodeName("random") 1146 1147 // Act 1148 attachedVolumes := asw.GetAttachedVolumesForNode(node) 1149 1150 // Assert 1151 if len(attachedVolumes) != 0 { 1152 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 1153 } 1154 } 1155 1156 func Test_GetAttachedVolumesForNode_Positive_OneVolumeOneNode(t *testing.T) { 1157 // Arrange 1158 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1159 asw := NewActualStateOfWorld(volumePluginMgr) 1160 volumeName := v1.UniqueVolumeName("volume-name") 1161 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1162 nodeName := types.NodeName("node-name") 1163 devicePath := "fake/device/path" 1164 logger, _ := ktesting.NewTestContext(t) 1165 generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1166 if addErr != nil { 1167 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr) 1168 } 1169 1170 // Act 1171 attachedVolumes := asw.GetAttachedVolumesForNode(nodeName) 1172 1173 // Assert 1174 if len(attachedVolumes) != 1 { 1175 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1176 } 1177 1178 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1179 } 1180 1181 func Test_GetAttachedVolumesForNode_Positive_TwoVolumeTwoNodes(t *testing.T) { 1182 // Arrange 1183 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1184 asw := NewActualStateOfWorld(volumePluginMgr) 1185 volume1Name := v1.UniqueVolumeName("volume1-name") 1186 volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name) 1187 node1Name := types.NodeName("node1-name") 1188 devicePath := "fake/device/path" 1189 logger, _ := ktesting.NewTestContext(t) 1190 _, add1Err := asw.AddVolumeNode(logger, volume1Name, volume1Spec, node1Name, devicePath, true) 1191 if add1Err != nil { 1192 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1193 } 1194 volume2Name := v1.UniqueVolumeName("volume2-name") 1195 volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name) 1196 node2Name := types.NodeName("node2-name") 1197 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volume2Name, volume2Spec, node2Name, devicePath, true) 1198 if add2Err != nil { 1199 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1200 } 1201 1202 // Act 1203 attachedVolumes := asw.GetAttachedVolumesForNode(node2Name) 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, generatedVolumeName2, string(volume2Name), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1211 } 1212 1213 func Test_GetAttachedVolumesForNode_Positive_OneVolumeTwoNodes(t *testing.T) { 1214 // Arrange 1215 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1216 asw := NewActualStateOfWorld(volumePluginMgr) 1217 volumeName := v1.UniqueVolumeName("volume-name") 1218 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1219 node1Name := types.NodeName("node1-name") 1220 devicePath := "fake/device/path" 1221 logger, _ := ktesting.NewTestContext(t) 1222 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1223 if err != nil || plugin == nil { 1224 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1225 } 1226 uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) 1227 if err != nil || plugin == nil { 1228 t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err) 1229 } 1230 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath, true) 1231 if add1Err != nil { 1232 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1233 } 1234 node2Name := types.NodeName("node2-name") 1235 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath, true) 1236 if add2Err != nil { 1237 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1238 } 1239 1240 if generatedVolumeName1 != generatedVolumeName2 { 1241 t.Fatalf( 1242 "Generated volume names for the same volume should be the same but they are not: %q and %q", 1243 generatedVolumeName1, 1244 generatedVolumeName2) 1245 } 1246 1247 // Act 1248 attachedVolumes := asw.GetAttachedVolumesForNode(node1Name) 1249 1250 // Assert 1251 if len(attachedVolumes) != 1 { 1252 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1253 } 1254 1255 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1256 } 1257 1258 func Test_OneVolumeTwoNodes_TwoDevicePaths(t *testing.T) { 1259 // Arrange 1260 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1261 asw := NewActualStateOfWorld(volumePluginMgr) 1262 volumeName := v1.UniqueVolumeName("volume-name") 1263 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1264 node1Name := types.NodeName("node1-name") 1265 devicePath1 := "fake/device/path1" 1266 logger, _ := ktesting.NewTestContext(t) 1267 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1268 if err != nil || plugin == nil { 1269 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1270 } 1271 uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) 1272 if err != nil || plugin == nil { 1273 t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err) 1274 } 1275 generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath1, true) 1276 if add1Err != nil { 1277 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err) 1278 } 1279 node2Name := types.NodeName("node2-name") 1280 devicePath2 := "fake/device/path2" 1281 generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath2, true) 1282 if add2Err != nil { 1283 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err) 1284 } 1285 1286 if generatedVolumeName1 != generatedVolumeName2 { 1287 t.Fatalf( 1288 "Generated volume names for the same volume should be the same but they are not: %q and %q", 1289 generatedVolumeName1, 1290 generatedVolumeName2) 1291 } 1292 1293 // Act 1294 attachedVolumes := asw.GetAttachedVolumesForNode(node2Name) 1295 1296 // Assert 1297 if len(attachedVolumes) != 1 { 1298 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1299 } 1300 1301 verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volumeName), node2Name, devicePath2, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1302 } 1303 1304 // Test_SetNodeStatusUpdateNeededError expects the map nodesToUpdateStatusFor 1305 // to be empty if the SetNodeStatusUpdateNeeded is called on a node that 1306 // does not exist in the actual state of the world 1307 func Test_SetNodeStatusUpdateNeededError(t *testing.T) { 1308 // Arrange 1309 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1310 asw := NewActualStateOfWorld(volumePluginMgr) 1311 nodeName := types.NodeName("node-1") 1312 1313 // Act 1314 logger, _ := ktesting.NewTestContext(t) 1315 asw.SetNodeStatusUpdateNeeded(logger, nodeName) 1316 1317 // Assert 1318 nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor() 1319 if len(nodesToUpdateStatusFor) != 0 { 1320 t.Fatalf("nodesToUpdateStatusFor should be empty as nodeName does not exist") 1321 } 1322 } 1323 1324 // Test_updateNodeStatusUpdateNeeded expects statusUpdateNeeded to be properly updated if 1325 // updateNodeStatusUpdateNeeded is called on a node that exists in the actual state of the world 1326 func Test_updateNodeStatusUpdateNeeded(t *testing.T) { 1327 // Arrange 1328 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1329 asw := &actualStateOfWorld{ 1330 attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume), 1331 nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor), 1332 volumePluginMgr: volumePluginMgr, 1333 } 1334 nodeName := types.NodeName("node-1") 1335 nodeToUpdate := nodeToUpdateStatusFor{ 1336 nodeName: nodeName, 1337 statusUpdateNeeded: true, 1338 volumesToReportAsAttached: make(map[v1.UniqueVolumeName]v1.UniqueVolumeName), 1339 } 1340 asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate 1341 1342 // Act 1343 err := asw.updateNodeStatusUpdateNeeded(nodeName, false) 1344 1345 // Assert 1346 if err != nil { 1347 t.Fatalf("updateNodeStatusUpdateNeeded should not return error, but got: %v", err) 1348 } 1349 nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor() 1350 if nodesToUpdateStatusFor[nodeName].statusUpdateNeeded { 1351 t.Fatalf("nodesToUpdateStatusFor should be updated to: false, but got: true") 1352 } 1353 } 1354 1355 // Test_updateNodeStatusUpdateNeededError expects statusUpdateNeeded to report error if 1356 // updateNodeStatusUpdateNeeded is called on a node that does not exist in the actual state of the world 1357 func Test_updateNodeStatusUpdateNeededError(t *testing.T) { 1358 // Arrange 1359 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1360 asw := &actualStateOfWorld{ 1361 attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume), 1362 nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor), 1363 volumePluginMgr: volumePluginMgr, 1364 } 1365 nodeName := types.NodeName("node-1") 1366 1367 // Act 1368 err := asw.updateNodeStatusUpdateNeeded(nodeName, false) 1369 1370 // Assert 1371 if err == nil { 1372 t.Fatalf("updateNodeStatusUpdateNeeded should return error, but got nothing") 1373 } 1374 } 1375 1376 // Mark a volume as attached to a node. 1377 // Verify GetAttachState returns AttachedState 1378 // Verify GetAttachedVolumes return this volume 1379 func Test_MarkVolumeAsAttached(t *testing.T) { 1380 // Arrange 1381 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1382 asw := NewActualStateOfWorld(volumePluginMgr) 1383 volumeName := v1.UniqueVolumeName("volume-name") 1384 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1385 1386 nodeName := types.NodeName("node-name") 1387 devicePath := "fake/device/path" 1388 1389 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1390 if err != nil || plugin == nil { 1391 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1392 } 1393 1394 // Act 1395 logger, _ := ktesting.NewTestContext(t) 1396 err = asw.MarkVolumeAsAttached(logger, volumeName, volumeSpec, nodeName, devicePath) 1397 1398 // Assert 1399 if err != nil { 1400 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err) 1401 } 1402 1403 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 1404 if volumeNodeComboState != AttachStateAttached { 1405 t.Fatalf("asw says the volume: %q is not attached (%v) to node:%q, it should.", 1406 volumeName, AttachStateAttached, nodeName) 1407 } 1408 attachedVolumes := asw.GetAttachedVolumes() 1409 if len(attachedVolumes) != 1 { 1410 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1411 } 1412 verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1413 } 1414 1415 // Mark a volume as attachment as uncertain. 1416 // Verify GetAttachState returns UncertainState 1417 // Verify GetAttachedVolumes return this volume 1418 func Test_MarkVolumeAsUncertain(t *testing.T) { 1419 // Arrange 1420 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1421 asw := NewActualStateOfWorld(volumePluginMgr) 1422 volumeName := v1.UniqueVolumeName("volume-name") 1423 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1424 nodeName := types.NodeName("node-name") 1425 1426 plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec) 1427 if err != nil || plugin == nil { 1428 t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err) 1429 } 1430 1431 // Act 1432 logger, _ := ktesting.NewTestContext(t) 1433 err = asw.MarkVolumeAsUncertain(logger, volumeName, volumeSpec, nodeName) 1434 1435 // Assert 1436 if err != nil { 1437 t.Fatalf("MarkVolumeAsUncertain failed. Expected: <no error> Actual: <%v>", err) 1438 } 1439 volumeNodeComboState := asw.GetAttachState(volumeName, nodeName) 1440 if volumeNodeComboState != AttachStateUncertain { 1441 t.Fatalf("asw says the volume: %q is attached (%v) to node:%q, it should not.", 1442 volumeName, volumeNodeComboState, nodeName) 1443 } 1444 attachedVolumes := asw.GetAttachedVolumes() 1445 if len(attachedVolumes) != 1 { 1446 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1447 } 1448 verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, "", true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) 1449 } 1450 1451 // Calls AddVolumeNode() once with attached set to true. 1452 // Verifies GetVolumesToReportAttachedForNode has an update for the node. 1453 // Call GetVolumesToReportAttachedForNode a second time for the node, verify it does not report 1454 // an update is needed any more 1455 // Then calls RemoveVolumeFromReportAsAttached() 1456 // Verifies GetVolumesToReportAttachedForNode reports an update is needed 1457 func Test_GetVolumesToReportAttachedForNode_Positive(t *testing.T) { 1458 // Arrange 1459 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1460 asw := NewActualStateOfWorld(volumePluginMgr) 1461 volumeName := v1.UniqueVolumeName("volume-name") 1462 volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName) 1463 1464 nodeName := types.NodeName("node-name") 1465 devicePath := "fake/device/path" 1466 1467 // Act 1468 logger, _ := ktesting.NewTestContext(t) 1469 generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true) 1470 1471 // Assert 1472 if err != nil { 1473 t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err) 1474 } 1475 1476 needsUpdate, attachedVolumes := asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1477 if !needsUpdate { 1478 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) 1479 } 1480 if len(attachedVolumes) != 1 { 1481 t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes)) 1482 } 1483 1484 needsUpdate, _ = asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1485 if needsUpdate { 1486 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) 1487 } 1488 1489 removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName) 1490 if removeVolumeDetachErr != nil { 1491 t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr) 1492 } 1493 1494 needsUpdate, attachedVolumes = asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1495 if !needsUpdate { 1496 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) 1497 } 1498 if len(attachedVolumes) != 0 { 1499 t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes)) 1500 } 1501 } 1502 1503 // Verifies GetVolumesToReportAttachedForNode reports no update needed for an unknown node. 1504 func Test_GetVolumesToReportAttachedForNode_UnknownNode(t *testing.T) { 1505 // Arrange 1506 volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) 1507 asw := NewActualStateOfWorld(volumePluginMgr) 1508 nodeName := types.NodeName("node-name") 1509 logger, _ := ktesting.NewTestContext(t) 1510 needsUpdate, _ := asw.GetVolumesToReportAttachedForNode(logger, nodeName) 1511 if needsUpdate { 1512 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) 1513 } 1514 } 1515 1516 func verifyAttachedVolume( 1517 t *testing.T, 1518 attachedVolumes []AttachedVolume, 1519 expectedVolumeName v1.UniqueVolumeName, 1520 expectedVolumeSpecName string, 1521 expectedNodeName types.NodeName, 1522 expectedDevicePath string, 1523 expectedMountedByNode, 1524 expectNonZeroDetachRequestedTime bool) { 1525 for _, attachedVolume := range attachedVolumes { 1526 if attachedVolume.VolumeName == expectedVolumeName && 1527 attachedVolume.VolumeSpec.Name() == expectedVolumeSpecName && 1528 attachedVolume.NodeName == expectedNodeName && 1529 attachedVolume.DevicePath == expectedDevicePath && 1530 attachedVolume.MountedByNode == expectedMountedByNode && 1531 attachedVolume.DetachRequestedTime.IsZero() == !expectNonZeroDetachRequestedTime { 1532 return 1533 } 1534 } 1535 1536 t.Fatalf( 1537 "attachedVolumes (%v) should contain the volume/node combo %q/%q with DevicePath=%q MountedByNode=%v and NonZeroDetachRequestedTime=%v. It does not.", 1538 attachedVolumes, 1539 expectedVolumeName, 1540 expectedNodeName, 1541 expectedDevicePath, 1542 expectedMountedByNode, 1543 expectNonZeroDetachRequestedTime) 1544 }