mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	Move deps from _workspace/ to vendor/
godep restore pushd $GOPATH/src/github.com/appc/spec git co master popd go get go4.org/errorutil rm -rf Godeps godep save ./... git add vendor git add -f $(git ls-files --other vendor/) git co -- Godeps/LICENSES Godeps/.license_file_state Godeps/OWNERS
This commit is contained in:
		
							
								
								
									
										6
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
// Package servers provides information and interaction with the server API
 | 
			
		||||
// resource in the OpenStack Compute service.
 | 
			
		||||
//
 | 
			
		||||
// A server is a virtual machine instance in the compute system. In order for
 | 
			
		||||
// one to be provisioned, a valid flavor and image are required.
 | 
			
		||||
package servers
 | 
			
		||||
							
								
								
									
										692
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										692
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,692 @@
 | 
			
		||||
// +build fixtures
 | 
			
		||||
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	th "github.com/rackspace/gophercloud/testhelper"
 | 
			
		||||
	"github.com/rackspace/gophercloud/testhelper/client"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ServerListBody contains the canned body of a servers.List response.
 | 
			
		||||
const ServerListBody = `
 | 
			
		||||
{
 | 
			
		||||
	"servers": [
 | 
			
		||||
		{
 | 
			
		||||
			"status": "ACTIVE",
 | 
			
		||||
			"updated": "2014-09-25T13:10:10Z",
 | 
			
		||||
			"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:host": "devstack",
 | 
			
		||||
			"addresses": {
 | 
			
		||||
				"private": [
 | 
			
		||||
					{
 | 
			
		||||
						"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b",
 | 
			
		||||
						"version": 4,
 | 
			
		||||
						"addr": "10.0.0.32",
 | 
			
		||||
						"OS-EXT-IPS:type": "fixed"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"links": [
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
					"rel": "self"
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
					"rel": "bookmark"
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"key_name": null,
 | 
			
		||||
			"image": {
 | 
			
		||||
				"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
				"links": [
 | 
			
		||||
					{
 | 
			
		||||
						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
						"rel": "bookmark"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"OS-EXT-STS:task_state": null,
 | 
			
		||||
			"OS-EXT-STS:vm_state": "active",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:instance_name": "instance-0000001e",
 | 
			
		||||
			"OS-SRV-USG:launched_at": "2014-09-25T13:10:10.000000",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
 | 
			
		||||
			"flavor": {
 | 
			
		||||
				"id": "1",
 | 
			
		||||
				"links": [
 | 
			
		||||
					{
 | 
			
		||||
						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
 | 
			
		||||
						"rel": "bookmark"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"id": "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
			"security_groups": [
 | 
			
		||||
				{
 | 
			
		||||
					"name": "default"
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"OS-SRV-USG:terminated_at": null,
 | 
			
		||||
			"OS-EXT-AZ:availability_zone": "nova",
 | 
			
		||||
			"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
 | 
			
		||||
			"name": "herp",
 | 
			
		||||
			"created": "2014-09-25T13:10:02Z",
 | 
			
		||||
			"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
 | 
			
		||||
			"OS-DCF:diskConfig": "MANUAL",
 | 
			
		||||
			"os-extended-volumes:volumes_attached": [],
 | 
			
		||||
			"accessIPv4": "",
 | 
			
		||||
			"accessIPv6": "",
 | 
			
		||||
			"progress": 0,
 | 
			
		||||
			"OS-EXT-STS:power_state": 1,
 | 
			
		||||
			"config_drive": "",
 | 
			
		||||
			"metadata": {}
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"status": "ACTIVE",
 | 
			
		||||
			"updated": "2014-09-25T13:04:49Z",
 | 
			
		||||
			"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:host": "devstack",
 | 
			
		||||
			"addresses": {
 | 
			
		||||
				"private": [
 | 
			
		||||
					{
 | 
			
		||||
						"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
 | 
			
		||||
						"version": 4,
 | 
			
		||||
						"addr": "10.0.0.31",
 | 
			
		||||
						"OS-EXT-IPS:type": "fixed"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"links": [
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
					"rel": "self"
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
					"rel": "bookmark"
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"key_name": null,
 | 
			
		||||
			"image": {
 | 
			
		||||
				"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
				"links": [
 | 
			
		||||
					{
 | 
			
		||||
						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
						"rel": "bookmark"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"OS-EXT-STS:task_state": null,
 | 
			
		||||
			"OS-EXT-STS:vm_state": "active",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
 | 
			
		||||
			"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
 | 
			
		||||
			"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
 | 
			
		||||
			"flavor": {
 | 
			
		||||
				"id": "1",
 | 
			
		||||
				"links": [
 | 
			
		||||
					{
 | 
			
		||||
						"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
 | 
			
		||||
						"rel": "bookmark"
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			},
 | 
			
		||||
			"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
			"security_groups": [
 | 
			
		||||
				{
 | 
			
		||||
					"name": "default"
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"OS-SRV-USG:terminated_at": null,
 | 
			
		||||
			"OS-EXT-AZ:availability_zone": "nova",
 | 
			
		||||
			"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
 | 
			
		||||
			"name": "derp",
 | 
			
		||||
			"created": "2014-09-25T13:04:41Z",
 | 
			
		||||
			"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
 | 
			
		||||
			"OS-DCF:diskConfig": "MANUAL",
 | 
			
		||||
			"os-extended-volumes:volumes_attached": [],
 | 
			
		||||
			"accessIPv4": "",
 | 
			
		||||
			"accessIPv6": "",
 | 
			
		||||
			"progress": 0,
 | 
			
		||||
			"OS-EXT-STS:power_state": 1,
 | 
			
		||||
			"config_drive": "",
 | 
			
		||||
			"metadata": {}
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
// SingleServerBody is the canned body of a Get request on an existing server.
 | 
			
		||||
const SingleServerBody = `
 | 
			
		||||
{
 | 
			
		||||
	"server": {
 | 
			
		||||
		"status": "ACTIVE",
 | 
			
		||||
		"updated": "2014-09-25T13:04:49Z",
 | 
			
		||||
		"hostId": "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
 | 
			
		||||
		"OS-EXT-SRV-ATTR:host": "devstack",
 | 
			
		||||
		"addresses": {
 | 
			
		||||
			"private": [
 | 
			
		||||
				{
 | 
			
		||||
					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
 | 
			
		||||
					"version": 4,
 | 
			
		||||
					"addr": "10.0.0.31",
 | 
			
		||||
					"OS-EXT-IPS:type": "fixed"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"links": [
 | 
			
		||||
			{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
				"rel": "self"
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
				"rel": "bookmark"
 | 
			
		||||
			}
 | 
			
		||||
		],
 | 
			
		||||
		"key_name": null,
 | 
			
		||||
		"image": {
 | 
			
		||||
			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
			"links": [
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
					"rel": "bookmark"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"OS-EXT-STS:task_state": null,
 | 
			
		||||
		"OS-EXT-STS:vm_state": "active",
 | 
			
		||||
		"OS-EXT-SRV-ATTR:instance_name": "instance-0000001d",
 | 
			
		||||
		"OS-SRV-USG:launched_at": "2014-09-25T13:04:49.000000",
 | 
			
		||||
		"OS-EXT-SRV-ATTR:hypervisor_hostname": "devstack",
 | 
			
		||||
		"flavor": {
 | 
			
		||||
			"id": "1",
 | 
			
		||||
			"links": [
 | 
			
		||||
				{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
 | 
			
		||||
					"rel": "bookmark"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"id": "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
		"security_groups": [
 | 
			
		||||
			{
 | 
			
		||||
				"name": "default"
 | 
			
		||||
			}
 | 
			
		||||
		],
 | 
			
		||||
		"OS-SRV-USG:terminated_at": null,
 | 
			
		||||
		"OS-EXT-AZ:availability_zone": "nova",
 | 
			
		||||
		"user_id": "9349aff8be7545ac9d2f1d00999a23cd",
 | 
			
		||||
		"name": "derp",
 | 
			
		||||
		"created": "2014-09-25T13:04:41Z",
 | 
			
		||||
		"tenant_id": "fcad67a6189847c4aecfa3c81a05783b",
 | 
			
		||||
		"OS-DCF:diskConfig": "MANUAL",
 | 
			
		||||
		"os-extended-volumes:volumes_attached": [],
 | 
			
		||||
		"accessIPv4": "",
 | 
			
		||||
		"accessIPv6": "",
 | 
			
		||||
		"progress": 0,
 | 
			
		||||
		"OS-EXT-STS:power_state": 1,
 | 
			
		||||
		"config_drive": "",
 | 
			
		||||
		"metadata": {}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
const ServerPasswordBody = `
 | 
			
		||||
{
 | 
			
		||||
    "password": "xlozO3wLCBRWAa2yDjCCVx8vwNPypxnypmRYDa/zErlQ+EzPe1S/Gz6nfmC52mOlOSCRuUOmG7kqqgejPof6M7bOezS387zjq4LSvvwp28zUknzy4YzfFGhnHAdai3TxUJ26pfQCYrq8UTzmKF2Bq8ioSEtVVzM0A96pDh8W2i7BOz6MdoiVyiev/I1K2LsuipfxSJR7Wdke4zNXJjHHP2RfYsVbZ/k9ANu+Nz4iIH8/7Cacud/pphH7EjrY6a4RZNrjQskrhKYed0YERpotyjYk1eDtRe72GrSiXteqCM4biaQ5w3ruS+AcX//PXk3uJ5kC7d67fPXaVz4WaQRYMg=="
 | 
			
		||||
}
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ServerHerp is a Server struct that should correspond to the first result in ServerListBody.
 | 
			
		||||
	ServerHerp = Server{
 | 
			
		||||
		Status:  "ACTIVE",
 | 
			
		||||
		Updated: "2014-09-25T13:10:10Z",
 | 
			
		||||
		HostID:  "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
 | 
			
		||||
		Addresses: map[string]interface{}{
 | 
			
		||||
			"private": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b",
 | 
			
		||||
					"version":                 float64(4),
 | 
			
		||||
					"addr":                    "10.0.0.32",
 | 
			
		||||
					"OS-EXT-IPS:type":         "fixed",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Links: []interface{}{
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
				"rel":  "self",
 | 
			
		||||
			},
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
				"rel":  "bookmark",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Image: map[string]interface{}{
 | 
			
		||||
			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
			"links": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
					"rel":  "bookmark",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Flavor: map[string]interface{}{
 | 
			
		||||
			"id": "1",
 | 
			
		||||
			"links": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
 | 
			
		||||
					"rel":  "bookmark",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		ID:       "ef079b0c-e610-4dfb-b1aa-b49f07ac48e5",
 | 
			
		||||
		UserID:   "9349aff8be7545ac9d2f1d00999a23cd",
 | 
			
		||||
		Name:     "herp",
 | 
			
		||||
		Created:  "2014-09-25T13:10:02Z",
 | 
			
		||||
		TenantID: "fcad67a6189847c4aecfa3c81a05783b",
 | 
			
		||||
		Metadata: map[string]interface{}{},
 | 
			
		||||
		SecurityGroups: []map[string]interface{}{
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"name": "default",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ServerDerp is a Server struct that should correspond to the second server in ServerListBody.
 | 
			
		||||
	ServerDerp = Server{
 | 
			
		||||
		Status:  "ACTIVE",
 | 
			
		||||
		Updated: "2014-09-25T13:04:49Z",
 | 
			
		||||
		HostID:  "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
 | 
			
		||||
		Addresses: map[string]interface{}{
 | 
			
		||||
			"private": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:9e:89:be",
 | 
			
		||||
					"version":                 float64(4),
 | 
			
		||||
					"addr":                    "10.0.0.31",
 | 
			
		||||
					"OS-EXT-IPS:type":         "fixed",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Links: []interface{}{
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/v2/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
				"rel":  "self",
 | 
			
		||||
			},
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/servers/9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
				"rel":  "bookmark",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Image: map[string]interface{}{
 | 
			
		||||
			"id": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
			"links": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
					"rel":  "bookmark",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Flavor: map[string]interface{}{
 | 
			
		||||
			"id": "1",
 | 
			
		||||
			"links": []interface{}{
 | 
			
		||||
				map[string]interface{}{
 | 
			
		||||
					"href": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/flavors/1",
 | 
			
		||||
					"rel":  "bookmark",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		ID:       "9e5476bd-a4ec-4653-93d6-72c93aa682ba",
 | 
			
		||||
		UserID:   "9349aff8be7545ac9d2f1d00999a23cd",
 | 
			
		||||
		Name:     "derp",
 | 
			
		||||
		Created:  "2014-09-25T13:04:41Z",
 | 
			
		||||
		TenantID: "fcad67a6189847c4aecfa3c81a05783b",
 | 
			
		||||
		Metadata: map[string]interface{}{},
 | 
			
		||||
		SecurityGroups: []map[string]interface{}{
 | 
			
		||||
			map[string]interface{}{
 | 
			
		||||
				"name": "default",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// HandleServerCreationSuccessfully sets up the test server to respond to a server creation request
 | 
			
		||||
// with a given response.
 | 
			
		||||
func HandleServerCreationSuccessfully(t *testing.T, response string) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{
 | 
			
		||||
			"server": {
 | 
			
		||||
				"name": "derp",
 | 
			
		||||
				"imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
				"flavorRef": "1"
 | 
			
		||||
			}
 | 
			
		||||
		}`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		fmt.Fprintf(w, response)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerListSuccessfully sets up the test server to respond to a server List request.
 | 
			
		||||
func HandleServerListSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/detail", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		r.ParseForm()
 | 
			
		||||
		marker := r.Form.Get("marker")
 | 
			
		||||
		switch marker {
 | 
			
		||||
		case "":
 | 
			
		||||
			fmt.Fprintf(w, ServerListBody)
 | 
			
		||||
		case "9e5476bd-a4ec-4653-93d6-72c93aa682ba":
 | 
			
		||||
			fmt.Fprintf(w, `{ "servers": [] }`)
 | 
			
		||||
		default:
 | 
			
		||||
			t.Fatalf("/servers/detail invoked with unexpected marker=[%s]", marker)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerDeletionSuccessfully sets up the test server to respond to a server deletion request.
 | 
			
		||||
func HandleServerDeletionSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/asdfasdfasdf", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "DELETE")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusNoContent)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerForceDeletionSuccessfully sets up the test server to respond to a server force deletion
 | 
			
		||||
// request.
 | 
			
		||||
func HandleServerForceDeletionSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/asdfasdfasdf/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{ "forceDelete": "" }`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
 | 
			
		||||
func HandleServerGetSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestHeader(t, r, "Accept", "application/json")
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(w, SingleServerBody)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerUpdateSuccessfully sets up the test server to respond to a server Update request.
 | 
			
		||||
func HandleServerUpdateSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "PUT")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestHeader(t, r, "Accept", "application/json")
 | 
			
		||||
		th.TestHeader(t, r, "Content-Type", "application/json")
 | 
			
		||||
		th.TestJSONRequest(t, r, `{ "server": { "name": "new-name" } }`)
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(w, SingleServerBody)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleAdminPasswordChangeSuccessfully sets up the test server to respond to a server password
 | 
			
		||||
// change request.
 | 
			
		||||
func HandleAdminPasswordChangeSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{ "changePassword": { "adminPass": "new-password" } }`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleRebootSuccessfully sets up the test server to respond to a reboot request with success.
 | 
			
		||||
func HandleRebootSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{ "reboot": { "type": "SOFT" } }`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleRebuildSuccessfully sets up the test server to respond to a rebuild request with success.
 | 
			
		||||
func HandleRebuildSuccessfully(t *testing.T, response string) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `
 | 
			
		||||
			{
 | 
			
		||||
				"rebuild": {
 | 
			
		||||
					"name": "new-name",
 | 
			
		||||
					"adminPass": "swordfish",
 | 
			
		||||
					"imageRef": "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
 | 
			
		||||
					"accessIPv4": "1.2.3.4"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		fmt.Fprintf(w, response)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleServerRescueSuccessfully sets up the test server to respond to a server Rescue request.
 | 
			
		||||
func HandleServerRescueSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{ "rescue": { "adminPass": "1234567890" } }`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Write([]byte(`{ "adminPass": "1234567890" }`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadatumGetSuccessfully sets up the test server to respond to a metadatum Get request.
 | 
			
		||||
func HandleMetadatumGetSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestHeader(t, r, "Accept", "application/json")
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		w.Write([]byte(`{ "meta": {"foo":"bar"}}`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadatumCreateSuccessfully sets up the test server to respond to a metadatum Create request.
 | 
			
		||||
func HandleMetadatumCreateSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "PUT")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{
 | 
			
		||||
			"meta": {
 | 
			
		||||
				"foo": "bar"
 | 
			
		||||
			}
 | 
			
		||||
		}`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		w.Write([]byte(`{ "meta": {"foo":"bar"}}`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadatumDeleteSuccessfully sets up the test server to respond to a metadatum Delete request.
 | 
			
		||||
func HandleMetadatumDeleteSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata/foo", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "DELETE")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusNoContent)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadataGetSuccessfully sets up the test server to respond to a metadata Get request.
 | 
			
		||||
func HandleMetadataGetSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestHeader(t, r, "Accept", "application/json")
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadataResetSuccessfully sets up the test server to respond to a metadata Create request.
 | 
			
		||||
func HandleMetadataResetSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "PUT")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{
 | 
			
		||||
				"metadata": {
 | 
			
		||||
					"foo": "bar",
 | 
			
		||||
					"this": "that"
 | 
			
		||||
				}
 | 
			
		||||
			}`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		w.Write([]byte(`{ "metadata": {"foo":"bar", "this":"that"}}`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleMetadataUpdateSuccessfully sets up the test server to respond to a metadata Update request.
 | 
			
		||||
func HandleMetadataUpdateSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/metadata", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestJSONRequest(t, r, `{
 | 
			
		||||
				"metadata": {
 | 
			
		||||
					"foo": "baz",
 | 
			
		||||
					"this": "those"
 | 
			
		||||
				}
 | 
			
		||||
			}`)
 | 
			
		||||
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		w.Write([]byte(`{ "metadata": {"foo":"baz", "this":"those"}}`))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListAddressesExpected represents an expected repsonse from a ListAddresses request.
 | 
			
		||||
var ListAddressesExpected = map[string][]Address{
 | 
			
		||||
	"public": []Address{
 | 
			
		||||
		Address{
 | 
			
		||||
			Version: 4,
 | 
			
		||||
			Address: "80.56.136.39",
 | 
			
		||||
		},
 | 
			
		||||
		Address{
 | 
			
		||||
			Version: 6,
 | 
			
		||||
			Address: "2001:4800:790e:510:be76:4eff:fe04:82a8",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"private": []Address{
 | 
			
		||||
		Address{
 | 
			
		||||
			Version: 4,
 | 
			
		||||
			Address: "10.880.3.154",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleAddressListSuccessfully sets up the test server to respond to a ListAddresses request.
 | 
			
		||||
func HandleAddressListSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/asdfasdfasdf/ips", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		fmt.Fprintf(w, `{
 | 
			
		||||
			"addresses": {
 | 
			
		||||
				"public": [
 | 
			
		||||
				{
 | 
			
		||||
					"version": 4,
 | 
			
		||||
					"addr": "50.56.176.35"
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"version": 6,
 | 
			
		||||
					"addr": "2001:4800:780e:510:be76:4eff:fe04:84a8"
 | 
			
		||||
				}
 | 
			
		||||
				],
 | 
			
		||||
				"private": [
 | 
			
		||||
				{
 | 
			
		||||
					"version": 4,
 | 
			
		||||
					"addr": "10.180.3.155"
 | 
			
		||||
				}
 | 
			
		||||
				]
 | 
			
		||||
			}
 | 
			
		||||
		}`)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListNetworkAddressesExpected represents an expected repsonse from a ListAddressesByNetwork request.
 | 
			
		||||
var ListNetworkAddressesExpected = []Address{
 | 
			
		||||
	Address{
 | 
			
		||||
		Version: 4,
 | 
			
		||||
		Address: "50.56.176.35",
 | 
			
		||||
	},
 | 
			
		||||
	Address{
 | 
			
		||||
		Version: 6,
 | 
			
		||||
		Address: "2001:4800:780e:510:be76:4eff:fe04:84a8",
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleNetworkAddressListSuccessfully sets up the test server to respond to a ListAddressesByNetwork request.
 | 
			
		||||
func HandleNetworkAddressListSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/asdfasdfasdf/ips/public", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
 | 
			
		||||
		w.Header().Add("Content-Type", "application/json")
 | 
			
		||||
		fmt.Fprintf(w, `{
 | 
			
		||||
			"public": [
 | 
			
		||||
			{
 | 
			
		||||
				"version": 4,
 | 
			
		||||
				"addr": "50.56.176.35"
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"version": 6,
 | 
			
		||||
					"addr": "2001:4800:780e:510:be76:4eff:fe04:84a8"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
			}`)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleCreateServerImageSuccessfully sets up the test server to respond to a TestCreateServerImage request.
 | 
			
		||||
func HandleCreateServerImageSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/serverimage/action", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "POST")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		w.Header().Add("Location", "https://0.0.0.0/images/xxxx-xxxxx-xxxxx-xxxx")
 | 
			
		||||
		w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandlePasswordGetSuccessfully sets up the test server to respond to a password Get request.
 | 
			
		||||
func HandlePasswordGetSuccessfully(t *testing.T) {
 | 
			
		||||
	th.Mux.HandleFunc("/servers/1234asdf/os-server-password", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		th.TestMethod(t, r, "GET")
 | 
			
		||||
		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
 | 
			
		||||
		th.TestHeader(t, r, "Accept", "application/json")
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(w, ServerPasswordBody)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										872
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										872
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,872 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/images"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToServerListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
// the API. Filtering is achieved by passing in struct field values that map to
 | 
			
		||||
// the server attributes you want to see returned. Marker and Limit are used
 | 
			
		||||
// for pagination.
 | 
			
		||||
type ListOpts struct {
 | 
			
		||||
	// A time/date stamp for when the server last changed status.
 | 
			
		||||
	ChangesSince string `q:"changes-since"`
 | 
			
		||||
 | 
			
		||||
	// Name of the image in URL format.
 | 
			
		||||
	Image string `q:"image"`
 | 
			
		||||
 | 
			
		||||
	// Name of the flavor in URL format.
 | 
			
		||||
	Flavor string `q:"flavor"`
 | 
			
		||||
 | 
			
		||||
	// Name of the server as a string; can be queried with regular expressions.
 | 
			
		||||
	// Realize that ?name=bob returns both bob and bobb. If you need to match bob
 | 
			
		||||
	// only, you can use a regular expression matching the syntax of the
 | 
			
		||||
	// underlying database server implemented for Compute.
 | 
			
		||||
	Name string `q:"name"`
 | 
			
		||||
 | 
			
		||||
	// Value of the status of the server so that you can filter on "ACTIVE" for example.
 | 
			
		||||
	Status string `q:"status"`
 | 
			
		||||
 | 
			
		||||
	// Name of the host as a string.
 | 
			
		||||
	Host string `q:"host"`
 | 
			
		||||
 | 
			
		||||
	// UUID of the server at which you want to set a marker.
 | 
			
		||||
	Marker string `q:"marker"`
 | 
			
		||||
 | 
			
		||||
	// Integer value for the limit of values to return.
 | 
			
		||||
	Limit int `q:"limit"`
 | 
			
		||||
 | 
			
		||||
	// Bool to show all tenants
 | 
			
		||||
	AllTenants bool `q:"all_tenants"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToServerListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return q.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List makes a request against the API to list servers accessible to you.
 | 
			
		||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := listDetailURL(client)
 | 
			
		||||
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToServerListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	createPageFn := func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return ServerPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(client, url, createPageFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
 | 
			
		||||
// The CreateOpts struct in this package does.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToServerCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Network is used within CreateOpts to control a new server's network attachments.
 | 
			
		||||
type Network struct {
 | 
			
		||||
	// UUID of a nova-network to attach to the newly provisioned server.
 | 
			
		||||
	// Required unless Port is provided.
 | 
			
		||||
	UUID string
 | 
			
		||||
 | 
			
		||||
	// Port of a neutron network to attach to the newly provisioned server.
 | 
			
		||||
	// Required unless UUID is provided.
 | 
			
		||||
	Port string
 | 
			
		||||
 | 
			
		||||
	// FixedIP [optional] specifies a fixed IPv4 address to be used on this network.
 | 
			
		||||
	FixedIP string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Personality is an array of files that are injected into the server at launch.
 | 
			
		||||
type Personality []*File
 | 
			
		||||
 | 
			
		||||
// File is used within CreateOpts and RebuildOpts to inject a file into the server at launch.
 | 
			
		||||
// File implements the json.Marshaler interface, so when a Create or Rebuild operation is requested,
 | 
			
		||||
// json.Marshal will call File's MarshalJSON method.
 | 
			
		||||
type File struct {
 | 
			
		||||
	// Path of the file
 | 
			
		||||
	Path string
 | 
			
		||||
	// Contents of the file. Maximum content size is 255 bytes.
 | 
			
		||||
	Contents []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON marshals the escaped file, base64 encoding the contents.
 | 
			
		||||
func (f *File) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	file := struct {
 | 
			
		||||
		Path     string `json:"path"`
 | 
			
		||||
		Contents string `json:"contents"`
 | 
			
		||||
	}{
 | 
			
		||||
		Path:     f.Path,
 | 
			
		||||
		Contents: base64.StdEncoding.EncodeToString(f.Contents),
 | 
			
		||||
	}
 | 
			
		||||
	return json.Marshal(file)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts specifies server creation parameters.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Name [required] is the name to assign to the newly launched server.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// ImageRef [optional; required if ImageName is not provided] is the ID or full
 | 
			
		||||
	// URL to the image that contains the server's OS and initial state.
 | 
			
		||||
	// Also optional if using the boot-from-volume extension.
 | 
			
		||||
	ImageRef string
 | 
			
		||||
 | 
			
		||||
	// ImageName [optional; required if ImageRef is not provided] is the name of the
 | 
			
		||||
	// image that contains the server's OS and initial state.
 | 
			
		||||
	// Also optional if using the boot-from-volume extension.
 | 
			
		||||
	ImageName string
 | 
			
		||||
 | 
			
		||||
	// FlavorRef [optional; required if FlavorName is not provided] is the ID or
 | 
			
		||||
	// full URL to the flavor that describes the server's specs.
 | 
			
		||||
	FlavorRef string
 | 
			
		||||
 | 
			
		||||
	// FlavorName [optional; required if FlavorRef is not provided] is the name of
 | 
			
		||||
	// the flavor that describes the server's specs.
 | 
			
		||||
	FlavorName string
 | 
			
		||||
 | 
			
		||||
	// SecurityGroups [optional] lists the names of the security groups to which this server should belong.
 | 
			
		||||
	SecurityGroups []string
 | 
			
		||||
 | 
			
		||||
	// UserData [optional] contains configuration information or scripts to use upon launch.
 | 
			
		||||
	// Create will base64-encode it for you.
 | 
			
		||||
	UserData []byte
 | 
			
		||||
 | 
			
		||||
	// AvailabilityZone [optional] in which to launch the server.
 | 
			
		||||
	AvailabilityZone string
 | 
			
		||||
 | 
			
		||||
	// Networks [optional] dictates how this server will be attached to available networks.
 | 
			
		||||
	// By default, the server will be attached to all isolated networks for the tenant.
 | 
			
		||||
	Networks []Network
 | 
			
		||||
 | 
			
		||||
	// Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
 | 
			
		||||
	Metadata map[string]string
 | 
			
		||||
 | 
			
		||||
	// Personality [optional] includes files to inject into the server at launch.
 | 
			
		||||
	// Create will base64-encode file contents for you.
 | 
			
		||||
	Personality Personality
 | 
			
		||||
 | 
			
		||||
	// ConfigDrive [optional] enables metadata injection through a configuration drive.
 | 
			
		||||
	ConfigDrive bool
 | 
			
		||||
 | 
			
		||||
	// AdminPass [optional] sets the root user password. If not set, a randomly-generated
 | 
			
		||||
	// password will be created and returned in the response.
 | 
			
		||||
	AdminPass string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 [optional] specifies an IPv4 address for the instance.
 | 
			
		||||
	AccessIPv4 string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv6 [optional] specifies an IPv6 address for the instance.
 | 
			
		||||
	AccessIPv6 string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerCreateMap assembles a request body based on the contents of a CreateOpts.
 | 
			
		||||
func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	server := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	server["name"] = opts.Name
 | 
			
		||||
	server["imageRef"] = opts.ImageRef
 | 
			
		||||
	server["imageName"] = opts.ImageName
 | 
			
		||||
	server["flavorRef"] = opts.FlavorRef
 | 
			
		||||
	server["flavorName"] = opts.FlavorName
 | 
			
		||||
 | 
			
		||||
	if opts.UserData != nil {
 | 
			
		||||
		encoded := base64.StdEncoding.EncodeToString(opts.UserData)
 | 
			
		||||
		server["user_data"] = &encoded
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ConfigDrive {
 | 
			
		||||
		server["config_drive"] = "true"
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AvailabilityZone != "" {
 | 
			
		||||
		server["availability_zone"] = opts.AvailabilityZone
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Metadata != nil {
 | 
			
		||||
		server["metadata"] = opts.Metadata
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminPass != "" {
 | 
			
		||||
		server["adminPass"] = opts.AdminPass
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AccessIPv4 != "" {
 | 
			
		||||
		server["accessIPv4"] = opts.AccessIPv4
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AccessIPv6 != "" {
 | 
			
		||||
		server["accessIPv6"] = opts.AccessIPv6
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.SecurityGroups) > 0 {
 | 
			
		||||
		securityGroups := make([]map[string]interface{}, len(opts.SecurityGroups))
 | 
			
		||||
		for i, groupName := range opts.SecurityGroups {
 | 
			
		||||
			securityGroups[i] = map[string]interface{}{"name": groupName}
 | 
			
		||||
		}
 | 
			
		||||
		server["security_groups"] = securityGroups
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.Networks) > 0 {
 | 
			
		||||
		networks := make([]map[string]interface{}, len(opts.Networks))
 | 
			
		||||
		for i, net := range opts.Networks {
 | 
			
		||||
			networks[i] = make(map[string]interface{})
 | 
			
		||||
			if net.UUID != "" {
 | 
			
		||||
				networks[i]["uuid"] = net.UUID
 | 
			
		||||
			}
 | 
			
		||||
			if net.Port != "" {
 | 
			
		||||
				networks[i]["port"] = net.Port
 | 
			
		||||
			}
 | 
			
		||||
			if net.FixedIP != "" {
 | 
			
		||||
				networks[i]["fixed_ip"] = net.FixedIP
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		server["networks"] = networks
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.Personality) > 0 {
 | 
			
		||||
		server["personality"] = opts.Personality
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"server": server}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create requests a server to be provisioned to the user in the current tenant.
 | 
			
		||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToServerCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If ImageRef isn't provided, use ImageName to ascertain the image ID.
 | 
			
		||||
	if reqBody["server"].(map[string]interface{})["imageRef"].(string) == "" {
 | 
			
		||||
		imageName := reqBody["server"].(map[string]interface{})["imageName"].(string)
 | 
			
		||||
		if imageName == "" {
 | 
			
		||||
			res.Err = errors.New("One and only one of ImageRef and ImageName must be provided.")
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		imageID, err := images.IDFromName(client, imageName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			res.Err = err
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		reqBody["server"].(map[string]interface{})["imageRef"] = imageID
 | 
			
		||||
	}
 | 
			
		||||
	delete(reqBody["server"].(map[string]interface{}), "imageName")
 | 
			
		||||
 | 
			
		||||
	// If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID.
 | 
			
		||||
	if reqBody["server"].(map[string]interface{})["flavorRef"].(string) == "" {
 | 
			
		||||
		flavorName := reqBody["server"].(map[string]interface{})["flavorName"].(string)
 | 
			
		||||
		if flavorName == "" {
 | 
			
		||||
			res.Err = errors.New("One and only one of FlavorRef and FlavorName must be provided.")
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		flavorID, err := flavors.IDFromName(client, flavorName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			res.Err = err
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		reqBody["server"].(map[string]interface{})["flavorRef"] = flavorID
 | 
			
		||||
	}
 | 
			
		||||
	delete(reqBody["server"].(map[string]interface{}), "flavorName")
 | 
			
		||||
 | 
			
		||||
	_, res.Err = client.Post(listURL(client), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete requests that a server previously provisioned be removed from your account.
 | 
			
		||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = client.Delete(deleteURL(client, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ForceDelete(client *gophercloud.ServiceClient, id string) ActionResult {
 | 
			
		||||
	var req struct {
 | 
			
		||||
		ForceDelete string `json:"forceDelete"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), req, nil, nil)
 | 
			
		||||
	return res
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get requests details on a single server, by ID.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var result GetResult
 | 
			
		||||
	_, result.Err = client.Get(getURL(client, id), &result.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 203},
 | 
			
		||||
	})
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToServerUpdateMap() map[string]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts specifies the base attributes that may be updated on an existing server.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Name [optional] changes the displayed name of the server.
 | 
			
		||||
	// The server host name will *not* change.
 | 
			
		||||
	// Server names are not constrained to be unique, even within the same tenant.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 [optional] provides a new IPv4 address for the instance.
 | 
			
		||||
	AccessIPv4 string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv6 [optional] provides a new IPv6 address for the instance.
 | 
			
		||||
	AccessIPv6 string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerUpdateMap formats an UpdateOpts structure into a request body.
 | 
			
		||||
func (opts UpdateOpts) ToServerUpdateMap() map[string]interface{} {
 | 
			
		||||
	server := make(map[string]string)
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		server["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AccessIPv4 != "" {
 | 
			
		||||
		server["accessIPv4"] = opts.AccessIPv4
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AccessIPv6 != "" {
 | 
			
		||||
		server["accessIPv6"] = opts.AccessIPv6
 | 
			
		||||
	}
 | 
			
		||||
	return map[string]interface{}{"server": server}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update requests that various attributes of the indicated server be changed.
 | 
			
		||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
 | 
			
		||||
	var result UpdateResult
 | 
			
		||||
	reqBody := opts.ToServerUpdateMap()
 | 
			
		||||
	_, result.Err = client.Put(updateURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChangeAdminPassword alters the administrator or root password for a specified server.
 | 
			
		||||
func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) ActionResult {
 | 
			
		||||
	var req struct {
 | 
			
		||||
		ChangePassword struct {
 | 
			
		||||
			AdminPass string `json:"adminPass"`
 | 
			
		||||
		} `json:"changePassword"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.ChangePassword.AdminPass = newPassword
 | 
			
		||||
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), req, nil, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrArgument errors occur when an argument supplied to a package function
 | 
			
		||||
// fails to fall within acceptable values.  For example, the Reboot() function
 | 
			
		||||
// expects the "how" parameter to be one of HardReboot or SoftReboot.  These
 | 
			
		||||
// constants are (currently) strings, leading someone to wonder if they can pass
 | 
			
		||||
// other string values instead, perhaps in an effort to break the API of their
 | 
			
		||||
// provider.  Reboot() returns this error in this situation.
 | 
			
		||||
//
 | 
			
		||||
// Function identifies which function was called/which function is generating
 | 
			
		||||
// the error.
 | 
			
		||||
// Argument identifies which formal argument was responsible for producing the
 | 
			
		||||
// error.
 | 
			
		||||
// Value provides the value as it was passed into the function.
 | 
			
		||||
type ErrArgument struct {
 | 
			
		||||
	Function, Argument string
 | 
			
		||||
	Value              interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error yields a useful diagnostic for debugging purposes.
 | 
			
		||||
func (e *ErrArgument) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Bad argument in call to %s, formal parameter %s, value %#v", e.Function, e.Argument, e.Value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *ErrArgument) String() string {
 | 
			
		||||
	return e.Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebootMethod describes the mechanisms by which a server reboot can be requested.
 | 
			
		||||
type RebootMethod string
 | 
			
		||||
 | 
			
		||||
// These constants determine how a server should be rebooted.
 | 
			
		||||
// See the Reboot() function for further details.
 | 
			
		||||
const (
 | 
			
		||||
	SoftReboot RebootMethod = "SOFT"
 | 
			
		||||
	HardReboot RebootMethod = "HARD"
 | 
			
		||||
	OSReboot                = SoftReboot
 | 
			
		||||
	PowerCycle              = HardReboot
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Reboot requests that a given server reboot.
 | 
			
		||||
// Two methods exist for rebooting a server:
 | 
			
		||||
//
 | 
			
		||||
// HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the machine, or if a VM,
 | 
			
		||||
// terminating it at the hypervisor level.
 | 
			
		||||
// It's done. Caput. Full stop.
 | 
			
		||||
// Then, after a brief while, power is restored or the VM instance restarted.
 | 
			
		||||
//
 | 
			
		||||
// SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures.
 | 
			
		||||
// E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine.
 | 
			
		||||
func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) ActionResult {
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
 | 
			
		||||
	if (how != SoftReboot) && (how != HardReboot) {
 | 
			
		||||
		res.Err = &ErrArgument{
 | 
			
		||||
			Function: "Reboot",
 | 
			
		||||
			Argument: "how",
 | 
			
		||||
			Value:    how,
 | 
			
		||||
		}
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := struct {
 | 
			
		||||
		C map[string]string `json:"reboot"`
 | 
			
		||||
	}{
 | 
			
		||||
		map[string]string{"type": string(how)},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildOptsBuilder is an interface that allows extensions to override the
 | 
			
		||||
// default behaviour of rebuild options
 | 
			
		||||
type RebuildOptsBuilder interface {
 | 
			
		||||
	ToServerRebuildMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildOpts represents the configuration options used in a server rebuild
 | 
			
		||||
// operation
 | 
			
		||||
type RebuildOpts struct {
 | 
			
		||||
	// Required. The ID of the image you want your server to be provisioned on
 | 
			
		||||
	ImageID string
 | 
			
		||||
 | 
			
		||||
	// Name to set the server to
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Required. The server's admin password
 | 
			
		||||
	AdminPass string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 [optional] provides a new IPv4 address for the instance.
 | 
			
		||||
	AccessIPv4 string
 | 
			
		||||
 | 
			
		||||
	// AccessIPv6 [optional] provides a new IPv6 address for the instance.
 | 
			
		||||
	AccessIPv6 string
 | 
			
		||||
 | 
			
		||||
	// Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
 | 
			
		||||
	Metadata map[string]string
 | 
			
		||||
 | 
			
		||||
	// Personality [optional] includes files to inject into the server at launch.
 | 
			
		||||
	// Rebuild will base64-encode file contents for you.
 | 
			
		||||
	Personality Personality
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON
 | 
			
		||||
func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	server := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.AdminPass == "" {
 | 
			
		||||
		err = fmt.Errorf("AdminPass is required")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.ImageID == "" {
 | 
			
		||||
		err = fmt.Errorf("ImageID is required")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return server, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	server["name"] = opts.Name
 | 
			
		||||
	server["adminPass"] = opts.AdminPass
 | 
			
		||||
	server["imageRef"] = opts.ImageID
 | 
			
		||||
 | 
			
		||||
	if opts.AccessIPv4 != "" {
 | 
			
		||||
		server["accessIPv4"] = opts.AccessIPv4
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.AccessIPv6 != "" {
 | 
			
		||||
		server["accessIPv6"] = opts.AccessIPv6
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Metadata != nil {
 | 
			
		||||
		server["metadata"] = opts.Metadata
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.Personality) > 0 {
 | 
			
		||||
		server["personality"] = opts.Personality
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"rebuild": server}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rebuild will reprovision the server according to the configuration options
 | 
			
		||||
// provided in the RebuildOpts struct.
 | 
			
		||||
func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) RebuildResult {
 | 
			
		||||
	var result RebuildResult
 | 
			
		||||
 | 
			
		||||
	if id == "" {
 | 
			
		||||
		result.Err = fmt.Errorf("ID is required")
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToServerRebuildMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		result.Err = err
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, nil)
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResizeOptsBuilder is an interface that allows extensions to override the default structure of
 | 
			
		||||
// a Resize request.
 | 
			
		||||
type ResizeOptsBuilder interface {
 | 
			
		||||
	ToServerResizeMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResizeOpts represents the configuration options used to control a Resize operation.
 | 
			
		||||
type ResizeOpts struct {
 | 
			
		||||
	// FlavorRef is the ID of the flavor you wish your server to become.
 | 
			
		||||
	FlavorRef string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON request body for the
 | 
			
		||||
// Resize request.
 | 
			
		||||
func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) {
 | 
			
		||||
	resize := map[string]interface{}{
 | 
			
		||||
		"flavorRef": opts.FlavorRef,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"resize": resize}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Resize instructs the provider to change the flavor of the server.
 | 
			
		||||
// Note that this implies rebuilding it.
 | 
			
		||||
// Unfortunately, one cannot pass rebuild parameters to the resize function.
 | 
			
		||||
// When the resize completes, the server will be in RESIZE_VERIFY state.
 | 
			
		||||
// While in this state, you can explore the use of the new server's configuration.
 | 
			
		||||
// If you like it, call ConfirmResize() to commit the resize permanently.
 | 
			
		||||
// Otherwise, call RevertResize() to restore the old configuration.
 | 
			
		||||
func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) ActionResult {
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
	reqBody, err := opts.ToServerResizeMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfirmResize confirms a previous resize operation on a server.
 | 
			
		||||
// See Resize() for more details.
 | 
			
		||||
func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult {
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
 | 
			
		||||
	reqBody := map[string]interface{}{"confirmResize": nil}
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{201, 202, 204},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RevertResize cancels a previous resize operation on a server.
 | 
			
		||||
// See Resize() for more details.
 | 
			
		||||
func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult {
 | 
			
		||||
	var res ActionResult
 | 
			
		||||
	reqBody := map[string]interface{}{"revertResize": nil}
 | 
			
		||||
	_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueOptsBuilder is an interface that allows extensions to override the
 | 
			
		||||
// default structure of a Rescue request.
 | 
			
		||||
type RescueOptsBuilder interface {
 | 
			
		||||
	ToServerRescueMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueOpts represents the configuration options used to control a Rescue
 | 
			
		||||
// option.
 | 
			
		||||
type RescueOpts struct {
 | 
			
		||||
	// AdminPass is the desired administrative password for the instance in
 | 
			
		||||
	// RESCUE mode. If it's left blank, the server will generate a password.
 | 
			
		||||
	AdminPass string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerRescueMap formats a RescueOpts as a map that can be used as a JSON
 | 
			
		||||
// request body for the Rescue request.
 | 
			
		||||
func (opts RescueOpts) ToServerRescueMap() (map[string]interface{}, error) {
 | 
			
		||||
	server := make(map[string]interface{})
 | 
			
		||||
	if opts.AdminPass != "" {
 | 
			
		||||
		server["adminPass"] = opts.AdminPass
 | 
			
		||||
	}
 | 
			
		||||
	return map[string]interface{}{"rescue": server}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rescue instructs the provider to place the server into RESCUE mode.
 | 
			
		||||
func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) RescueResult {
 | 
			
		||||
	var result RescueResult
 | 
			
		||||
 | 
			
		||||
	if id == "" {
 | 
			
		||||
		result.Err = fmt.Errorf("ID is required")
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
	reqBody, err := opts.ToServerRescueMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		result.Err = err
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetMetadataOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Reset request.
 | 
			
		||||
type ResetMetadataOptsBuilder interface {
 | 
			
		||||
	ToMetadataResetMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadataOpts is a map that contains key-value pairs.
 | 
			
		||||
type MetadataOpts map[string]string
 | 
			
		||||
 | 
			
		||||
// ToMetadataResetMap assembles a body for a Reset request based on the contents of a MetadataOpts.
 | 
			
		||||
func (opts MetadataOpts) ToMetadataResetMap() (map[string]interface{}, error) {
 | 
			
		||||
	return map[string]interface{}{"metadata": opts}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMetadataUpdateMap assembles a body for an Update request based on the contents of a MetadataOpts.
 | 
			
		||||
func (opts MetadataOpts) ToMetadataUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return map[string]interface{}{"metadata": opts}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetMetadata will create multiple new key-value pairs for the given server ID.
 | 
			
		||||
// Note: Using this operation will erase any already-existing metadata and create
 | 
			
		||||
// the new metadata provided. To keep any already-existing metadata, use the
 | 
			
		||||
// UpdateMetadatas or UpdateMetadata function.
 | 
			
		||||
func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) ResetMetadataResult {
 | 
			
		||||
	var res ResetMetadataResult
 | 
			
		||||
	metadata, err := opts.ToMetadataResetMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
	_, res.Err = client.Put(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Metadata requests all the metadata for the given server ID.
 | 
			
		||||
func Metadata(client *gophercloud.ServiceClient, id string) GetMetadataResult {
 | 
			
		||||
	var res GetMetadataResult
 | 
			
		||||
	_, res.Err = client.Get(metadataURL(client, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Create request.
 | 
			
		||||
type UpdateMetadataOptsBuilder interface {
 | 
			
		||||
	ToMetadataUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID.
 | 
			
		||||
// This operation does not affect already-existing metadata that is not specified
 | 
			
		||||
// by opts.
 | 
			
		||||
func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult {
 | 
			
		||||
	var res UpdateMetadataResult
 | 
			
		||||
	metadata, err := opts.ToMetadataUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
	_, res.Err = client.Post(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadatumOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Create request.
 | 
			
		||||
type MetadatumOptsBuilder interface {
 | 
			
		||||
	ToMetadatumCreateMap() (map[string]interface{}, string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadatumOpts is a map of length one that contains a key-value pair.
 | 
			
		||||
type MetadatumOpts map[string]string
 | 
			
		||||
 | 
			
		||||
// ToMetadatumCreateMap assembles a body for a Create request based on the contents of a MetadataumOpts.
 | 
			
		||||
func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) {
 | 
			
		||||
	if len(opts) != 1 {
 | 
			
		||||
		return nil, "", errors.New("CreateMetadatum operation must have 1 and only 1 key-value pair.")
 | 
			
		||||
	}
 | 
			
		||||
	metadatum := map[string]interface{}{"meta": opts}
 | 
			
		||||
	var key string
 | 
			
		||||
	for k := range metadatum["meta"].(MetadatumOpts) {
 | 
			
		||||
		key = k
 | 
			
		||||
	}
 | 
			
		||||
	return metadatum, key, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateMetadatum will create or update the key-value pair with the given key for the given server ID.
 | 
			
		||||
func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts MetadatumOptsBuilder) CreateMetadatumResult {
 | 
			
		||||
	var res CreateMetadatumResult
 | 
			
		||||
	metadatum, key, err := opts.ToMetadatumCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = client.Put(metadatumURL(client, id, key), metadatum, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Metadatum requests the key-value pair with the given key for the given server ID.
 | 
			
		||||
func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumResult {
 | 
			
		||||
	var res GetMetadatumResult
 | 
			
		||||
	_, res.Err = client.Request("GET", metadatumURL(client, id, key), gophercloud.RequestOpts{
 | 
			
		||||
		JSONResponse: &res.Body,
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteMetadatum will delete the key-value pair with the given key for the given server ID.
 | 
			
		||||
func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) DeleteMetadatumResult {
 | 
			
		||||
	var res DeleteMetadatumResult
 | 
			
		||||
	_, res.Err = client.Delete(metadatumURL(client, id, key), nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListAddresses makes a request against the API to list the servers IP addresses.
 | 
			
		||||
func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager {
 | 
			
		||||
	createPageFn := func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return AddressPage{pagination.SinglePageBase(r)}
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, listAddressesURL(client, id), createPageFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListAddressesByNetwork makes a request against the API to list the servers IP addresses
 | 
			
		||||
// for the given network.
 | 
			
		||||
func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager {
 | 
			
		||||
	createPageFn := func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return NetworkAddressPage{pagination.SinglePageBase(r)}
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), createPageFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CreateImageOpts struct {
 | 
			
		||||
	// Name [required] of the image/snapshot
 | 
			
		||||
	Name string
 | 
			
		||||
	// Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the created image.
 | 
			
		||||
	Metadata map[string]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CreateImageOptsBuilder interface {
 | 
			
		||||
	ToServerCreateImageMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerCreateImageMap formats a CreateImageOpts structure into a request body.
 | 
			
		||||
func (opts CreateImageOpts) ToServerCreateImageMap() (map[string]interface{}, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	img := make(map[string]interface{})
 | 
			
		||||
	if opts.Name == "" {
 | 
			
		||||
		return nil, fmt.Errorf("Cannot create a server image without a name")
 | 
			
		||||
	}
 | 
			
		||||
	img["name"] = opts.Name
 | 
			
		||||
	if opts.Metadata != nil {
 | 
			
		||||
		img["metadata"] = opts.Metadata
 | 
			
		||||
	}
 | 
			
		||||
	createImage := make(map[string]interface{})
 | 
			
		||||
	createImage["createImage"] = img
 | 
			
		||||
	return createImage, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateImage makes a request against the nova API to schedule an image to be created of the server
 | 
			
		||||
func CreateImage(client *gophercloud.ServiceClient, serverId string, opts CreateImageOptsBuilder) CreateImageResult {
 | 
			
		||||
	var res CreateImageResult
 | 
			
		||||
	reqBody, err := opts.ToServerCreateImageMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
	response, err := client.Post(actionURL(client, serverId), reqBody, nil, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{202},
 | 
			
		||||
	})
 | 
			
		||||
	res.Err = err
 | 
			
		||||
	res.Header = response.Header
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IDFromName is a convienience function that returns a server's ID given its name.
 | 
			
		||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
 | 
			
		||||
	serverCount := 0
 | 
			
		||||
	serverID := ""
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		return "", fmt.Errorf("A server name must be provided.")
 | 
			
		||||
	}
 | 
			
		||||
	pager := List(client, nil)
 | 
			
		||||
	pager.EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		serverList, err := ExtractServers(page)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, s := range serverList {
 | 
			
		||||
			if s.Name == name {
 | 
			
		||||
				serverCount++
 | 
			
		||||
				serverID = s.ID
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true, nil
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	switch serverCount {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return "", fmt.Errorf("Unable to find server: %s", name)
 | 
			
		||||
	case 1:
 | 
			
		||||
		return serverID, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return "", fmt.Errorf("Found %d servers matching %s", serverCount, name)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPassword makes a request against the nova API to get the encrypted administrative password.
 | 
			
		||||
func GetPassword(client *gophercloud.ServiceClient, serverId string) GetPasswordResult {
 | 
			
		||||
	var res GetPasswordResult
 | 
			
		||||
	_, res.Err = client.Request("GET", passwordURL(client, serverId), gophercloud.RequestOpts{
 | 
			
		||||
		JSONResponse: &res.Body,
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										415
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,415 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"path"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type serverResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any serverResult as a Server, if possible.
 | 
			
		||||
func (r serverResult) Extract() (*Server, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Server Server `mapstructure:"server"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := &mapstructure.DecoderConfig{
 | 
			
		||||
		DecodeHook: toMapFromString,
 | 
			
		||||
		Result:     &response,
 | 
			
		||||
	}
 | 
			
		||||
	decoder, err := mapstructure.NewDecoder(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = decoder.Decode(r.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &response.Server, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult temporarily contains the response from a Create call.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult temporarily contains the response from a Get call.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult temporarily contains the response from an Update call.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult temporarily contains the response from a Delete call.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildResult temporarily contains the response from a Rebuild call.
 | 
			
		||||
type RebuildResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ActionResult represents the result of server action operations, like reboot
 | 
			
		||||
type ActionResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueResult represents the result of a server rescue operation
 | 
			
		||||
type RescueResult struct {
 | 
			
		||||
	ActionResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateImageResult represents the result of an image creation operation
 | 
			
		||||
type CreateImageResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPasswordResult represent the result of a get os-server-password operation.
 | 
			
		||||
type GetPasswordResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractPassword gets the encrypted password.
 | 
			
		||||
// If privateKey != nil the password is decrypted with the private key.
 | 
			
		||||
// If privateKey == nil the encrypted password is returned and can be decrypted with:
 | 
			
		||||
//   echo '<pwd>' | base64 -D | openssl rsautl -decrypt -inkey <private_key>
 | 
			
		||||
func (r GetPasswordResult) ExtractPassword(privateKey *rsa.PrivateKey) (string, error) {
 | 
			
		||||
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return "", r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Password string `mapstructure:"password"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &response)
 | 
			
		||||
	if err == nil && privateKey != nil && response.Password != "" {
 | 
			
		||||
		return decryptPassword(response.Password, privateKey)
 | 
			
		||||
	}
 | 
			
		||||
	return response.Password, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func decryptPassword(encryptedPassword string, privateKey *rsa.PrivateKey) (string, error) {
 | 
			
		||||
	b64EncryptedPassword := make([]byte, base64.StdEncoding.DecodedLen(len(encryptedPassword)))
 | 
			
		||||
 | 
			
		||||
	n, err := base64.StdEncoding.Decode(b64EncryptedPassword, []byte(encryptedPassword))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to base64 decode encrypted password: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	password, err := rsa.DecryptPKCS1v15(nil, privateKey, b64EncryptedPassword[0:n])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to decrypt password: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(password), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractImageID gets the ID of the newly created server image from the header
 | 
			
		||||
func (res CreateImageResult) ExtractImageID() (string, error) {
 | 
			
		||||
	if res.Err != nil {
 | 
			
		||||
		return "", res.Err
 | 
			
		||||
	}
 | 
			
		||||
	// Get the image id from the header
 | 
			
		||||
	u, err := url.ParseRequestURI(res.Header.Get("Location"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to parse the image id: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	imageId := path.Base(u.Path)
 | 
			
		||||
	if imageId == "." || imageId == "/" {
 | 
			
		||||
		return "", fmt.Errorf("Failed to parse the ID of newly created image: %s", u)
 | 
			
		||||
	}
 | 
			
		||||
	return imageId, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any RescueResult as an AdminPass, if possible.
 | 
			
		||||
func (r RescueResult) Extract() (string, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return "", r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		AdminPass string `mapstructure:"adminPass"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &response)
 | 
			
		||||
	return response.AdminPass, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
 | 
			
		||||
type Server struct {
 | 
			
		||||
	// ID uniquely identifies this server amongst all other servers, including those not accessible to the current tenant.
 | 
			
		||||
	ID string
 | 
			
		||||
 | 
			
		||||
	// TenantID identifies the tenant owning this server resource.
 | 
			
		||||
	TenantID string `mapstructure:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// UserID uniquely identifies the user account owning the tenant.
 | 
			
		||||
	UserID string `mapstructure:"user_id"`
 | 
			
		||||
 | 
			
		||||
	// Name contains the human-readable name for the server.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created.
 | 
			
		||||
	Updated string
 | 
			
		||||
	Created string
 | 
			
		||||
 | 
			
		||||
	HostID string
 | 
			
		||||
 | 
			
		||||
	// Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE.
 | 
			
		||||
	Status string
 | 
			
		||||
 | 
			
		||||
	// Progress ranges from 0..100.
 | 
			
		||||
	// A request made against the server completes only once Progress reaches 100.
 | 
			
		||||
	Progress int
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration.
 | 
			
		||||
	AccessIPv4, AccessIPv6 string
 | 
			
		||||
 | 
			
		||||
	// Image refers to a JSON object, which itself indicates the OS image used to deploy the server.
 | 
			
		||||
	Image map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	// Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server.
 | 
			
		||||
	Flavor map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	// Addresses includes a list of all IP addresses assigned to the server, keyed by pool.
 | 
			
		||||
	Addresses map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	// Metadata includes a list of all user-specified key-value pairs attached to the server.
 | 
			
		||||
	Metadata map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	// Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
 | 
			
		||||
	Links []interface{}
 | 
			
		||||
 | 
			
		||||
	// KeyName indicates which public key was injected into the server on launch.
 | 
			
		||||
	KeyName string `json:"key_name" mapstructure:"key_name"`
 | 
			
		||||
 | 
			
		||||
	// AdminPass will generally be empty ("").  However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place.
 | 
			
		||||
	// Note that this is the ONLY time this field will be valid.
 | 
			
		||||
	AdminPass string `json:"adminPass" mapstructure:"adminPass"`
 | 
			
		||||
 | 
			
		||||
	// SecurityGroups includes the security groups that this instance has applied to it
 | 
			
		||||
	SecurityGroups []map[string]interface{} `json:"security_groups" mapstructure:"security_groups"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ServerPage abstracts the raw results of making a List() request against the API.
 | 
			
		||||
// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the
 | 
			
		||||
// data provided through the ExtractServers call.
 | 
			
		||||
type ServerPage struct {
 | 
			
		||||
	pagination.LinkedPageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if a page contains no Server results.
 | 
			
		||||
func (page ServerPage) IsEmpty() (bool, error) {
 | 
			
		||||
	servers, err := ExtractServers(page)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	return len(servers) == 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
 | 
			
		||||
func (page ServerPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"servers_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(page.Body, &r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
 | 
			
		||||
func ExtractServers(page pagination.Page) ([]Server, error) {
 | 
			
		||||
	casted := page.(ServerPage).Body
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Servers []Server `mapstructure:"servers"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := &mapstructure.DecoderConfig{
 | 
			
		||||
		DecodeHook: toMapFromString,
 | 
			
		||||
		Result:     &response,
 | 
			
		||||
	}
 | 
			
		||||
	decoder, err := mapstructure.NewDecoder(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = decoder.Decode(casted)
 | 
			
		||||
 | 
			
		||||
	return response.Servers, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadataResult contains the result of a call for (potentially) multiple key-value pairs.
 | 
			
		||||
type MetadataResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMetadataResult temporarily contains the response from a metadata Get call.
 | 
			
		||||
type GetMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetMetadataResult temporarily contains the response from a metadata Reset call.
 | 
			
		||||
type ResetMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateMetadataResult temporarily contains the response from a metadata Update call.
 | 
			
		||||
type UpdateMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadatumResult contains the result of a call for individual a single key-value pair.
 | 
			
		||||
type MetadatumResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMetadatumResult temporarily contains the response from a metadatum Get call.
 | 
			
		||||
type GetMetadatumResult struct {
 | 
			
		||||
	MetadatumResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateMetadatumResult temporarily contains the response from a metadatum Create call.
 | 
			
		||||
type CreateMetadatumResult struct {
 | 
			
		||||
	MetadatumResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteMetadatumResult temporarily contains the response from a metadatum Delete call.
 | 
			
		||||
type DeleteMetadatumResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any MetadataResult as a Metadata, if possible.
 | 
			
		||||
func (r MetadataResult) Extract() (map[string]string, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Metadata map[string]string `mapstructure:"metadata"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &response)
 | 
			
		||||
	return response.Metadata, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any MetadatumResult as a Metadatum, if possible.
 | 
			
		||||
func (r MetadatumResult) Extract() (map[string]string, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Metadatum map[string]string `mapstructure:"meta"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &response)
 | 
			
		||||
	return response.Metadatum, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toMapFromString(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) {
 | 
			
		||||
	if (from == reflect.String) && (to == reflect.Map) {
 | 
			
		||||
		return map[string]interface{}{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Address represents an IP address.
 | 
			
		||||
type Address struct {
 | 
			
		||||
	Version int    `mapstructure:"version"`
 | 
			
		||||
	Address string `mapstructure:"addr"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddressPage abstracts the raw results of making a ListAddresses() request against the API.
 | 
			
		||||
// As OpenStack extensions may freely alter the response bodies of structures returned
 | 
			
		||||
// to the client, you may only safely access the data provided through the ExtractAddresses call.
 | 
			
		||||
type AddressPage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if an AddressPage contains no networks.
 | 
			
		||||
func (r AddressPage) IsEmpty() (bool, error) {
 | 
			
		||||
	addresses, err := ExtractAddresses(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	return len(addresses) == 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractAddresses interprets the results of a single page from a ListAddresses() call,
 | 
			
		||||
// producing a map of addresses.
 | 
			
		||||
func ExtractAddresses(page pagination.Page) (map[string][]Address, error) {
 | 
			
		||||
	casted := page.(AddressPage).Body
 | 
			
		||||
 | 
			
		||||
	var response struct {
 | 
			
		||||
		Addresses map[string][]Address `mapstructure:"addresses"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(casted, &response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response.Addresses, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NetworkAddressPage abstracts the raw results of making a ListAddressesByNetwork() request against the API.
 | 
			
		||||
// As OpenStack extensions may freely alter the response bodies of structures returned
 | 
			
		||||
// to the client, you may only safely access the data provided through the ExtractAddresses call.
 | 
			
		||||
type NetworkAddressPage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if a NetworkAddressPage contains no addresses.
 | 
			
		||||
func (r NetworkAddressPage) IsEmpty() (bool, error) {
 | 
			
		||||
	addresses, err := ExtractNetworkAddresses(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	return len(addresses) == 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call,
 | 
			
		||||
// producing a slice of addresses.
 | 
			
		||||
func ExtractNetworkAddresses(page pagination.Page) ([]Address, error) {
 | 
			
		||||
	casted := page.(NetworkAddressPage).Body
 | 
			
		||||
 | 
			
		||||
	var response map[string][]Address
 | 
			
		||||
	err := mapstructure.Decode(casted, &response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var key string
 | 
			
		||||
	for k := range response {
 | 
			
		||||
		key = k
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response[key], err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
 | 
			
		||||
func createURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("servers")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return createURL(client)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listDetailURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("servers", "detail")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(client, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func updateURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(client, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func actionURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "action")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func metadatumURL(client *gophercloud.ServiceClient, id, key string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "metadata", key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func metadataURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "metadata")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listAddressesURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "ips")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listAddressesByNetworkURL(client *gophercloud.ServiceClient, id, network string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "ips", network)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func passwordURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "os-server-password")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
 | 
			
		||||
// WaitForStatus will continually poll a server until it successfully transitions to a specified
 | 
			
		||||
// status. It will do this for at most the number of seconds specified.
 | 
			
		||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
 | 
			
		||||
	return gophercloud.WaitFor(secs, func() (bool, error) {
 | 
			
		||||
		current, err := Get(c, id).Extract()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if current.Status == status {
 | 
			
		||||
			return true, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false, nil
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user