forked from rackspace/gophercloud
/
results.go
191 lines (151 loc) · 5.07 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
package instances
import (
"fmt"
"reflect"
"time"
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/db/v1/datastores"
"github.com/rackspace/gophercloud/openstack/db/v1/flavors"
os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
"github.com/rackspace/gophercloud/pagination"
)
// Instance represents a remote MySQL instance.
type Instance struct {
// Indicates the datetime that the instance was created
Created time.Time `mapstructure:"-"`
// Indicates the most recent datetime that the instance was updated.
Updated time.Time `mapstructure:"-"`
// Indicates how the instance stores data.
Datastore datastores.DatastorePartial
// Indicates the hardware flavor the instance uses.
Flavor flavors.Flavor
// A DNS-resolvable hostname associated with the database instance (rather
// than an IPv4 address). Since the hostname always resolves to the correct
// IP address of the database instance, this relieves the user from the task
// of maintaining the mapping. Note that although the IP address may likely
// change on resizing, migrating, and so forth, the hostname always resolves
// to the correct database instance.
Hostname string
// Indicates the unique identifier for the instance resource.
ID string
// Exposes various links that reference the instance resource.
Links []gophercloud.Link
// The human-readable name of the instance.
Name string
// The build status of the instance.
Status string
// Information about the attached volume of the instance.
Volume os.Volume
// IP indicates the various IP addresses which allow access.
IP []string
// Indicates whether this instance is a replica of another source instance.
ReplicaOf *Instance `mapstructure:"replica_of" json:"replica_of"`
// Indicates whether this instance is the source of other replica instances.
Replicas []Instance
}
func commonExtract(err error, body interface{}) (*Instance, error) {
if err != nil {
return nil, err
}
var response struct {
Instance Instance `mapstructure:"instance"`
}
err = mapstructure.Decode(body, &response)
val := body.(map[string]interface{})["instance"].(map[string]interface{})
if t, ok := val["created"].(string); ok && t != "" {
creationTime, err := time.Parse(time.RFC3339, t)
if err != nil {
return &response.Instance, err
}
response.Instance.Created = creationTime
}
if t, ok := val["updated"].(string); ok && t != "" {
updatedTime, err := time.Parse(time.RFC3339, t)
if err != nil {
return &response.Instance, err
}
response.Instance.Updated = updatedTime
}
return &response.Instance, err
}
// CreateResult represents the result of a Create operation.
type CreateResult struct {
os.CreateResult
}
// Extract will retrieve an instance from a create result.
func (r CreateResult) Extract() (*Instance, error) {
return commonExtract(r.Err, r.Body)
}
// GetResult represents the result of a Get operation.
type GetResult struct {
os.GetResult
}
// Extract will extract an Instance from a GetResult.
func (r GetResult) Extract() (*Instance, error) {
return commonExtract(r.Err, r.Body)
}
// ConfigResult represents the result of getting default configuration for an
// instance.
type ConfigResult struct {
gophercloud.Result
}
// DetachResult represents the result of detaching a replica from its source.
type DetachResult struct {
gophercloud.ErrResult
}
// Extract will extract the configuration information (in the form of a map)
// about a particular instance.
func (r ConfigResult) Extract() (map[string]string, error) {
if r.Err != nil {
return nil, r.Err
}
var response struct {
Instance struct {
Config map[string]string `mapstructure:"configuration"`
} `mapstructure:"instance"`
}
err := mapstructure.Decode(r.Body, &response)
return response.Instance.Config, err
}
// UpdateResult represents the result of an Update operation.
type UpdateResult struct {
gophercloud.ErrResult
}
// ExtractInstances retrieves a slice of instances from a paginated collection.
func ExtractInstances(page pagination.Page) ([]Instance, error) {
casted := page.(os.InstancePage).Body
var resp struct {
Instances []Instance `mapstructure:"instances"`
}
if err := mapstructure.Decode(casted, &resp); err != nil {
return nil, err
}
var vals []interface{}
switch casted.(type) {
case map[string]interface{}:
vals = casted.(map[string]interface{})["instances"].([]interface{})
case map[string][]interface{}:
vals = casted.(map[string][]interface{})["instances"]
default:
return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
}
for i, v := range vals {
val := v.(map[string]interface{})
if t, ok := val["created"].(string); ok && t != "" {
creationTime, err := time.Parse(time.RFC3339, t)
if err != nil {
return resp.Instances, err
}
resp.Instances[i].Created = creationTime
}
if t, ok := val["updated"].(string); ok && t != "" {
updatedTime, err := time.Parse(time.RFC3339, t)
if err != nil {
return resp.Instances, err
}
resp.Instances[i].Updated = updatedTime
}
}
return resp.Instances, nil
}