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