forked from docker/machine
/
results.go
237 lines (185 loc) · 6.8 KB
/
results.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package servers
import (
"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"`
}
err := mapstructure.Decode(r.Body, &response)
return &response.Server, err
}
// 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
}
// 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"`
}
// 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"`
}
err := mapstructure.Decode(casted, &response)
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
}