github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/baremetal/v1/nodes/testing/requests_test.go (about)

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