1package instances
2
3import (
4	"encoding/json"
5	"time"
6
7	"github.com/gophercloud/gophercloud"
8	"github.com/gophercloud/gophercloud/openstack/db/v1/datastores"
9	"github.com/gophercloud/gophercloud/openstack/db/v1/users"
10	"github.com/gophercloud/gophercloud/pagination"
11)
12
13// Volume represents information about an attached volume for a database instance.
14type Volume struct {
15	// The size in GB of the volume
16	Size int
17
18	Used float64
19}
20
21// Flavor represents (virtual) hardware configurations for server resources in a region.
22type Flavor struct {
23	// The flavor's unique identifier.
24	ID string
25	// Links to access the flavor.
26	Links []gophercloud.Link
27}
28
29// Fault describes the fault reason in more detail when a database instance has errored
30type Fault struct {
31	// Indicates the time when the fault occured
32	Created time.Time `json:"-"`
33
34	// A message describing the fault reason
35	Message string
36
37	// More details about the fault, for example a stack trace. Only filled
38	// in for admin users.
39	Details string
40}
41
42func (r *Fault) UnmarshalJSON(b []byte) error {
43	type tmp Fault
44	var s struct {
45		tmp
46		Created gophercloud.JSONRFC3339NoZ `json:"created"`
47	}
48	err := json.Unmarshal(b, &s)
49	if err != nil {
50		return err
51	}
52	*r = Fault(s.tmp)
53
54	r.Created = time.Time(s.Created)
55
56	return nil
57}
58
59// Instance represents a remote MySQL instance.
60type Instance struct {
61	// Indicates the datetime that the instance was created
62	Created time.Time `json:"-"`
63
64	// Indicates the most recent datetime that the instance was updated.
65	Updated time.Time `json:"-"`
66
67	// Indicates the hardware flavor the instance uses.
68	Flavor Flavor
69
70	// A DNS-resolvable hostname associated with the database instance (rather
71	// than an IPv4 address). Since the hostname always resolves to the correct
72	// IP address of the database instance, this relieves the user from the task
73	// of maintaining the mapping. Note that although the IP address may likely
74	// change on resizing, migrating, and so forth, the hostname always resolves
75	// to the correct database instance.
76	Hostname string
77
78	// The IP addresses associated with the database instance
79	// Is empty if the instance has a hostname
80	IP []string
81
82	// Indicates the unique identifier for the instance resource.
83	ID string
84
85	// Exposes various links that reference the instance resource.
86	Links []gophercloud.Link
87
88	// The human-readable name of the instance.
89	Name string
90
91	// The build status of the instance.
92	Status string
93
94	// Fault information (only available when the instance has errored)
95	Fault *Fault
96
97	// Information about the attached volume of the instance.
98	Volume Volume
99
100	// Indicates how the instance stores data.
101	Datastore datastores.DatastorePartial
102}
103
104func (r *Instance) UnmarshalJSON(b []byte) error {
105	type tmp Instance
106	var s struct {
107		tmp
108		Created gophercloud.JSONRFC3339NoZ `json:"created"`
109		Updated gophercloud.JSONRFC3339NoZ `json:"updated"`
110	}
111	err := json.Unmarshal(b, &s)
112	if err != nil {
113		return err
114	}
115	*r = Instance(s.tmp)
116
117	r.Created = time.Time(s.Created)
118	r.Updated = time.Time(s.Updated)
119
120	return nil
121}
122
123type commonResult struct {
124	gophercloud.Result
125}
126
127// CreateResult represents the result of a Create operation.
128type CreateResult struct {
129	commonResult
130}
131
132// GetResult represents the result of a Get operation.
133type GetResult struct {
134	commonResult
135}
136
137// DeleteResult represents the result of a Delete operation.
138type DeleteResult struct {
139	gophercloud.ErrResult
140}
141
142// ConfigurationResult represents the result of a AttachConfigurationGroup/DetachConfigurationGroup operation.
143type ConfigurationResult struct {
144	gophercloud.ErrResult
145}
146
147// Extract will extract an Instance from various result structs.
148func (r commonResult) Extract() (*Instance, error) {
149	var s struct {
150		Instance *Instance `json:"instance"`
151	}
152	err := r.ExtractInto(&s)
153	return s.Instance, err
154}
155
156// InstancePage represents a single page of a paginated instance collection.
157type InstancePage struct {
158	pagination.LinkedPageBase
159}
160
161// IsEmpty checks to see whether the collection is empty.
162func (page InstancePage) IsEmpty() (bool, error) {
163	instances, err := ExtractInstances(page)
164	return len(instances) == 0, err
165}
166
167// NextPageURL will retrieve the next page URL.
168func (page InstancePage) NextPageURL() (string, error) {
169	var s struct {
170		Links []gophercloud.Link `json:"instances_links"`
171	}
172	err := page.ExtractInto(&s)
173	if err != nil {
174		return "", err
175	}
176	return gophercloud.ExtractNextURL(s.Links)
177}
178
179// ExtractInstances will convert a generic pagination struct into a more
180// relevant slice of Instance structs.
181func ExtractInstances(r pagination.Page) ([]Instance, error) {
182	var s struct {
183		Instances []Instance `json:"instances"`
184	}
185	err := (r.(InstancePage)).ExtractInto(&s)
186	return s.Instances, err
187}
188
189// EnableRootUserResult represents the result of an operation to enable the root user.
190type EnableRootUserResult struct {
191	gophercloud.Result
192}
193
194// Extract will extract root user information from a UserRootResult.
195func (r EnableRootUserResult) Extract() (*users.User, error) {
196	var s struct {
197		User *users.User `json:"user"`
198	}
199	err := r.ExtractInto(&s)
200	return s.User, err
201}
202
203// ActionResult represents the result of action requests, such as: restarting
204// an instance service, resizing its memory allocation, and resizing its
205// attached volume size.
206type ActionResult struct {
207	gophercloud.ErrResult
208}
209
210// IsRootEnabledResult is the result of a call to IsRootEnabled. To see if
211// root is enabled, call the type's Extract method.
212type IsRootEnabledResult struct {
213	gophercloud.Result
214}
215
216// Extract is used to extract the data from a IsRootEnabledResult.
217func (r IsRootEnabledResult) Extract() (bool, error) {
218	return r.Body.(map[string]interface{})["rootEnabled"] == true, r.Err
219}
220