github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/compute/v2/servers/testing/fixtures_test.go (about)

     1  package testing
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/vnpaycloud-console/gophercloud/v2"
    10  	"github.com/vnpaycloud-console/gophercloud/v2/openstack/compute/v2/servers"
    11  	th "github.com/vnpaycloud-console/gophercloud/v2/testhelper"
    12  	"github.com/vnpaycloud-console/gophercloud/v2/testhelper/client"
    13  )
    14  
    15  // ServerListBody contains the canned body of a servers.List response.
    16  const ServerListBody = `
    17  {
    18  	"servers": [
    19  		{
    20  			"status": "ACTIVE",
    21  			"updated": "2014-09-25T13:10:10Z",
    22  			"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
    23  			"OS-EXT-SRV-ATTR:host": "devstack",
    24  			"addresses": {
    25  				"private": [
    26  					{
    27  						"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b",
    28  						"version": 4,
    29  						"addr": "10.0.0.32",
    30  						"OS-EXT-IPS:type": "fixed"
    31  					}
    32  				]
    33  			},
    34  			"links": [
    35  				{
    36  					"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
    37  					"rel": "self"
    38  				},
    39  				{
    40  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
    41  					"rel": "bookmark"
    42  				}
    43  			],
    44  			"key_name": null,
    45  			"image": {
    46  				"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
    47  				"links": [
    48  					{
    49  						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
    50  						"rel": "bookmark"
    51  					}
    52  				]
    53  			},
    54  			"OS-EXT-STS:task_state": null,
    55  			"OS-EXT-STS:vm_state": "active",
    56  			"OS-EXT-SRV-ATTR:instance_name": "instance-0000001e",
    57  			"OS-SRV-USG:launched_at": "2014-09-25T13:10:10.000000",
    58  			"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
    59  			"flavor": {
    60  				"id": "1",
    61  				"links": [
    62  					{
    63  						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
    64  						"rel": "bookmark"
    65  					}
    66  				]
    67  			},
    68  			"id": "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
    69  			"security_groups": [
    70  				{
    71  					"name": "default"
    72  				}
    73  			],
    74  			"OS-SRV-USG:terminated_at": null,
    75  			"OS-EXT-AZ:availability_zone": "nova",
    76  			"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
    77  			"name": "herp",
    78  			"created": "2014-09-25T13:10:02Z",
    79  			"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
    80  			"OS-DCF:diskConfig": "MANUAL",
    81  			"os-extended-volumes:volumes_attached": [
    82  				{
    83  					"id": "2bdbc40f-a277-45d4-94ac-d9881c777d33"
    84  				}
    85  			],
    86  			"accessIPv4": "",
    87  			"accessIPv6": "",
    88  			"progress": 0,
    89  			"OS-EXT-STS:power_state": 1,
    90  			"config_drive": "",
    91  			"metadata": {}
    92  		},
    93  		{
    94  			"status": "ACTIVE",
    95  			"updated": "2014-09-25T13:04:49Z",
    96  			"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
    97  			"OS-EXT-SRV-ATTR:host": "devstack",
    98  			"addresses": {
    99  				"private": [
   100  					{
   101  						"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   102  						"version": 4,
   103  						"addr": "10.0.0.31",
   104  						"OS-EXT-IPS:type": "fixed"
   105  					}
   106  				]
   107  			},
   108  			"links": [
   109  				{
   110  					"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   111  					"rel": "self"
   112  				},
   113  				{
   114  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   115  					"rel": "bookmark"
   116  				}
   117  			],
   118  			"key_name": null,
   119  			"image": {
   120  				"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   121  				"links": [
   122  					{
   123  						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   124  						"rel": "bookmark"
   125  					}
   126  				]
   127  			},
   128  			"OS-EXT-STS:task_state": null,
   129  			"OS-EXT-STS:vm_state": "active",
   130  			"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
   131  			"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
   132  			"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
   133  			"flavor": {
   134  				"id": "1",
   135  				"links": [
   136  					{
   137  						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   138  						"rel": "bookmark"
   139  					}
   140  				]
   141  			},
   142  			"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   143  			"security_groups": [
   144  				{
   145  					"name": "default"
   146  				}
   147  			],
   148  			"OS-SRV-USG:terminated_at": null,
   149  			"OS-EXT-AZ:availability_zone": "nova",
   150  			"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
   151  			"name": "derp",
   152  			"created": "2014-09-25T13:04:41Z",
   153  			"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
   154  			"OS-DCF:diskConfig": "MANUAL",
   155  			"os-extended-volumes:volumes_attached": [],
   156  			"accessIPv4": "",
   157  			"accessIPv6": "",
   158  			"progress": 0,
   159  			"OS-EXT-STS:power_state": 1,
   160  			"config_drive": "",
   161  			"metadata": {},
   162  			"locked": true
   163  		},
   164  		{
   165  		"status": "ACTIVE",
   166  		"updated": "2014-09-25T13:04:49Z",
   167  		"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   168  		"OS-EXT-SRV-ATTR:host": "devstack",
   169  		"addresses": {
   170  			"private": [
   171  				{
   172  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   173  					"version": 4,
   174  					"addr": "10.0.0.31",
   175  					"OS-EXT-IPS:type": "fixed"
   176  				}
   177  			]
   178  		},
   179  		"links": [
   180  			{
   181  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   182  				"rel": "self"
   183  			},
   184  			{
   185  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   186  				"rel": "bookmark"
   187  			}
   188  		],
   189  		"key_name": null,
   190  		"image": "",
   191  		"OS-EXT-STS:task_state": null,
   192  		"OS-EXT-STS:vm_state": "active",
   193  		"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
   194  		"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
   195  		"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
   196  		"flavor": {
   197  			"id": "1",
   198  			"links": [
   199  				{
   200  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   201  					"rel": "bookmark"
   202  				}
   203  			]
   204  		},
   205  		"id": "9e5476bd-a4ec-4653-93d6-72c93aa682bb",
   206  		"security_groups": [
   207  			{
   208  				"name": "default"
   209  			}
   210  		],
   211  		"OS-SRV-USG:terminated_at": null,
   212  		"OS-EXT-AZ:availability_zone": "nova",
   213  		"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
   214  		"name": "merp",
   215  		"created": "2014-09-25T13:04:41Z",
   216  		"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
   217  		"OS-DCF:diskConfig": "MANUAL",
   218  		"os-extended-volumes:volumes_attached": [],
   219  		"accessIPv4": "",
   220  		"accessIPv6": "",
   221  		"progress": 0,
   222  		"OS-EXT-STS:power_state": 1,
   223  		"config_drive": "",
   224  		"metadata": {}
   225  	}
   226  	]
   227  }
   228  `
   229  
   230  // SingleServerBody is the canned body of a Get request on an existing server.
   231  const SingleServerBody = `
   232  {
   233  	"server": {
   234  		"status": "ACTIVE",
   235  		"updated": "2014-09-25T13:04:49Z",
   236  		"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   237  		"OS-EXT-SRV-ATTR:host": "devstack",
   238  		"addresses": {
   239  			"private": [
   240  				{
   241  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   242  					"version": 4,
   243  					"addr": "10.0.0.31",
   244  					"OS-EXT-IPS:type": "fixed"
   245  				}
   246  			]
   247  		},
   248  		"links": [
   249  			{
   250  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   251  				"rel": "self"
   252  			},
   253  			{
   254  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   255  				"rel": "bookmark"
   256  			}
   257  		],
   258  		"key_name": null,
   259  		"image": {
   260  			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   261  			"links": [
   262  				{
   263  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   264  					"rel": "bookmark"
   265  				}
   266  			]
   267  		},
   268  		"OS-EXT-STS:task_state": null,
   269  		"OS-EXT-STS:vm_state": "active",
   270  		"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
   271  		"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
   272  		"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
   273  		"flavor": {
   274  			"id": "1",
   275  			"links": [
   276  				{
   277  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   278  					"rel": "bookmark"
   279  				}
   280  			]
   281  		},
   282  		"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   283  		"security_groups": [
   284  			{
   285  				"name": "default"
   286  			}
   287  		],
   288  		"OS-SRV-USG:terminated_at": null,
   289  		"OS-EXT-AZ:availability_zone": "nova",
   290  		"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
   291  		"name": "derp",
   292  		"created": "2014-09-25T13:04:41Z",
   293  		"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
   294  		"OS-DCF:diskConfig": "MANUAL",
   295  		"os-extended-volumes:volumes_attached": [],
   296  		"accessIPv4": "",
   297  		"accessIPv6": "",
   298  		"progress": 0,
   299  		"OS-EXT-STS:power_state": 1,
   300  		"config_drive": "",
   301  		"metadata": {},
   302  		"locked": true
   303  	}
   304  }
   305  `
   306  
   307  // FaultyServerBody is the body of a Get request on an existing server
   308  // which has a fault/error.
   309  const FaultyServerBody = `
   310  {
   311  	"server": {
   312  		"status": "ACTIVE",
   313  		"updated": "2014-09-25T13:04:49Z",
   314  		"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   315  		"OS-EXT-SRV-ATTR:host": "devstack",
   316  		"addresses": {
   317  			"private": [
   318  				{
   319  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   320  					"version": 4,
   321  					"addr": "10.0.0.31",
   322  					"OS-EXT-IPS:type": "fixed"
   323  				}
   324  			]
   325  		},
   326  		"links": [
   327  			{
   328  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   329  				"rel": "self"
   330  			},
   331  			{
   332  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   333  				"rel": "bookmark"
   334  			}
   335  		],
   336  		"key_name": null,
   337  		"image": {
   338  			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   339  			"links": [
   340  				{
   341  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   342  					"rel": "bookmark"
   343  				}
   344  			]
   345  		},
   346  		"OS-EXT-STS:task_state": null,
   347  		"OS-EXT-STS:vm_state": "active",
   348  		"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
   349  		"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
   350  		"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
   351  		"flavor": {
   352  			"id": "1",
   353  			"links": [
   354  				{
   355  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   356  					"rel": "bookmark"
   357  				}
   358  			]
   359  		},
   360  		"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   361  		"security_groups": [
   362  			{
   363  				"name": "default"
   364  			}
   365  		],
   366  		"OS-SRV-USG:terminated_at": null,
   367  		"OS-EXT-AZ:availability_zone": "nova",
   368  		"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
   369  		"name": "derp",
   370  		"created": "2014-09-25T13:04:41Z",
   371  		"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
   372  		"OS-DCF:diskConfig": "MANUAL",
   373  		"os-extended-volumes:volumes_attached": [],
   374  		"accessIPv4": "",
   375  		"accessIPv6": "",
   376  		"progress": 0,
   377  		"OS-EXT-STS:power_state": 1,
   378  		"config_drive": "",
   379  		"metadata": {},
   380  		"fault": {
   381  			"message": "Conflict updating instance c2ce4dea-b73f-4d01-8633-2c6032869281. Expected: {'task_state': [u'spawning']}. Actual: {'task_state': None}",
   382  			"code": 500,
   383  			"created": "2017-11-11T07:58:39Z",
   384  			"details": "Stock details for test"
   385  		}
   386  	}
   387  }
   388  `
   389  
   390  const ServerPasswordBody = `
   391  {
   392      "password": "xlozO3wLCBRWAa2yDjCCVx8vwNPypxnypmRYDa/zErlQ+EzPe1S/Gz6nfmC52mOlOSCRuUOmG7kqqgejPof6M7bOezS387zjq4LSvvwp28zUknzy4YzfFGhnHAdai3TxUJ26pfQCYrq8UTzmKF2Bq8ioSEtVVzM0A96pDh8W2i7BOz6MdoiVyiev/I1K2LsuipfxSJR7Wdke4zNXJjHHP2RfYsVbZ/k9ANu+Nz4iIH8/7Cacud/pphH7EjrY6a4RZNrjQskrhKYed0YERpotyjYk1eDtRe72GrSiXteqCM4biaQ5w3ruS+AcX//PXk3uJ5kC7d67fPXaVz4WaQRYMg=="
   393  }
   394  `
   395  
   396  const ConsoleOutputBody = `{
   397  	"output": "abc"
   398  }`
   399  
   400  const ServerWithTagsCreateRequest = `
   401  {
   402    "server": {
   403      "name": "derp",
   404      "imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   405      "flavorRef": "1",
   406      "tags": ["foo", "bar"]
   407    }
   408  }`
   409  
   410  // SingleServerWithTagsBody is the canned body of a Get request on an existing server with tags.
   411  const SingleServerWithTagsBody = `
   412  {
   413  	"server": {
   414  		"status": "ACTIVE",
   415  		"updated": "2014-09-25T13:04:49Z",
   416  		"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   417  		"OS-EXT-SRV-ATTR:host": "devstack",
   418  		"addresses": {
   419  			"private": [
   420  				{
   421  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   422  					"version": 4,
   423  					"addr": "10.0.0.31",
   424  					"OS-EXT-IPS:type": "fixed"
   425  				}
   426  			]
   427  		},
   428  		"links": [
   429  			{
   430  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   431  				"rel": "self"
   432  			},
   433  			{
   434  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   435  				"rel": "bookmark"
   436  			}
   437  		],
   438  		"key_name": null,
   439  		"image": {
   440  			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   441  			"links": [
   442  				{
   443  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   444  					"rel": "bookmark"
   445  				}
   446  			]
   447  		},
   448  		"OS-EXT-STS:task_state": null,
   449  		"OS-EXT-STS:vm_state": "active",
   450  		"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
   451  		"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
   452  		"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
   453  		"flavor": {
   454  			"id": "1",
   455  			"links": [
   456  				{
   457  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   458  					"rel": "bookmark"
   459  				}
   460  			]
   461  		},
   462  		"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   463  		"security_groups": [
   464  			{
   465  				"name": "default"
   466  			}
   467  		],
   468  		"OS-SRV-USG:terminated_at": null,
   469  		"OS-EXT-AZ:availability_zone": "nova",
   470  		"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
   471  		"name": "derp",
   472  		"created": "2014-09-25T13:04:41Z",
   473  		"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
   474  		"OS-DCF:diskConfig": "MANUAL",
   475  		"os-extended-volumes:volumes_attached": [],
   476  		"accessIPv4": "",
   477  		"accessIPv6": "",
   478  		"progress": 0,
   479  		"OS-EXT-STS:power_state": 1,
   480  		"config_drive": "",
   481  		"metadata": {},
   482  		"tags": ["foo", "bar"]
   483  	}
   484  }
   485  `
   486  
   487  var (
   488  	herpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:10:02Z")
   489  	herpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:10:10Z")
   490  	// ServerHerp is a Server struct that should correspond to the first result in ServerListBody.
   491  	ServerHerp = servers.Server{
   492  		Status:  "ACTIVE",
   493  		Updated: herpTimeUpdated,
   494  		HostID:  "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   495  		Addresses: map[string]any{
   496  			"private": []any{
   497  				map[string]any{
   498  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b",
   499  					"version":                 float64(4),
   500  					"addr":                    "10.0.0.32",
   501  					"OS-EXT-IPS:type":         "fixed",
   502  				},
   503  			},
   504  		},
   505  		Links: []any{
   506  			map[string]any{
   507  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
   508  				"rel":  "self",
   509  			},
   510  			map[string]any{
   511  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
   512  				"rel":  "bookmark",
   513  			},
   514  		},
   515  		Image: map[string]any{
   516  			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   517  			"links": []any{
   518  				map[string]any{
   519  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   520  					"rel":  "bookmark",
   521  				},
   522  			},
   523  		},
   524  		Flavor: map[string]any{
   525  			"id": "1",
   526  			"links": []any{
   527  				map[string]any{
   528  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   529  					"rel":  "bookmark",
   530  				},
   531  			},
   532  		},
   533  		ID:       "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
   534  		UserID:   "9349aff8be7545ac9d2f1d00999a23cd",
   535  		Name:     "herp",
   536  		Created:  herpTimeCreated,
   537  		TenantID: "fcad67a6189847c4aecfa3c81a05783b",
   538  		Metadata: map[string]string{},
   539  		AttachedVolumes: []servers.AttachedVolume{
   540  			{
   541  				ID: "2bdbc40f-a277-45d4-94ac-d9881c777d33",
   542  			},
   543  		},
   544  		SecurityGroups: []map[string]any{
   545  			{
   546  				"name": "default",
   547  			},
   548  		},
   549  		Host:               "devstack",
   550  		Hostname:           nil,
   551  		HypervisorHostname: "devstack",
   552  		InstanceName:       "instance-0000001e",
   553  		LaunchIndex:        nil,
   554  		ReservationID:      nil,
   555  		RootDeviceName:     nil,
   556  		Userdata:           nil,
   557  		VmState:            "active",
   558  		PowerState:         servers.RUNNING,
   559  		LaunchedAt:         time.Date(2014, 9, 25, 13, 10, 10, 0, time.UTC),
   560  		TerminatedAt:       time.Time{},
   561  		DiskConfig:         servers.Manual,
   562  		AvailabilityZone:   "nova",
   563  	}
   564  
   565  	derpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:41Z")
   566  	derpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:49Z")
   567  	// ServerDerp is a Server struct that should correspond to the second server in ServerListBody.
   568  	ServerDerp = servers.Server{
   569  		Status:  "ACTIVE",
   570  		Updated: derpTimeUpdated,
   571  		HostID:  "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   572  		Addresses: map[string]any{
   573  			"private": []any{
   574  				map[string]any{
   575  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   576  					"version":                 float64(4),
   577  					"addr":                    "10.0.0.31",
   578  					"OS-EXT-IPS:type":         "fixed",
   579  				},
   580  			},
   581  		},
   582  		Links: []any{
   583  			map[string]any{
   584  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   585  				"rel":  "self",
   586  			},
   587  			map[string]any{
   588  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   589  				"rel":  "bookmark",
   590  			},
   591  		},
   592  		Image: map[string]any{
   593  			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   594  			"links": []any{
   595  				map[string]any{
   596  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
   597  					"rel":  "bookmark",
   598  				},
   599  			},
   600  		},
   601  		Flavor: map[string]any{
   602  			"id": "1",
   603  			"links": []any{
   604  				map[string]any{
   605  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   606  					"rel":  "bookmark",
   607  				},
   608  			},
   609  		},
   610  		ID:              "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   611  		UserID:          "9349aff8be7545ac9d2f1d00999a23cd",
   612  		Name:            "derp",
   613  		Created:         derpTimeCreated,
   614  		TenantID:        "fcad67a6189847c4aecfa3c81a05783b",
   615  		Metadata:        map[string]string{},
   616  		AttachedVolumes: []servers.AttachedVolume{},
   617  		SecurityGroups: []map[string]any{
   618  			{
   619  				"name": "default",
   620  			},
   621  		},
   622  		Host:               "devstack",
   623  		Hostname:           nil,
   624  		HypervisorHostname: "devstack",
   625  		InstanceName:       "instance-0000001d",
   626  		LaunchIndex:        nil,
   627  		ReservationID:      nil,
   628  		RootDeviceName:     nil,
   629  		Userdata:           nil,
   630  		VmState:            "active",
   631  		PowerState:         servers.RUNNING,
   632  		LaunchedAt:         time.Date(2014, 9, 25, 13, 04, 49, 0, time.UTC),
   633  		TerminatedAt:       time.Time{},
   634  		DiskConfig:         servers.Manual,
   635  		AvailabilityZone:   "nova",
   636  		Locked:             func() *bool { b := true; return &b }(),
   637  	}
   638  
   639  	ConsoleOutput = "abc"
   640  
   641  	merpTimeCreated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:41Z")
   642  	merpTimeUpdated, _ = time.Parse(time.RFC3339, "2014-09-25T13:04:49Z")
   643  	// ServerMerp is a Server struct that should correspond to the second server in ServerListBody.
   644  	ServerMerp = servers.Server{
   645  		Status:  "ACTIVE",
   646  		Updated: merpTimeUpdated,
   647  		HostID:  "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
   648  		Addresses: map[string]any{
   649  			"private": []any{
   650  				map[string]any{
   651  					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
   652  					"version":                 float64(4),
   653  					"addr":                    "10.0.0.31",
   654  					"OS-EXT-IPS:type":         "fixed",
   655  				},
   656  			},
   657  		},
   658  		Links: []any{
   659  			map[string]any{
   660  				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   661  				"rel":  "self",
   662  			},
   663  			map[string]any{
   664  				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
   665  				"rel":  "bookmark",
   666  			},
   667  		},
   668  		Image: nil,
   669  		Flavor: map[string]any{
   670  			"id": "1",
   671  			"links": []any{
   672  				map[string]any{
   673  					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
   674  					"rel":  "bookmark",
   675  				},
   676  			},
   677  		},
   678  		ID:              "9e5476bd-a4ec-4653-93d6-72c93aa682bb",
   679  		UserID:          "9349aff8be7545ac9d2f1d00999a23cd",
   680  		Name:            "merp",
   681  		Created:         merpTimeCreated,
   682  		TenantID:        "fcad67a6189847c4aecfa3c81a05783b",
   683  		Metadata:        map[string]string{},
   684  		AttachedVolumes: []servers.AttachedVolume{},
   685  		SecurityGroups: []map[string]any{
   686  			{
   687  				"name": "default",
   688  			},
   689  		},
   690  		Host:               "devstack",
   691  		Hostname:           nil,
   692  		HypervisorHostname: "devstack",
   693  		InstanceName:       "instance-0000001d",
   694  		LaunchIndex:        nil,
   695  		ReservationID:      nil,
   696  		RootDeviceName:     nil,
   697  		Userdata:           nil,
   698  		VmState:            "active",
   699  		PowerState:         servers.RUNNING,
   700  		LaunchedAt:         time.Date(2014, 9, 25, 13, 04, 49, 0, time.UTC),
   701  		TerminatedAt:       time.Time{},
   702  		DiskConfig:         servers.Manual,
   703  		AvailabilityZone:   "nova",
   704  	}
   705  
   706  	faultTimeCreated, _ = time.Parse(time.RFC3339, "2017-11-11T07:58:39Z")
   707  	DerpFault           = servers.Fault{
   708  		Code:    500,
   709  		Created: faultTimeCreated,
   710  		Details: "Stock details for test",
   711  		Message: "Conflict updating instance c2ce4dea-b73f-4d01-8633-2c6032869281. " +
   712  			"Expected: {'task_state': [u'spawning']}. Actual: {'task_state': None}",
   713  	}
   714  )
   715  
   716  type CreateOptsWithCustomField struct {
   717  	servers.CreateOpts
   718  	Foo string `json:"foo,omitempty"`
   719  }
   720  
   721  func (opts CreateOptsWithCustomField) ToServerCreateMap() (map[string]any, error) {
   722  	b, err := gophercloud.BuildRequestBody(opts, "")
   723  	if err != nil {
   724  		return nil, err
   725  	}
   726  
   727  	return map[string]any{"server": b}, nil
   728  }
   729  
   730  // HandleServerNoNetworkCreationSuccessfully sets up the test server with no
   731  // network to respond to a server creation request with a given response.
   732  func HandleServerNoNetworkCreationSuccessfully(t *testing.T, response string) {
   733  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   734  		th.TestMethod(t, r, "POST")
   735  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   736  		th.TestJSONRequest(t, r, `{
   737  			"server": {
   738  				"name": "derp",
   739  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   740  				"flavorRef": "1",
   741  				"networks": "none"
   742  			}
   743  		}`)
   744  
   745  		w.WriteHeader(http.StatusAccepted)
   746  		w.Header().Add("Content-Type", "application/json")
   747  		fmt.Fprint(w, response)
   748  	})
   749  }
   750  
   751  // HandleServerCreationSuccessfully sets up the test server to respond to a server creation request
   752  // with a given response.
   753  func HandleServerCreationSuccessfully(t *testing.T, response string) {
   754  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   755  		th.TestMethod(t, r, "POST")
   756  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   757  		th.TestJSONRequest(t, r, `{
   758  			"server": {
   759  				"name": "derp",
   760  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   761  				"flavorRef": "1"
   762  			}
   763  		}`)
   764  
   765  		w.WriteHeader(http.StatusAccepted)
   766  		w.Header().Add("Content-Type", "application/json")
   767  		fmt.Fprint(w, response)
   768  	})
   769  
   770  	th.Mux.HandleFunc("/images/detail", func(w http.ResponseWriter, r *http.Request) {
   771  		th.TestMethod(t, r, "GET")
   772  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   773  
   774  		w.Header().Add("Content-Type", "application/json")
   775  		if err := r.ParseForm(); err != nil {
   776  			t.Errorf("Failed to parse request form %v", err)
   777  		}
   778  		marker := r.Form.Get("marker")
   779  		switch marker {
   780  		case "":
   781  			fmt.Fprint(w, `
   782  				{
   783  					"images": [
   784  						{
   785  							"status": "ACTIVE",
   786  							"updated": "2014-09-23T12:54:56Z",
   787  							"id": "f3e4a95d-1f4f-4989-97ce-f3a1fb8c04d7",
   788  							"OS-EXT-IMG-SIZE:size": 476704768,
   789  							"name": "F17-x86_64-cfntools",
   790  							"created": "2014-09-23T12:54:52Z",
   791  							"minDisk": 0,
   792  							"progress": 100,
   793  							"minRam": 0
   794  						},
   795  						{
   796  							"status": "ACTIVE",
   797  							"updated": "2014-09-23T12:51:43Z",
   798  							"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
   799  							"OS-EXT-IMG-SIZE:size": 13167616,
   800  							"name": "cirros-0.3.2-x86_64-disk",
   801  							"created": "2014-09-23T12:51:42Z",
   802  							"minDisk": 0,
   803  							"progress": 100,
   804  							"minRam": 0
   805  						}
   806  					]
   807  				}
   808  			`)
   809  		case "2":
   810  			fmt.Fprint(w, `{ "images": [] }`)
   811  		default:
   812  			t.Fatalf("Unexpected marker: [%s]", marker)
   813  		}
   814  	})
   815  
   816  	th.Mux.HandleFunc("/flavors/detail", func(w http.ResponseWriter, r *http.Request) {
   817  		th.TestMethod(t, r, "GET")
   818  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   819  
   820  		w.Header().Add("Content-Type", "application/json")
   821  		if err := r.ParseForm(); err != nil {
   822  			t.Errorf("Failed to parse request form %v", err)
   823  		}
   824  		marker := r.Form.Get("marker")
   825  		switch marker {
   826  		case "":
   827  			fmt.Fprintf(w, `
   828  						{
   829  							"flavors": [
   830  								{
   831  									"id": "1",
   832  									"name": "m1.tiny",
   833  									"disk": 1,
   834  									"ram": 512,
   835  									"vcpus": 1,
   836  									"swap":""
   837  								},
   838  								{
   839  									"id": "2",
   840  									"name": "m2.small",
   841  									"disk": 10,
   842  									"ram": 1024,
   843  									"vcpus": 2,
   844  									"swap": 1000
   845  								}
   846  							],
   847  							"flavors_links": [
   848  								{
   849  									"href": "%s/flavors/detail?marker=2",
   850  									"rel": "next"
   851  								}
   852  							]
   853  						}
   854  					`, th.Server.URL)
   855  		case "2":
   856  			fmt.Fprint(w, `{ "flavors": [] }`)
   857  		default:
   858  			t.Fatalf("Unexpected marker: [%s]", marker)
   859  		}
   860  	})
   861  }
   862  
   863  // HandleServerCreationWithCustomFieldSuccessfully sets up the test server to respond to a server creation request
   864  // with a given response.
   865  func HandleServersCreationSuccessfully(t *testing.T, response string) {
   866  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   867  		th.TestMethod(t, r, "POST")
   868  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   869  		th.TestJSONRequest(t, r, `{
   870  			"server": {
   871  				"name": "derp",
   872  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   873  				"flavorRef": "1",
   874  				"min_count": 3,
   875  				"max_count": 3
   876  			}
   877  		}`)
   878  
   879  		w.WriteHeader(http.StatusAccepted)
   880  		w.Header().Add("Content-Type", "application/json")
   881  		fmt.Fprint(w, response)
   882  	})
   883  }
   884  
   885  // HandleServerCreationWithCustomFieldSuccessfully sets up the test server to respond to a server creation request
   886  // with a given response.
   887  func HandleServerCreationWithCustomFieldSuccessfully(t *testing.T, response string) {
   888  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   889  		th.TestMethod(t, r, "POST")
   890  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   891  		th.TestJSONRequest(t, r, `{
   892  			"server": {
   893  				"name": "derp",
   894  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   895  				"flavorRef": "1",
   896  				"foo": "bar"
   897  			}
   898  		}`)
   899  
   900  		w.WriteHeader(http.StatusAccepted)
   901  		w.Header().Add("Content-Type", "application/json")
   902  		fmt.Fprint(w, response)
   903  	})
   904  }
   905  
   906  func HandleServerCreationWithHostname(t *testing.T, response string) {
   907  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   908  		th.TestMethod(t, r, "POST")
   909  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   910  		th.TestJSONRequest(t, r, `{
   911  			"server": {
   912  				"name": "derp",
   913  				"hostname": "derp.local",
   914  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   915  				"flavorRef": "1"
   916  			}
   917  		}`)
   918  
   919  		w.WriteHeader(http.StatusAccepted)
   920  		w.Header().Add("Content-Type", "application/json")
   921  		fmt.Fprint(w, response)
   922  	})
   923  }
   924  
   925  // HandleServerCreationWithUserdata sets up the test server to respond to a server creation request
   926  // with a given response.
   927  func HandleServerCreationWithUserdata(t *testing.T, response string) {
   928  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   929  		th.TestMethod(t, r, "POST")
   930  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   931  		th.TestJSONRequest(t, r, `{
   932  			"server": {
   933  				"name": "derp",
   934  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   935  				"flavorRef": "1",
   936  				"user_data": "dXNlcmRhdGEgc3RyaW5n"
   937  			}
   938  		}`)
   939  
   940  		w.WriteHeader(http.StatusAccepted)
   941  		w.Header().Add("Content-Type", "application/json")
   942  		fmt.Fprint(w, response)
   943  	})
   944  }
   945  
   946  // HandleServerCreationWithMetadata sets up the test server to respond to a server creation request
   947  // with a given response.
   948  func HandleServerCreationWithMetadata(t *testing.T, response string) {
   949  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   950  		th.TestMethod(t, r, "POST")
   951  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   952  		th.TestJSONRequest(t, r, `{
   953  			"server": {
   954  				"name": "derp",
   955  				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
   956  				"flavorRef": "1",
   957  				"metadata": {
   958  					"abc": "def"
   959  				}
   960  			}
   961  		}`)
   962  
   963  		w.WriteHeader(http.StatusAccepted)
   964  		w.Header().Add("Content-Type", "application/json")
   965  		fmt.Fprint(w, response)
   966  	})
   967  }
   968  
   969  // HandleServerListSimpleSuccessfully sets up the test server to respond to a server List request.
   970  func HandleServerListSimpleSuccessfully(t *testing.T) {
   971  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
   972  		th.TestMethod(t, r, "GET")
   973  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   974  
   975  		w.Header().Add("Content-Type", "application/json")
   976  		if err := r.ParseForm(); err != nil {
   977  			t.Errorf("Failed to parse request form %v", err)
   978  		}
   979  		marker := r.Form.Get("marker")
   980  		switch marker {
   981  		case "":
   982  			fmt.Fprint(w, ServerListBody)
   983  		case "9e5476bd-a4ec-4653-93d6-72c93aa682ba":
   984  			fmt.Fprint(w, `{ "servers": [] }`)
   985  		default:
   986  			t.Fatalf("/servers invoked with unexpected marker=[%s]", marker)
   987  		}
   988  	})
   989  }
   990  
   991  // HandleServerListSuccessfully sets up the test server to respond to a server detail List request.
   992  func HandleServerListSuccessfully(t *testing.T) {
   993  	th.Mux.HandleFunc("/servers/detail", func(w http.ResponseWriter, r *http.Request) {
   994  		th.TestMethod(t, r, "GET")
   995  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
   996  
   997  		w.Header().Add("Content-Type", "application/json")
   998  		if err := r.ParseForm(); err != nil {
   999  			t.Errorf("Failed to parse request form %v", err)
  1000  		}
  1001  		marker := r.Form.Get("marker")
  1002  		switch marker {
  1003  		case "":
  1004  			fmt.Fprint(w, ServerListBody)
  1005  		case "9e5476bd-a4ec-4653-93d6-72c93aa682ba":
  1006  			fmt.Fprint(w, `{ "servers": [] }`)
  1007  		default:
  1008  			t.Fatalf("/servers/detail invoked with unexpected marker=[%s]", marker)
  1009  		}
  1010  	})
  1011  }
  1012  
  1013  // HandleServerDeletionSuccessfully sets up the test server to respond to a server deletion request.
  1014  func HandleServerDeletionSuccessfully(t *testing.T) {
  1015  	th.Mux.HandleFunc("/servers/asdfasdfasdf", func(w http.ResponseWriter, r *http.Request) {
  1016  		th.TestMethod(t, r, "DELETE")
  1017  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1018  
  1019  		w.WriteHeader(http.StatusNoContent)
  1020  	})
  1021  }
  1022  
  1023  // HandleServerForceDeletionSuccessfully sets up the test server to respond to a server force deletion
  1024  // request.
  1025  func HandleServerForceDeletionSuccessfully(t *testing.T) {
  1026  	th.Mux.HandleFunc("/servers/asdfasdfasdf/action", func(w http.ResponseWriter, r *http.Request) {
  1027  		th.TestMethod(t, r, "POST")
  1028  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1029  		th.TestJSONRequest(t, r, `{ "forceDelete": "" }`)
  1030  
  1031  		w.WriteHeader(http.StatusAccepted)
  1032  	})
  1033  }
  1034  
  1035  // HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
  1036  func HandleServerGetSuccessfully(t *testing.T) {
  1037  	th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
  1038  		th.TestMethod(t, r, "GET")
  1039  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1040  		th.TestHeader(t, r, "Accept", "application/json")
  1041  
  1042  		fmt.Fprint(w, SingleServerBody)
  1043  	})
  1044  }
  1045  
  1046  // HandleServerGetFaultSuccessfully sets up the test server to respond to a server Get
  1047  // request which contains a fault.
  1048  func HandleServerGetFaultSuccessfully(t *testing.T) {
  1049  	th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
  1050  		th.TestMethod(t, r, "GET")
  1051  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1052  		th.TestHeader(t, r, "Accept", "application/json")
  1053  
  1054  		fmt.Fprint(w, FaultyServerBody)
  1055  	})
  1056  }
  1057  
  1058  // HandleServerUpdateSuccessfully sets up the test server to respond to a server Update request.
  1059  func HandleServerUpdateSuccessfully(t *testing.T) {
  1060  	th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
  1061  		th.TestMethod(t, r, "PUT")
  1062  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1063  		th.TestHeader(t, r, "Accept", "application/json")
  1064  		th.TestHeader(t, r, "Content-Type", "application/json")
  1065  		th.TestJSONRequest(t, r, `{ "server": { "name": "new-name" } }`)
  1066  
  1067  		fmt.Fprint(w, SingleServerBody)
  1068  	})
  1069  }
  1070  
  1071  // HandleAdminPasswordChangeSuccessfully sets up the test server to respond to a server password
  1072  // change request.
  1073  func HandleAdminPasswordChangeSuccessfully(t *testing.T) {
  1074  	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
  1075  		th.TestMethod(t, r, "POST")
  1076  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1077  		th.TestJSONRequest(t, r, `{ "changePassword": { "adminPass": "new-password" } }`)
  1078  
  1079  		w.WriteHeader(http.StatusAccepted)
  1080  	})
  1081  }
  1082  
  1083  // HandleRebootSuccessfully sets up the test server to respond to a reboot request with success.
  1084  func HandleRebootSuccessfully(t *testing.T) {
  1085  	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
  1086  		th.TestMethod(t, r, "POST")
  1087  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1088  		th.TestJSONRequest(t, r, `{ "reboot": { "type": "SOFT" } }`)
  1089  
  1090  		w.WriteHeader(http.StatusAccepted)
  1091  	})
  1092  }
  1093  
  1094  // HandleShowConsoleOutputSuccessfully sets up the test server to respond to a os-getConsoleOutput request with success.
  1095  func HandleShowConsoleOutputSuccessfully(t *testing.T, response string) {
  1096  	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
  1097  		th.TestMethod(t, r, "POST")
  1098  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1099  		th.TestJSONRequest(t, r, `{ "os-getConsoleOutput": { "length": 50 } }`)
  1100  
  1101  		w.WriteHeader(http.StatusOK)
  1102  		w.Header().Add("Content-Type", "application/json")
  1103  		fmt.Fprint(w, response)
  1104  	})
  1105  }
  1106  
  1107  // HandleRebuildSuccessfully sets up the test server to respond to a rebuild request with success.
  1108  func HandleRebuildSuccessfully(t *testing.T, response string) {
  1109  	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
  1110  		th.TestMethod(t, r, "POST")
  1111  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1112  		th.TestJSONRequest(t, r, `
  1113  			{
  1114  				"rebuild": {
  1115  					"name": "new-name",
  1116  					"adminPass": "swordfish",
  1117  					"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
  1118  					"accessIPv4": "1.2.3.4"
  1119  				}
  1120  			}
  1121  		`)
  1122  
  1123  		w.WriteHeader(http.StatusAccepted)
  1124  		w.Header().Add("Content-Type", "application/json")
  1125  		fmt.Fprint(w, response)
  1126  	})
  1127  }
  1128  
  1129  // HandleMetadatumGetSuccessfully sets up the test server to respond to a metadatum Get request.
  1130  func HandleMetadatumGetSuccessfully(t *testing.T) {
  1131  	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
  1132  		th.TestMethod(t, r, "GET")
  1133  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1134  		th.TestHeader(t, r, "Accept", "application/json")
  1135  
  1136  		w.WriteHeader(http.StatusOK)
  1137  		w.Header().Add("Content-Type", "application/json")
  1138  		_, err := w.Write([]byte(`{ "meta": {"foo":"bar"}}`))
  1139  		th.AssertNoErr(t, err)
  1140  	})
  1141  }
  1142  
  1143  // HandleMetadatumCreateSuccessfully sets up the test server to respond to a metadatum Create request.
  1144  func HandleMetadatumCreateSuccessfully(t *testing.T) {
  1145  	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
  1146  		th.TestMethod(t, r, "PUT")
  1147  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1148  		th.TestJSONRequest(t, r, `{
  1149  			"meta": {
  1150  				"foo": "bar"
  1151  			}
  1152  		}`)
  1153  
  1154  		w.WriteHeader(http.StatusOK)
  1155  		w.Header().Add("Content-Type", "application/json")
  1156  		_, err := w.Write([]byte(`{ "meta": {"foo":"bar"}}`))
  1157  		th.AssertNoErr(t, err)
  1158  	})
  1159  }
  1160  
  1161  // HandleMetadatumDeleteSuccessfully sets up the test server to respond to a metadatum Delete request.
  1162  func HandleMetadatumDeleteSuccessfully(t *testing.T) {
  1163  	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
  1164  		th.TestMethod(t, r, "DELETE")
  1165  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1166  
  1167  		w.WriteHeader(http.StatusNoContent)
  1168  	})
  1169  }
  1170  
  1171  // HandleMetadataGetSuccessfully sets up the test server to respond to a metadata Get request.
  1172  func HandleMetadataGetSuccessfully(t *testing.T) {
  1173  	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
  1174  		th.TestMethod(t, r, "GET")
  1175  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1176  		th.TestHeader(t, r, "Accept", "application/json")
  1177  
  1178  		w.WriteHeader(http.StatusOK)
  1179  		_, err := w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`))
  1180  		th.AssertNoErr(t, err)
  1181  	})
  1182  }
  1183  
  1184  // HandleMetadataResetSuccessfully sets up the test server to respond to a metadata Create request.
  1185  func HandleMetadataResetSuccessfully(t *testing.T) {
  1186  	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
  1187  		th.TestMethod(t, r, "PUT")
  1188  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1189  		th.TestJSONRequest(t, r, `{
  1190  				"metadata": {
  1191  					"foo": "bar",
  1192  					"this": "that"
  1193  				}
  1194  			}`)
  1195  
  1196  		w.WriteHeader(http.StatusOK)
  1197  		w.Header().Add("Content-Type", "application/json")
  1198  		_, err := w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`))
  1199  		th.AssertNoErr(t, err)
  1200  	})
  1201  }
  1202  
  1203  // HandleMetadataUpdateSuccessfully sets up the test server to respond to a metadata Update request.
  1204  func HandleMetadataUpdateSuccessfully(t *testing.T) {
  1205  	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
  1206  		th.TestMethod(t, r, "POST")
  1207  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1208  		th.TestJSONRequest(t, r, `{
  1209  				"metadata": {
  1210  					"foo": "baz",
  1211  					"this": "those"
  1212  				}
  1213  			}`)
  1214  
  1215  		w.WriteHeader(http.StatusOK)
  1216  		w.Header().Add("Content-Type", "application/json")
  1217  		_, err := w.Write([]byte(`{ "metadata": {"foo":"baz", "this":"those"}}`))
  1218  		th.AssertNoErr(t, err)
  1219  	})
  1220  }
  1221  
  1222  // ListAddressesExpected represents an expected repsonse from a ListAddresses request.
  1223  var ListAddressesExpected = map[string][]servers.Address{
  1224  	"public": {
  1225  		{
  1226  			Version: 4,
  1227  			Address: "50.56.176.35",
  1228  		},
  1229  		{
  1230  			Version: 6,
  1231  			Address: "2001:4800:790e:510:be76:4eff:fe04:84a8",
  1232  		},
  1233  	},
  1234  	"private": {
  1235  		{
  1236  			Version: 4,
  1237  			Address: "10.180.3.155",
  1238  		},
  1239  	},
  1240  }
  1241  
  1242  // HandleAddressListSuccessfully sets up the test server to respond to a ListAddresses request.
  1243  func HandleAddressListSuccessfully(t *testing.T) {
  1244  	th.Mux.HandleFunc("/servers/asdfasdfasdf/ips", func(w http.ResponseWriter, r *http.Request) {
  1245  		th.TestMethod(t, r, "GET")
  1246  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1247  
  1248  		w.Header().Add("Content-Type", "application/json")
  1249  		fmt.Fprint(w, `{
  1250  			"addresses": {
  1251  				"public": [
  1252  				{
  1253  					"version": 4,
  1254  					"addr": "50.56.176.35"
  1255  				},
  1256  				{
  1257  					"version": 6,
  1258  					"addr": "2001:4800:790e:510:be76:4eff:fe04:84a8"
  1259  				}
  1260  				],
  1261  				"private": [
  1262  				{
  1263  					"version": 4,
  1264  					"addr": "10.180.3.155"
  1265  				}
  1266  				]
  1267  			}
  1268  		}`)
  1269  	})
  1270  }
  1271  
  1272  // ListNetworkAddressesExpected represents an expected repsonse from a ListAddressesByNetwork request.
  1273  var ListNetworkAddressesExpected = []servers.Address{
  1274  	{
  1275  		Version: 4,
  1276  		Address: "50.56.176.35",
  1277  	},
  1278  	{
  1279  		Version: 6,
  1280  		Address: "2001:4800:790e:510:be76:4eff:fe04:84a8",
  1281  	},
  1282  }
  1283  
  1284  // HandleNetworkAddressListSuccessfully sets up the test server to respond to a ListAddressesByNetwork request.
  1285  func HandleNetworkAddressListSuccessfully(t *testing.T) {
  1286  	th.Mux.HandleFunc("/servers/asdfasdfasdf/ips/public", func(w http.ResponseWriter, r *http.Request) {
  1287  		th.TestMethod(t, r, "GET")
  1288  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1289  
  1290  		w.Header().Add("Content-Type", "application/json")
  1291  		fmt.Fprint(w, `{
  1292  			"public": [
  1293  			{
  1294  				"version": 4,
  1295  				"addr": "50.56.176.35"
  1296  				},
  1297  				{
  1298  					"version": 6,
  1299  					"addr": "2001:4800:790e:510:be76:4eff:fe04:84a8"
  1300  				}
  1301  			]
  1302  			}`)
  1303  	})
  1304  }
  1305  
  1306  // HandleCreateServerImageSuccessfully sets up the test server to respond to a TestCreateServerImage request.
  1307  func HandleCreateServerImageSuccessfully(t *testing.T) {
  1308  	th.Mux.HandleFunc("/servers/serverimage/action", func(w http.ResponseWriter, r *http.Request) {
  1309  		th.TestMethod(t, r, "POST")
  1310  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1311  		w.Header().Add("Location", "https://0.0.0.0/images/xxxx-xxxxx-xxxxx-xxxx")
  1312  		w.WriteHeader(http.StatusAccepted)
  1313  	})
  1314  }
  1315  
  1316  // HandlePasswordGetSuccessfully sets up the test server to respond to a password Get request.
  1317  func HandlePasswordGetSuccessfully(t *testing.T) {
  1318  	th.Mux.HandleFunc("/servers/1234asdf/os-server-password", func(w http.ResponseWriter, r *http.Request) {
  1319  		th.TestMethod(t, r, "GET")
  1320  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1321  		th.TestHeader(t, r, "Accept", "application/json")
  1322  
  1323  		fmt.Fprint(w, ServerPasswordBody)
  1324  	})
  1325  }
  1326  
  1327  // HandleServerWithTagsCreationSuccessfully sets up the test server to respond
  1328  // to a server creation request with a given response.
  1329  func HandleServerWithTagsCreationSuccessfully(t *testing.T) {
  1330  	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
  1331  		th.TestMethod(t, r, "POST")
  1332  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1333  		th.TestJSONRequest(t, r, ServerWithTagsCreateRequest)
  1334  
  1335  		w.WriteHeader(http.StatusAccepted)
  1336  		w.Header().Add("Content-Type", "application/json")
  1337  
  1338  		fmt.Fprint(w, SingleServerWithTagsBody)
  1339  	})
  1340  }