blob: cdcc9c716f23ba03c5723c0a9ddbd13a658e221e [file] [log] [blame]
Jamie Hannaford2a4beaa2015-02-09 17:27:18 +01001package instances
2
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +01003import (
Jamie Hannaford87704ba2016-01-14 11:49:56 +01004 "fmt"
5 "reflect"
Jamie Hannaforde65ad952015-11-16 14:05:11 +01006 "time"
7
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +01008 "github.com/mitchellh/mapstructure"
9 "github.com/rackspace/gophercloud"
Jamie Hannaford52dbcee2015-10-06 16:09:56 +020010 "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
Jamie Hannaford11108402015-02-23 10:31:41 +010011 "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
Jamie Hannaford9fdda582015-02-10 12:15:43 +010012 os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +010013 "github.com/rackspace/gophercloud/pagination"
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +010014)
15
Jamie Hannaford27957b22015-02-12 12:50:55 +010016// Instance represents a remote MySQL instance.
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +010017type Instance struct {
Jamie Hannaford27957b22015-02-12 12:50:55 +010018 // Indicates the datetime that the instance was created
Jamie Hannaforde65ad952015-11-16 14:05:11 +010019 Created time.Time `mapstructure:"-"`
Jamie Hannaford27957b22015-02-12 12:50:55 +010020
21 // Indicates the most recent datetime that the instance was updated.
Jamie Hannaforde65ad952015-11-16 14:05:11 +010022 Updated time.Time `mapstructure:"-"`
Jamie Hannaford27957b22015-02-12 12:50:55 +010023
24 // Indicates how the instance stores data.
Jamie Hannaforda50d1352015-02-18 11:38:38 +010025 Datastore datastores.DatastorePartial
Jamie Hannaford27957b22015-02-12 12:50:55 +010026
27 // Indicates the hardware flavor the instance uses.
Jamie Hannaford11108402015-02-23 10:31:41 +010028 Flavor flavors.Flavor
Jamie Hannaford27957b22015-02-12 12:50:55 +010029
30 // A DNS-resolvable hostname associated with the database instance (rather
31 // than an IPv4 address). Since the hostname always resolves to the correct
32 // IP address of the database instance, this relieves the user from the task
33 // of maintaining the mapping. Note that although the IP address may likely
34 // change on resizing, migrating, and so forth, the hostname always resolves
35 // to the correct database instance.
36 Hostname string
37
38 // Indicates the unique identifier for the instance resource.
39 ID string
40
41 // Exposes various links that reference the instance resource.
42 Links []gophercloud.Link
43
44 // The human-readable name of the instance.
45 Name string
46
47 // The build status of the instance.
48 Status string
49
50 // Information about the attached volume of the instance.
51 Volume os.Volume
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +010052
Jamie Hannafordb0d267b2015-02-19 11:59:53 +010053 // IP indicates the various IP addresses which allow access.
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +010054 IP []string
55
Jamie Hannafordb0d267b2015-02-19 11:59:53 +010056 // Indicates whether this instance is a replica of another source instance.
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +010057 ReplicaOf *Instance `mapstructure:"replica_of" json:"replica_of"`
58
Jamie Hannafordb0d267b2015-02-19 11:59:53 +010059 // Indicates whether this instance is the source of other replica instances.
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +010060 Replicas []Instance
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +010061}
Jamie Hannaford2a4beaa2015-02-09 17:27:18 +010062
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +010063func commonExtract(err error, body interface{}) (*Instance, error) {
64 if err != nil {
65 return nil, err
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +010066 }
67
68 var response struct {
69 Instance Instance `mapstructure:"instance"`
70 }
71
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +010072 err = mapstructure.Decode(body, &response)
Jamie Hannaforde65ad952015-11-16 14:05:11 +010073
74 val := body.(map[string]interface{})["instance"].(map[string]interface{})
75
76 if t, ok := val["created"].(string); ok && t != "" {
77 creationTime, err := time.Parse(time.RFC3339, t)
78 if err != nil {
79 return &response.Instance, err
80 }
81 response.Instance.Created = creationTime
82 }
83
84 if t, ok := val["updated"].(string); ok && t != "" {
85 updatedTime, err := time.Parse(time.RFC3339, t)
86 if err != nil {
87 return &response.Instance, err
88 }
89 response.Instance.Updated = updatedTime
90 }
91
Jamie Hannaford3dbfb2d2015-02-10 11:06:47 +010092 return &response.Instance, err
93}
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +010094
95// CreateResult represents the result of a Create operation.
96type CreateResult struct {
97 os.CreateResult
98}
99
Jamie Hannafordb0d267b2015-02-19 11:59:53 +0100100// Extract will retrieve an instance from a create result.
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +0100101func (r CreateResult) Extract() (*Instance, error) {
102 return commonExtract(r.Err, r.Body)
103}
104
Jamie Hannaford27957b22015-02-12 12:50:55 +0100105// GetResult represents the result of a Get operation.
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +0100106type GetResult struct {
107 os.GetResult
108}
109
Jamie Hannaford27957b22015-02-12 12:50:55 +0100110// Extract will extract an Instance from a GetResult.
Jamie Hannaford39d4ffb2015-02-10 13:19:44 +0100111func (r GetResult) Extract() (*Instance, error) {
112 return commonExtract(r.Err, r.Body)
113}
Jamie Hannaford936a5472015-02-10 14:38:28 +0100114
Jamie Hannafordb0d267b2015-02-19 11:59:53 +0100115// ConfigResult represents the result of getting default configuration for an
116// instance.
Jamie Hannaford936a5472015-02-10 14:38:28 +0100117type ConfigResult struct {
118 gophercloud.Result
119}
120
Jamie Hannafordb0d267b2015-02-19 11:59:53 +0100121// DetachResult represents the result of detaching a replica from its source.
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +0100122type DetachResult struct {
123 gophercloud.ErrResult
124}
125
Jamie Hannaford27957b22015-02-12 12:50:55 +0100126// Extract will extract the configuration information (in the form of a map)
127// about a particular instance.
Jamie Hannaford936a5472015-02-10 14:38:28 +0100128func (r ConfigResult) Extract() (map[string]string, error) {
Jamie Hannafordf77fc102015-02-10 14:56:02 +0100129 if r.Err != nil {
130 return nil, r.Err
Jamie Hannaford936a5472015-02-10 14:38:28 +0100131 }
132
133 var response struct {
134 Instance struct {
135 Config map[string]string `mapstructure:"configuration"`
136 } `mapstructure:"instance"`
137 }
138
Jamie Hannafordf77fc102015-02-10 14:56:02 +0100139 err := mapstructure.Decode(r.Body, &response)
140 return response.Instance.Config, err
141}
142
Jamie Hannaford27957b22015-02-12 12:50:55 +0100143// UpdateResult represents the result of an Update operation.
Jamie Hannafordf77fc102015-02-10 14:56:02 +0100144type UpdateResult struct {
145 gophercloud.ErrResult
Jamie Hannaford936a5472015-02-10 14:38:28 +0100146}
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +0100147
Jamie Hannafordb0d267b2015-02-19 11:59:53 +0100148// ExtractInstances retrieves a slice of instances from a paginated collection.
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +0100149func ExtractInstances(page pagination.Page) ([]Instance, error) {
150 casted := page.(os.InstancePage).Body
151
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100152 var resp struct {
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +0100153 Instances []Instance `mapstructure:"instances"`
154 }
155
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100156 if err := mapstructure.Decode(casted, &resp); err != nil {
157 return nil, err
158 }
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100159
160 var vals []interface{}
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100161 switch casted.(type) {
162 case map[string]interface{}:
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100163 vals = casted.(map[string]interface{})["instances"].([]interface{})
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100164 case map[string][]interface{}:
165 vals = casted.(map[string][]interface{})["instances"]
166 default:
167 return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100168 }
169
170 for i, v := range vals {
171 val := v.(map[string]interface{})
172
173 if t, ok := val["created"].(string); ok && t != "" {
174 creationTime, err := time.Parse(time.RFC3339, t)
175 if err != nil {
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100176 return resp.Instances, err
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100177 }
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100178 resp.Instances[i].Created = creationTime
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100179 }
180
181 if t, ok := val["updated"].(string); ok && t != "" {
182 updatedTime, err := time.Parse(time.RFC3339, t)
183 if err != nil {
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100184 return resp.Instances, err
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100185 }
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100186 resp.Instances[i].Updated = updatedTime
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100187 }
188 }
189
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100190 return resp.Instances, nil
Jamie Hannaford4ec6afe2015-02-16 16:52:49 +0100191}