blob: 95aed166b59c32ec7f2bb0cf6988dab9120052fa [file] [log] [blame]
Jamie Hannaford9fdda582015-02-10 12:15:43 +01001package instances
2
3import (
Jamie Hannaford87704ba2016-01-14 11:49:56 +01004 "fmt"
5 "reflect"
Jamie Hannaforde65ad952015-11-16 14:05:11 +01006 "time"
7
Jamie Hannaford9fdda582015-02-10 12:15:43 +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 Hannaford9793d942015-02-18 15:13:20 +010011 "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010012 "github.com/rackspace/gophercloud/openstack/db/v1/users"
Jamie Hannaford90684242015-02-10 12:46:07 +010013 "github.com/rackspace/gophercloud/pagination"
Jamie Hannaford9fdda582015-02-10 12:15:43 +010014)
15
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010016// Volume represents information about an attached volume for a database instance.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010017type Volume struct {
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010018 // The size in GB of the volume
Jamie Hannaford9fdda582015-02-10 12:15:43 +010019 Size int
Jamie Hannaford76e177b2015-02-16 16:53:00 +010020
21 Used float64
Jamie Hannaford9fdda582015-02-10 12:15:43 +010022}
23
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010024// Instance represents a remote MySQL instance.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010025type Instance struct {
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010026 // Indicates the datetime that the instance was created
Jamie Hannaforde65ad952015-11-16 14:05:11 +010027 Created time.Time `mapstructure:"-"`
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010028
29 // Indicates the most recent datetime that the instance was updated.
Jamie Hannaforde65ad952015-11-16 14:05:11 +010030 Updated time.Time `mapstructure:"-"`
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010031
32 // Indicates the hardware flavor the instance uses.
Jamie Hannaford9793d942015-02-18 15:13:20 +010033 Flavor flavors.Flavor
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010034
35 // A DNS-resolvable hostname associated with the database instance (rather
36 // than an IPv4 address). Since the hostname always resolves to the correct
37 // IP address of the database instance, this relieves the user from the task
38 // of maintaining the mapping. Note that although the IP address may likely
39 // change on resizing, migrating, and so forth, the hostname always resolves
40 // to the correct database instance.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010041 Hostname string
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010042
43 // Indicates the unique identifier for the instance resource.
44 ID string
45
46 // Exposes various links that reference the instance resource.
47 Links []gophercloud.Link
48
49 // The human-readable name of the instance.
50 Name string
51
52 // The build status of the instance.
53 Status string
54
55 // Information about the attached volume of the instance.
56 Volume Volume
Jamie Hannaford99eced52015-03-02 15:24:22 +010057
58 // Indicates how the instance stores data.
59 Datastore datastores.DatastorePartial
Jamie Hannaford9fdda582015-02-10 12:15:43 +010060}
61
Jamie Hannaford821015f2015-02-10 12:58:36 +010062type commonResult struct {
Jamie Hannaford9fdda582015-02-10 12:15:43 +010063 gophercloud.Result
64}
65
Jamie Hannaford821015f2015-02-10 12:58:36 +010066// CreateResult represents the result of a Create operation.
67type CreateResult struct {
68 commonResult
69}
70
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010071// GetResult represents the result of a Get operation.
Jamie Hannaford821015f2015-02-10 12:58:36 +010072type GetResult struct {
73 commonResult
74}
75
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010076// DeleteResult represents the result of a Delete operation.
Jamie Hannaford5b16b632015-02-10 13:36:23 +010077type DeleteResult struct {
78 gophercloud.ErrResult
79}
80
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010081// Extract will extract an Instance from various result structs.
Jamie Hannaford821015f2015-02-10 12:58:36 +010082func (r commonResult) Extract() (*Instance, error) {
Jamie Hannaford9fdda582015-02-10 12:15:43 +010083 if r.Err != nil {
84 return nil, r.Err
85 }
86
87 var response struct {
88 Instance Instance `mapstructure:"instance"`
89 }
90
91 err := mapstructure.Decode(r.Body, &response)
Jamie Hannaforde65ad952015-11-16 14:05:11 +010092 val := r.Body.(map[string]interface{})["instance"].(map[string]interface{})
93
94 if t, ok := val["created"].(string); ok && t != "" {
95 creationTime, err := time.Parse(time.RFC3339, t)
96 if err != nil {
97 return &response.Instance, err
98 }
99 response.Instance.Created = creationTime
100 }
101
102 if t, ok := val["updated"].(string); ok && t != "" {
103 updatedTime, err := time.Parse(time.RFC3339, t)
104 if err != nil {
105 return &response.Instance, err
106 }
107 response.Instance.Updated = updatedTime
108 }
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100109
110 return &response.Instance, err
111}
Jamie Hannaford90684242015-02-10 12:46:07 +0100112
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100113// InstancePage represents a single page of a paginated instance collection.
Jamie Hannaford90684242015-02-10 12:46:07 +0100114type InstancePage struct {
115 pagination.LinkedPageBase
116}
117
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100118// IsEmpty checks to see whether the collection is empty.
Jamie Hannaford90684242015-02-10 12:46:07 +0100119func (page InstancePage) IsEmpty() (bool, error) {
120 instances, err := ExtractInstances(page)
121 if err != nil {
122 return true, err
123 }
124 return len(instances) == 0, nil
125}
126
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100127// NextPageURL will retrieve the next page URL.
Jamie Hannaford90684242015-02-10 12:46:07 +0100128func (page InstancePage) NextPageURL() (string, error) {
129 type resp struct {
130 Links []gophercloud.Link `mapstructure:"instances_links"`
131 }
132
133 var r resp
134 err := mapstructure.Decode(page.Body, &r)
135 if err != nil {
136 return "", err
137 }
138
139 return gophercloud.ExtractNextURL(r.Links)
140}
141
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100142// ExtractInstances will convert a generic pagination struct into a more
143// relevant slice of Instance structs.
Jamie Hannaford90684242015-02-10 12:46:07 +0100144func ExtractInstances(page pagination.Page) ([]Instance, error) {
145 casted := page.(InstancePage).Body
146
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100147 var resp struct {
Jamie Hannaford90684242015-02-10 12:46:07 +0100148 Instances []Instance `mapstructure:"instances"`
149 }
150
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100151 if err := mapstructure.Decode(casted, &resp); err != nil {
152 return nil, err
153 }
Jamie Hannaford90684242015-02-10 12:46:07 +0100154
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100155 var vals []interface{}
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100156 switch casted.(type) {
157 case map[string]interface{}:
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100158 vals = casted.(map[string]interface{})["instances"].([]interface{})
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100159 case map[string][]interface{}:
160 vals = casted.(map[string][]interface{})["instances"]
161 default:
162 return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100163 }
164
165 for i, v := range vals {
166 val := v.(map[string]interface{})
167
168 if t, ok := val["created"].(string); ok && t != "" {
169 creationTime, err := time.Parse(time.RFC3339, t)
170 if err != nil {
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100171 return resp.Instances, err
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100172 }
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100173 resp.Instances[i].Created = creationTime
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100174 }
175
176 if t, ok := val["updated"].(string); ok && t != "" {
177 updatedTime, err := time.Parse(time.RFC3339, t)
178 if err != nil {
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100179 return resp.Instances, err
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100180 }
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100181 resp.Instances[i].Updated = updatedTime
Jamie Hannaforde65ad952015-11-16 14:05:11 +0100182 }
183 }
184
Jamie Hannaford87704ba2016-01-14 11:49:56 +0100185 return resp.Instances, nil
Jamie Hannaford90684242015-02-10 12:46:07 +0100186}
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100187
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100188// UserRootResult represents the result of an operation to enable the root user.
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100189type UserRootResult struct {
190 gophercloud.Result
191}
192
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100193// Extract will extract root user information from a UserRootResult.
Jamie Hannaford3aba0b12015-02-13 14:33:39 +0100194func (r UserRootResult) Extract() (*users.User, error) {
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100195 if r.Err != nil {
196 return nil, r.Err
197 }
198
199 var response struct {
Jamie Hannaford2ca55d82015-02-12 14:21:55 +0100200 User users.User `mapstructure:"user"`
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100201 }
202
203 err := mapstructure.Decode(r.Body, &response)
204
205 return &response.User, err
206}
Jamie Hannaford219ca592015-02-10 15:59:05 +0100207
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100208// ActionResult represents the result of action requests, such as: restarting
209// an instance service, resizing its memory allocation, and resizing its
210// attached volume size.
Jamie Hannaford219ca592015-02-10 15:59:05 +0100211type ActionResult struct {
212 gophercloud.ErrResult
213}