github.com/gophercloud/gophercloud@v1.11.0/openstack/baremetal/v1/nodes/testing/requests_test.go (about) 1 package testing 2 3 import ( 4 "testing" 5 6 "github.com/gophercloud/gophercloud" 7 "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" 8 "github.com/gophercloud/gophercloud/pagination" 9 th "github.com/gophercloud/gophercloud/testhelper" 10 "github.com/gophercloud/gophercloud/testhelper/client" 11 ) 12 13 func TestListDetailNodes(t *testing.T) { 14 th.SetupHTTP() 15 defer th.TeardownHTTP() 16 HandleNodeListDetailSuccessfully(t) 17 18 pages := 0 19 err := nodes.ListDetail(client.ServiceClient(), nodes.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { 20 pages++ 21 22 actual, err := nodes.ExtractNodes(page) 23 if err != nil { 24 return false, err 25 } 26 27 if len(actual) != 3 { 28 t.Fatalf("Expected 3 nodes, got %d", len(actual)) 29 } 30 th.CheckDeepEquals(t, NodeFoo, actual[0]) 31 th.CheckDeepEquals(t, NodeBar, actual[1]) 32 th.CheckDeepEquals(t, NodeBaz, actual[2]) 33 34 return true, nil 35 }) 36 37 th.AssertNoErr(t, err) 38 39 if pages != 1 { 40 t.Errorf("Expected 1 page, saw %d", pages) 41 } 42 } 43 44 func TestListNodes(t *testing.T) { 45 th.SetupHTTP() 46 defer th.TeardownHTTP() 47 HandleNodeListSuccessfully(t) 48 49 pages := 0 50 err := nodes.List(client.ServiceClient(), nodes.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { 51 pages++ 52 53 actual, err := nodes.ExtractNodes(page) 54 if err != nil { 55 return false, err 56 } 57 58 if len(actual) != 3 { 59 t.Fatalf("Expected 3 nodes, got %d", len(actual)) 60 } 61 th.AssertEquals(t, "foo", actual[0].Name) 62 th.AssertEquals(t, "bar", actual[1].Name) 63 th.AssertEquals(t, "baz", actual[2].Name) 64 65 return true, nil 66 }) 67 68 th.AssertNoErr(t, err) 69 70 if pages != 1 { 71 t.Errorf("Expected 1 page, saw %d", pages) 72 } 73 } 74 75 func TestListOpts(t *testing.T) { 76 // Detail cannot take Fields 77 opts := nodes.ListOpts{ 78 Fields: []string{"name", "uuid"}, 79 } 80 81 _, err := opts.ToNodeListDetailQuery() 82 th.AssertEquals(t, err.Error(), "fields is not a valid option when getting a detailed listing of nodes") 83 84 // Regular ListOpts can 85 query, err := opts.ToNodeListQuery() 86 th.AssertEquals(t, query, "?fields=name&fields=uuid") 87 th.AssertNoErr(t, err) 88 } 89 90 func TestCreateNode(t *testing.T) { 91 th.SetupHTTP() 92 defer th.TeardownHTTP() 93 HandleNodeCreationSuccessfully(t, SingleNodeBody) 94 95 actual, err := nodes.Create(client.ServiceClient(), nodes.CreateOpts{ 96 Name: "foo", 97 Driver: "ipmi", 98 BootInterface: "pxe", 99 DriverInfo: map[string]interface{}{ 100 "ipmi_port": "6230", 101 "ipmi_username": "admin", 102 "deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz", 103 "ipmi_address": "192.168.122.1", 104 "deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz", 105 "ipmi_password": "admin", 106 }, 107 }).Extract() 108 th.AssertNoErr(t, err) 109 110 th.CheckDeepEquals(t, NodeFoo, *actual) 111 } 112 113 func TestDeleteNode(t *testing.T) { 114 th.SetupHTTP() 115 defer th.TeardownHTTP() 116 HandleNodeDeletionSuccessfully(t) 117 118 res := nodes.Delete(client.ServiceClient(), "asdfasdfasdf") 119 th.AssertNoErr(t, res.Err) 120 } 121 122 func TestGetNode(t *testing.T) { 123 th.SetupHTTP() 124 defer th.TeardownHTTP() 125 HandleNodeGetSuccessfully(t) 126 127 c := client.ServiceClient() 128 actual, err := nodes.Get(c, "1234asdf").Extract() 129 if err != nil { 130 t.Fatalf("Unexpected Get error: %v", err) 131 } 132 133 th.CheckDeepEquals(t, NodeFoo, *actual) 134 } 135 136 func TestUpdateNode(t *testing.T) { 137 th.SetupHTTP() 138 defer th.TeardownHTTP() 139 HandleNodeUpdateSuccessfully(t, SingleNodeBody) 140 141 c := client.ServiceClient() 142 actual, err := nodes.Update(c, "1234asdf", nodes.UpdateOpts{ 143 nodes.UpdateOperation{ 144 Op: nodes.ReplaceOp, 145 Path: "/properties", 146 Value: map[string]interface{}{ 147 "root_gb": 25, 148 }, 149 }, 150 }).Extract() 151 if err != nil { 152 t.Fatalf("Unexpected Update error: %v", err) 153 } 154 155 th.CheckDeepEquals(t, NodeFoo, *actual) 156 } 157 158 func TestUpdateRequiredOp(t *testing.T) { 159 c := client.ServiceClient() 160 _, err := nodes.Update(c, "1234asdf", nodes.UpdateOpts{ 161 nodes.UpdateOperation{ 162 Path: "/driver", 163 Value: "new-driver", 164 }, 165 }).Extract() 166 167 if _, ok := err.(gophercloud.ErrMissingInput); !ok { 168 t.Fatal("ErrMissingInput was expected to occur") 169 } 170 171 } 172 173 func TestUpdateRequiredPath(t *testing.T) { 174 c := client.ServiceClient() 175 _, err := nodes.Update(c, "1234asdf", nodes.UpdateOpts{ 176 nodes.UpdateOperation{ 177 Op: nodes.ReplaceOp, 178 Value: "new-driver", 179 }, 180 }).Extract() 181 182 if _, ok := err.(gophercloud.ErrMissingInput); !ok { 183 t.Fatal("ErrMissingInput was expected to occur") 184 } 185 } 186 187 func TestValidateNode(t *testing.T) { 188 th.SetupHTTP() 189 defer th.TeardownHTTP() 190 HandleNodeValidateSuccessfully(t) 191 192 c := client.ServiceClient() 193 actual, err := nodes.Validate(c, "1234asdf").Extract() 194 th.AssertNoErr(t, err) 195 th.CheckDeepEquals(t, NodeFooValidation, *actual) 196 } 197 198 func TestInjectNMI(t *testing.T) { 199 th.SetupHTTP() 200 defer th.TeardownHTTP() 201 HandleInjectNMISuccessfully(t) 202 203 c := client.ServiceClient() 204 err := nodes.InjectNMI(c, "1234asdf").ExtractErr() 205 th.AssertNoErr(t, err) 206 } 207 208 func TestSetBootDevice(t *testing.T) { 209 th.SetupHTTP() 210 defer th.TeardownHTTP() 211 HandleSetBootDeviceSuccessfully(t) 212 213 c := client.ServiceClient() 214 err := nodes.SetBootDevice(c, "1234asdf", nodes.BootDeviceOpts{ 215 BootDevice: "pxe", 216 Persistent: false, 217 }).ExtractErr() 218 th.AssertNoErr(t, err) 219 } 220 221 func TestGetBootDevice(t *testing.T) { 222 th.SetupHTTP() 223 defer th.TeardownHTTP() 224 HandleGetBootDeviceSuccessfully(t) 225 226 c := client.ServiceClient() 227 bootDevice, err := nodes.GetBootDevice(c, "1234asdf").Extract() 228 th.AssertNoErr(t, err) 229 th.CheckDeepEquals(t, NodeBootDevice, *bootDevice) 230 } 231 232 func TestGetSupportedBootDevices(t *testing.T) { 233 th.SetupHTTP() 234 defer th.TeardownHTTP() 235 HandleGetSupportedBootDeviceSuccessfully(t) 236 237 c := client.ServiceClient() 238 bootDevices, err := nodes.GetSupportedBootDevices(c, "1234asdf").Extract() 239 th.AssertNoErr(t, err) 240 th.CheckDeepEquals(t, NodeSupportedBootDevice, bootDevices) 241 } 242 243 func TestNodeChangeProvisionStateActive(t *testing.T) { 244 th.SetupHTTP() 245 defer th.TeardownHTTP() 246 HandleNodeChangeProvisionStateActive(t) 247 248 c := client.ServiceClient() 249 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 250 Target: nodes.TargetActive, 251 ConfigDrive: "http://127.0.0.1/images/test-node-config-drive.iso.gz", 252 }).ExtractErr() 253 254 th.AssertNoErr(t, err) 255 } 256 257 func TestNodeChangeProvisionStateActiveWithSteps(t *testing.T) { 258 th.SetupHTTP() 259 defer th.TeardownHTTP() 260 HandleNodeChangeProvisionStateActiveWithSteps(t) 261 262 c := client.ServiceClient() 263 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 264 Target: nodes.TargetActive, 265 DeploySteps: []nodes.DeployStep{ 266 { 267 Interface: nodes.InterfaceDeploy, 268 Step: "inject_files", 269 Priority: 50, 270 Args: map[string]interface{}{ 271 "files": []interface{}{}, 272 }, 273 }, 274 }, 275 }).ExtractErr() 276 277 th.AssertNoErr(t, err) 278 } 279 280 func TestHandleNodeChangeProvisionStateConfigDrive(t *testing.T) { 281 th.SetupHTTP() 282 defer th.TeardownHTTP() 283 284 HandleNodeChangeProvisionStateConfigDrive(t) 285 286 c := client.ServiceClient() 287 288 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 289 Target: nodes.TargetActive, 290 ConfigDrive: ConfigDriveMap, 291 }).ExtractErr() 292 293 th.AssertNoErr(t, err) 294 } 295 296 func TestNodeChangeProvisionStateClean(t *testing.T) { 297 th.SetupHTTP() 298 defer th.TeardownHTTP() 299 HandleNodeChangeProvisionStateClean(t) 300 301 c := client.ServiceClient() 302 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 303 Target: nodes.TargetClean, 304 CleanSteps: []nodes.CleanStep{ 305 { 306 Interface: nodes.InterfaceDeploy, 307 Step: "upgrade_firmware", 308 Args: map[string]interface{}{ 309 "force": "True", 310 }, 311 }, 312 }, 313 }).ExtractErr() 314 315 th.AssertNoErr(t, err) 316 } 317 318 func TestNodeChangeProvisionStateCleanWithConflict(t *testing.T) { 319 th.SetupHTTP() 320 defer th.TeardownHTTP() 321 HandleNodeChangeProvisionStateCleanWithConflict(t) 322 323 c := client.ServiceClient() 324 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 325 Target: nodes.TargetClean, 326 CleanSteps: []nodes.CleanStep{ 327 { 328 Interface: nodes.InterfaceDeploy, 329 Step: "upgrade_firmware", 330 Args: map[string]interface{}{ 331 "force": "True", 332 }, 333 }, 334 }, 335 }).ExtractErr() 336 337 if _, ok := err.(gophercloud.ErrDefault409); !ok { 338 t.Fatal("ErrDefault409 was expected to occur") 339 } 340 } 341 342 func TestCleanStepRequiresInterface(t *testing.T) { 343 c := client.ServiceClient() 344 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 345 Target: nodes.TargetClean, 346 CleanSteps: []nodes.CleanStep{ 347 { 348 Step: "upgrade_firmware", 349 Args: map[string]interface{}{ 350 "force": "True", 351 }, 352 }, 353 }, 354 }).ExtractErr() 355 356 if _, ok := err.(gophercloud.ErrMissingInput); !ok { 357 t.Fatal("ErrMissingInput was expected to occur") 358 } 359 } 360 361 func TestCleanStepRequiresStep(t *testing.T) { 362 c := client.ServiceClient() 363 err := nodes.ChangeProvisionState(c, "1234asdf", nodes.ProvisionStateOpts{ 364 Target: nodes.TargetClean, 365 CleanSteps: []nodes.CleanStep{ 366 { 367 Interface: nodes.InterfaceDeploy, 368 Args: map[string]interface{}{ 369 "force": "True", 370 }, 371 }, 372 }, 373 }).ExtractErr() 374 375 if _, ok := err.(gophercloud.ErrMissingInput); !ok { 376 t.Fatal("ErrMissingInput was expected to occur") 377 } 378 } 379 380 func TestChangePowerState(t *testing.T) { 381 th.SetupHTTP() 382 defer th.TeardownHTTP() 383 HandleChangePowerStateSuccessfully(t) 384 385 opts := nodes.PowerStateOpts{ 386 Target: nodes.PowerOn, 387 Timeout: 100, 388 } 389 390 c := client.ServiceClient() 391 err := nodes.ChangePowerState(c, "1234asdf", opts).ExtractErr() 392 th.AssertNoErr(t, err) 393 } 394 395 func TestChangePowerStateWithConflict(t *testing.T) { 396 th.SetupHTTP() 397 defer th.TeardownHTTP() 398 HandleChangePowerStateWithConflict(t) 399 400 opts := nodes.PowerStateOpts{ 401 Target: nodes.PowerOn, 402 Timeout: 100, 403 } 404 405 c := client.ServiceClient() 406 err := nodes.ChangePowerState(c, "1234asdf", opts).ExtractErr() 407 if _, ok := err.(gophercloud.ErrDefault409); !ok { 408 t.Fatal("ErrDefault409 was expected to occur") 409 } 410 } 411 412 func TestSetRAIDConfig(t *testing.T) { 413 th.SetupHTTP() 414 defer th.TeardownHTTP() 415 HandleSetRAIDConfig(t) 416 417 sizeGB := 100 418 isRootVolume := true 419 420 config := nodes.RAIDConfigOpts{ 421 LogicalDisks: []nodes.LogicalDisk{ 422 { 423 SizeGB: &sizeGB, 424 IsRootVolume: &isRootVolume, 425 RAIDLevel: nodes.RAID1, 426 }, 427 }, 428 } 429 430 c := client.ServiceClient() 431 err := nodes.SetRAIDConfig(c, "1234asdf", config).ExtractErr() 432 th.AssertNoErr(t, err) 433 } 434 435 // Without specifying a size, we need to send a string: "MAX" 436 func TestSetRAIDConfigMaxSize(t *testing.T) { 437 th.SetupHTTP() 438 defer th.TeardownHTTP() 439 HandleSetRAIDConfigMaxSize(t) 440 441 isRootVolume := true 442 443 config := nodes.RAIDConfigOpts{ 444 LogicalDisks: []nodes.LogicalDisk{ 445 { 446 IsRootVolume: &isRootVolume, 447 RAIDLevel: nodes.RAID1, 448 }, 449 }, 450 } 451 452 c := client.ServiceClient() 453 err := nodes.SetRAIDConfig(c, "1234asdf", config).ExtractErr() 454 th.AssertNoErr(t, err) 455 } 456 457 func TestToRAIDConfigMap(t *testing.T) { 458 cases := []struct { 459 name string 460 opts nodes.RAIDConfigOpts 461 expected map[string]interface{} 462 }{ 463 { 464 name: "LogicalDisks is empty", 465 opts: nodes.RAIDConfigOpts{}, 466 expected: map[string]interface{}{ 467 "logical_disks": nil, 468 }, 469 }, 470 { 471 name: "LogicalDisks is nil", 472 opts: nodes.RAIDConfigOpts{ 473 LogicalDisks: nil, 474 }, 475 expected: map[string]interface{}{ 476 "logical_disks": nil, 477 }, 478 }, 479 { 480 name: "PhysicalDisks is []string", 481 opts: nodes.RAIDConfigOpts{ 482 LogicalDisks: []nodes.LogicalDisk{ 483 { 484 RAIDLevel: "0", 485 VolumeName: "root", 486 PhysicalDisks: []interface{}{"6I:1:5", "6I:1:6", "6I:1:7"}, 487 }, 488 }, 489 }, 490 expected: map[string]interface{}{ 491 "logical_disks": []map[string]interface{}{ 492 { 493 "raid_level": "0", 494 "size_gb": "MAX", 495 "volume_name": "root", 496 "physical_disks": []interface{}{"6I:1:5", "6I:1:6", "6I:1:7"}, 497 }, 498 }, 499 }, 500 }, 501 { 502 name: "PhysicalDisks is []map[string]string", 503 opts: nodes.RAIDConfigOpts{ 504 LogicalDisks: []nodes.LogicalDisk{ 505 { 506 RAIDLevel: "0", 507 VolumeName: "root", 508 Controller: "software", 509 PhysicalDisks: []interface{}{ 510 map[string]string{ 511 "size": "> 100", 512 }, 513 map[string]string{ 514 "size": "> 100", 515 }, 516 }, 517 }, 518 }, 519 }, 520 expected: map[string]interface{}{ 521 "logical_disks": []map[string]interface{}{ 522 { 523 "raid_level": "0", 524 "size_gb": "MAX", 525 "volume_name": "root", 526 "controller": "software", 527 "physical_disks": []interface{}{ 528 map[string]interface{}{ 529 "size": "> 100", 530 }, 531 map[string]interface{}{ 532 "size": "> 100", 533 }, 534 }, 535 }, 536 }, 537 }, 538 }, 539 } 540 541 for _, c := range cases { 542 t.Run(c.name, func(t *testing.T) { 543 got, _ := c.opts.ToRAIDConfigMap() 544 th.CheckDeepEquals(t, c.expected, got) 545 }) 546 } 547 } 548 549 func TestListBIOSSettings(t *testing.T) { 550 th.SetupHTTP() 551 defer th.TeardownHTTP() 552 HandleListBIOSSettingsSuccessfully(t) 553 554 c := client.ServiceClient() 555 actual, err := nodes.ListBIOSSettings(c, "1234asdf", nil).Extract() 556 th.AssertNoErr(t, err) 557 th.CheckDeepEquals(t, NodeBIOSSettings, actual) 558 } 559 560 func TestListDetailBIOSSettings(t *testing.T) { 561 th.SetupHTTP() 562 defer th.TeardownHTTP() 563 HandleListDetailBIOSSettingsSuccessfully(t) 564 565 opts := nodes.ListBIOSSettingsOpts{ 566 Detail: true, 567 } 568 569 c := client.ServiceClient() 570 actual, err := nodes.ListBIOSSettings(c, "1234asdf", opts).Extract() 571 th.AssertNoErr(t, err) 572 th.CheckDeepEquals(t, NodeDetailBIOSSettings, actual) 573 } 574 575 func TestGetBIOSSetting(t *testing.T) { 576 th.SetupHTTP() 577 defer th.TeardownHTTP() 578 HandleGetBIOSSettingSuccessfully(t) 579 580 c := client.ServiceClient() 581 actual, err := nodes.GetBIOSSetting(c, "1234asdf", "ProcVirtualization").Extract() 582 th.AssertNoErr(t, err) 583 th.CheckDeepEquals(t, NodeSingleBIOSSetting, *actual) 584 } 585 586 func TestListBIOSSettingsOpts(t *testing.T) { 587 // Detail cannot take Fields 588 opts := nodes.ListBIOSSettingsOpts{ 589 Detail: true, 590 Fields: []string{"name", "value"}, 591 } 592 593 _, err := opts.ToListBIOSSettingsOptsQuery() 594 th.AssertEquals(t, err.Error(), "cannot have both fields and detail options for BIOS settings") 595 } 596 597 func TestGetVendorPassthruMethods(t *testing.T) { 598 th.SetupHTTP() 599 defer th.TeardownHTTP() 600 HandleGetVendorPassthruMethodsSuccessfully(t) 601 602 c := client.ServiceClient() 603 actual, err := nodes.GetVendorPassthruMethods(c, "1234asdf").Extract() 604 th.AssertNoErr(t, err) 605 th.CheckDeepEquals(t, NodeVendorPassthruMethods, *actual) 606 } 607 608 func TestGetAllSubscriptions(t *testing.T) { 609 th.SetupHTTP() 610 defer th.TeardownHTTP() 611 HandleGetAllSubscriptionsVendorPassthruSuccessfully(t) 612 613 c := client.ServiceClient() 614 method := nodes.CallVendorPassthruOpts{ 615 Method: "get_all_subscriptions", 616 } 617 actual, err := nodes.GetAllSubscriptions(c, "1234asdf", method).Extract() 618 th.AssertNoErr(t, err) 619 th.CheckDeepEquals(t, NodeGetAllSubscriptions, *actual) 620 } 621 622 func TestGetSubscription(t *testing.T) { 623 th.SetupHTTP() 624 defer th.TeardownHTTP() 625 HandleGetSubscriptionVendorPassthruSuccessfully(t) 626 627 c := client.ServiceClient() 628 method := nodes.CallVendorPassthruOpts{ 629 Method: "get_subscription", 630 } 631 subscriptionOpt := nodes.GetSubscriptionOpts{ 632 Id: "62dbd1b6-f637-11eb-b551-4cd98f20754c", 633 } 634 actual, err := nodes.GetSubscription(c, "1234asdf", method, subscriptionOpt).Extract() 635 th.AssertNoErr(t, err) 636 th.CheckDeepEquals(t, NodeGetSubscription, *actual) 637 } 638 639 func TestCreateSubscriptionAllParameters(t *testing.T) { 640 th.SetupHTTP() 641 defer th.TeardownHTTP() 642 HandleCreateSubscriptionVendorPassthruAllParametersSuccessfully(t) 643 644 c := client.ServiceClient() 645 method := nodes.CallVendorPassthruOpts{ 646 Method: "create_subscription", 647 } 648 createOpt := nodes.CreateSubscriptionOpts{ 649 Destination: "https://someurl", 650 Context: "gophercloud", 651 Protocol: "Redfish", 652 EventTypes: []string{"Alert"}, 653 HttpHeaders: []map[string]string{{"Content-Type": "application/json"}}, 654 } 655 actual, err := nodes.CreateSubscription(c, "1234asdf", method, createOpt).Extract() 656 th.AssertNoErr(t, err) 657 th.CheckDeepEquals(t, NodeCreateSubscriptionAllParameters, *actual) 658 } 659 660 func TestCreateSubscriptionWithRequiredParameters(t *testing.T) { 661 th.SetupHTTP() 662 defer th.TeardownHTTP() 663 HandleCreateSubscriptionVendorPassthruRequiredParametersSuccessfully(t) 664 665 c := client.ServiceClient() 666 method := nodes.CallVendorPassthruOpts{ 667 Method: "create_subscription", 668 } 669 createOpt := nodes.CreateSubscriptionOpts{ 670 Destination: "https://somedestinationurl", 671 } 672 actual, err := nodes.CreateSubscription(c, "1234asdf", method, createOpt).Extract() 673 th.AssertNoErr(t, err) 674 th.CheckDeepEquals(t, NodeCreateSubscriptionRequiredParameters, *actual) 675 } 676 677 func TestDeleteSubscription(t *testing.T) { 678 th.SetupHTTP() 679 defer th.TeardownHTTP() 680 HandleDeleteSubscriptionVendorPassthruSuccessfully(t) 681 682 c := client.ServiceClient() 683 method := nodes.CallVendorPassthruOpts{ 684 Method: "delete_subscription", 685 } 686 deleteOpt := nodes.DeleteSubscriptionOpts{ 687 Id: "344a3e2-978a-444e-990a-cbf47c62ef88", 688 } 689 err := nodes.DeleteSubscription(c, "1234asdf", method, deleteOpt).ExtractErr() 690 th.AssertNoErr(t, err) 691 } 692 693 func TestSetMaintenance(t *testing.T) { 694 th.SetupHTTP() 695 defer th.TeardownHTTP() 696 HandleSetNodeMaintenanceSuccessfully(t) 697 698 c := client.ServiceClient() 699 err := nodes.SetMaintenance(c, "1234asdf", nodes.MaintenanceOpts{ 700 Reason: "I'm tired", 701 }).ExtractErr() 702 th.AssertNoErr(t, err) 703 } 704 705 func TestUnsetMaintenance(t *testing.T) { 706 th.SetupHTTP() 707 defer th.TeardownHTTP() 708 HandleUnsetNodeMaintenanceSuccessfully(t) 709 710 c := client.ServiceClient() 711 err := nodes.UnsetMaintenance(c, "1234asdf").ExtractErr() 712 th.AssertNoErr(t, err) 713 }