blob: 4a0de8e10737f27bfaa3129791ac09d04b00c07c [file] [log] [blame]
Jon Perritt3711cd02014-12-22 22:20:15 -07001package stackresources
2
3import (
4 "time"
5
6 "github.com/mitchellh/mapstructure"
7 "github.com/rackspace/gophercloud"
8 "github.com/rackspace/gophercloud/pagination"
9)
10
11type Resource struct {
12 Links []gophercloud.Link `mapstructure:"links"`
13 LogicalID string `mapstructure:"logical_resource_id"`
14 Name string `mapstructure:"resource_name"`
15 PhysicalID string `mapstructure:"physical_resource_id"`
16 RequiredBy []interface{} `mapstructure:"required_by"`
17 Status string `mapstructure:"resource_status"`
18 StatusReason string `mapstructure:"resource_status_reason"`
19 Type string `mapstructure:"resource_type"`
20 UpdatedTime time.Time `mapstructure:"-"`
21}
22
23type FindResult struct {
24 gophercloud.Result
25}
26
27func (r FindResult) Extract() ([]Resource, error) {
28 if r.Err != nil {
29 return nil, r.Err
30 }
31
32 var res struct {
33 Res []Resource `mapstructure:"resources"`
34 }
35
36 if err := mapstructure.Decode(r.Body, &res); err != nil {
37 return nil, err
38 }
39
Jon Perritta065da12015-02-06 10:20:16 -070040 resources := r.Body.(map[string]interface{})["resources"].([]interface{})
Jon Perritt3711cd02014-12-22 22:20:15 -070041
Jon Perritta065da12015-02-06 10:20:16 -070042 for i, resourceRaw := range resources {
43 resource := resourceRaw.(map[string]interface{})
Jon Perritt3711cd02014-12-22 22:20:15 -070044 if date, ok := resource["updated_time"]; ok && date != nil {
45 t, err := time.Parse(time.RFC3339, date.(string))
46 if err != nil {
47 return nil, err
48 }
49 res.Res[i].UpdatedTime = t
50 }
51 }
52
53 return res.Res, nil
54}
55
56// ResourcePage abstracts the raw results of making a List() request against the API.
57// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the
58// data provided through the ExtractResources call.
59type ResourcePage struct {
Jon Perrittc8717332015-02-08 20:14:29 -070060 pagination.MarkerPageBase
Jon Perritt3711cd02014-12-22 22:20:15 -070061}
62
63// IsEmpty returns true if a page contains no Server results.
Jon Perrittc8717332015-02-08 20:14:29 -070064func (r ResourcePage) IsEmpty() (bool, error) {
65 resources, err := ExtractResources(r)
Jon Perritt3711cd02014-12-22 22:20:15 -070066 if err != nil {
67 return true, err
68 }
69 return len(resources) == 0, nil
70}
71
Jon Perrittc8717332015-02-08 20:14:29 -070072// LastMarker returns the last container name in a ListResult.
73func (r ResourcePage) LastMarker() (string, error) {
74 resources, err := ExtractResources(r)
Jon Perritt3711cd02014-12-22 22:20:15 -070075 if err != nil {
76 return "", err
77 }
Jon Perrittc8717332015-02-08 20:14:29 -070078 if len(resources) == 0 {
79 return "", nil
80 }
81 return resources[len(resources)-1].PhysicalID, nil
Jon Perritt3711cd02014-12-22 22:20:15 -070082}
83
84// ExtractResources interprets the results of a single page from a List() call, producing a slice of Resource entities.
85func ExtractResources(page pagination.Page) ([]Resource, error) {
86 casted := page.(ResourcePage).Body
87
88 var response struct {
89 Resources []Resource `mapstructure:"resources"`
90 }
91 err := mapstructure.Decode(casted, &response)
Jon Perritta065da12015-02-06 10:20:16 -070092
93 resources := casted.(map[string]interface{})["resources"].([]interface{})
94
95 for i, resourceRaw := range resources {
96 resource := resourceRaw.(map[string]interface{})
97 if date, ok := resource["updated_time"]; ok && date != nil {
98 t, err := time.Parse(time.RFC3339, date.(string))
99 if err != nil {
100 return nil, err
101 }
102 response.Resources[i].UpdatedTime = t
103 }
104 }
105
Jon Perritt3711cd02014-12-22 22:20:15 -0700106 return response.Resources, err
107}
108
109type GetResult struct {
110 gophercloud.Result
111}
112
113func (r GetResult) Extract() (*Resource, error) {
114 if r.Err != nil {
115 return nil, r.Err
116 }
117
118 var res struct {
119 Res *Resource `mapstructure:"resource"`
120 }
121
122 if err := mapstructure.Decode(r.Body, &res); err != nil {
123 return nil, err
124 }
125
126 resource := r.Body.(map[string]interface{})["resource"].(map[string]interface{})
127
128 if date, ok := resource["updated_time"]; ok && date != nil {
129 t, err := time.Parse(time.RFC3339, date.(string))
130 if err != nil {
131 return nil, err
132 }
133 res.Res.UpdatedTime = t
134 }
135
136 return res.Res, nil
137}
138
139type MetadataResult struct {
140 gophercloud.Result
141}
142
143func (r MetadataResult) Extract() (map[string]string, error) {
144 if r.Err != nil {
145 return nil, r.Err
146 }
147
148 var res struct {
149 Meta map[string]string `mapstructure:"metadata"`
150 }
151
152 if err := mapstructure.Decode(r.Body, &res); err != nil {
153 return nil, err
154 }
155
156 return res.Meta, nil
157}
Jon Perritta065da12015-02-06 10:20:16 -0700158
159// ResourceTypePage abstracts the raw results of making a ListTypes() request against the API.
160// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the
161// data provided through the ExtractResourceTypes call.
162type ResourceTypePage struct {
163 pagination.SinglePageBase
164}
165
166// IsEmpty returns true if a ResourceTypePage contains no resource types.
167func (r ResourceTypePage) IsEmpty() (bool, error) {
168 rts, err := ExtractResourceTypes(r)
169 if err != nil {
170 return true, err
171 }
172 return len(rts) == 0, nil
173}
174
175// ExtractResourceTypes extracts and returns resource types.
176func ExtractResourceTypes(page pagination.Page) ([]string, error) {
177 var response struct {
178 ResourceTypes []string `mapstructure:"resource_types"`
179 }
180
181 err := mapstructure.Decode(page.(ResourceTypePage).Body, &response)
182 return response.ResourceTypes, err
183}
Jon Perritt1d4aca02015-02-06 12:29:16 -0700184
185type TypeSchema struct {
186 Attributes map[string]interface{} `mapstructure:"attributes"`
187 Properties map[string]interface{} `mapstrucutre:"properties"`
188 ResourceType string `mapstructure:"resource_type"`
189}
190
191type SchemaResult struct {
192 gophercloud.Result
193}
194
195func (r SchemaResult) Extract() (*TypeSchema, error) {
196 if r.Err != nil {
197 return nil, r.Err
198 }
199
200 var res TypeSchema
201
202 if err := mapstructure.Decode(r.Body, &res); err != nil {
203 return nil, err
204 }
205
206 return &res, nil
207}
Jon Perrittb1e303a2015-02-06 22:15:44 -0700208
209type TypeTemplate struct {
210 HeatTemplateFormatVersion string
211 Outputs map[string]interface{}
212 Parameters map[string]interface{}
213 Resources map[string]interface{}
214}
215
216type TemplateResult struct {
217 gophercloud.Result
218}
219
220func (r TemplateResult) Extract() (*TypeTemplate, error) {
221 if r.Err != nil {
222 return nil, r.Err
223 }
224
225 var res TypeTemplate
226
227 if err := mapstructure.Decode(r.Body, &res); err != nil {
228 return nil, err
229 }
230
231 return &res, nil
232}