forked from gophercloud/utils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
requests.go
399 lines (332 loc) · 13.4 KB
/
requests.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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
package measures
import (
"fmt"
"net/url"
"time"
"github.com/cro8ox/gophercloud"
"github.com/cro8ox/gophercloud/pagination"
"github.com/cro8ox/utils/gnocchi"
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToMeasureListQuery() (string, error)
}
// ListOpts allows to provide additional options to the Gnocchi measures List request.
type ListOpts struct {
// Refresh can be used to force any unprocessed measures to be handled in the Gnocchi
// to ensure that List request returns all aggregates.
Refresh bool `q:"refresh"`
// Start is a start of time time range for the measures.
Start *time.Time
// Stop is a stop of time time range for the measures.
Stop *time.Time
// Aggregation is a needed aggregation method for returned measures.
// Gnocchi returns "mean" by default.
Aggregation string `q:"aggregation"`
// Granularity is a needed time between two series of measures to retreive.
// Gnocchi will response with all granularities for available measures by default.
Granularity string `q:"granularity"`
// Resample allows to select different granularity instead of those that were defined in the
// archive policy.
Resample string `q:"resample"`
}
// ToMeasureListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToMeasureListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
params := q.Query()
if opts.Start != nil {
params.Add("start", opts.Start.Format(gnocchi.RFC3339NanoNoTimezone))
}
if opts.Stop != nil {
params.Add("stop", opts.Stop.Format(gnocchi.RFC3339NanoNoTimezone))
}
q = &url.URL{RawQuery: params.Encode()}
return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
// measures.
// It accepts a ListOpts struct, which allows you to provide options to a Gnocchi measures List request.
func List(c *gophercloud.ServiceClient, metricID string, opts ListOptsBuilder) pagination.Pager {
url := listURL(c, metricID)
if opts != nil {
query, err := opts.ToMeasureListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return MeasurePage{pagination.SinglePageBase(r)}
})
}
// CreateOptsBuilder is needed to add measures to the Create request.
type CreateOptsBuilder interface {
ToMeasureCreateMap() (map[string]interface{}, error)
}
// MeasureOpts represents options of a single measure that can be created in the Gnocchi.
type MeasureOpts struct {
// Timestamp represents a measure creation timestamp.
Timestamp *time.Time `json:"-" required:"true"`
// Value represents a measure data value.
Value float64 `json:"value"`
}
// ToMap is a helper function to convert individual MeasureOpts structure into a sub-map.
func (opts MeasureOpts) ToMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "")
if err != nil {
return nil, err
}
if opts.Timestamp != nil {
b["timestamp"] = opts.Timestamp.Format(gnocchi.RFC3339NanoNoTimezone)
}
return b, nil
}
// CreateOpts specifies a parameters for creating measures for a single metric.
type CreateOpts struct {
// Measures is a set of measures for a single metric that needs to be created.
Measures []MeasureOpts
}
// ToMeasureCreateMap constructs a request body from CreateOpts.
func (opts CreateOpts) ToMeasureCreateMap() (map[string]interface{}, error) {
measures := make([]map[string]interface{}, len(opts.Measures))
for i, m := range opts.Measures {
measureMap, err := m.ToMap()
if err != nil {
return nil, err
}
measures[i] = measureMap
}
return map[string]interface{}{"measures": measures}, nil
}
// Create requests the creation of a new measures in the single Gnocchi metric.
func Create(client *gophercloud.ServiceClient, metricID string, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToMeasureCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = client.Post(createURL(client, metricID), b["measures"], &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{202},
MoreHeaders: map[string]string{
"Accept": "application/json, */*",
},
})
return
}
// BatchCreateMetricsOptsBuilder is needed to add measures to the BatchCreateMetrics request.
type BatchCreateMetricsOptsBuilder interface {
ToMeasuresBatchCreateMetricsMap() (map[string]interface{}, error)
}
// BatchCreateMetricsOpts specifies a parameters for creating measures for different metrics in a single request.
type BatchCreateMetricsOpts []MetricOpts
// MetricOpts represents measures of a single metric of the BatchCreateMetrics request.
type MetricOpts struct {
// ID uniquely identifies the Gnocchi metric.
ID string
// Measures is a set of measures for a single metric that needs to be created.
Measures []MeasureOpts
}
// ToMap is a helper function to convert individual MetricOpts structure into a sub-map.
func (opts MetricOpts) ToMap() (map[string]interface{}, error) {
// Check provided MetricOpts fields.
if opts.ID == "" {
errMsg := "missing input for the MetricOpts 'ID' argument"
return nil, fmt.Errorf(errMsg)
}
if opts.Measures == nil {
errMsg := "missing input for the MetricOpts 'Measures' argument"
return nil, fmt.Errorf(errMsg)
}
// measures is a slice of measures maps.
measures := make([]map[string]interface{}, len(opts.Measures))
// metricOpts is an internal map representation of the MetricOpts struct.
metricOpts := make(map[string]interface{})
for i, measure := range opts.Measures {
measureMap, err := measure.ToMap()
if err != nil {
return nil, err
}
measures[i] = measureMap
}
metricOpts[opts.ID] = measures
return metricOpts, nil
}
// ToMeasuresBatchCreateMetricsMap constructs a request body from BatchCreateMetricsOpts.
func (opts BatchCreateMetricsOpts) ToMeasuresBatchCreateMetricsMap() (map[string]interface{}, error) {
// batchCreateMetricsOpts is an internal representation of the BatchCreateMetricsOpts struct.
batchCreateMetricsOpts := make(map[string]interface{})
for _, metricOpts := range opts {
metricOptsMap, err := metricOpts.ToMap()
if err != nil {
return nil, err
}
for k, v := range metricOptsMap {
batchCreateMetricsOpts[k] = v
}
}
return map[string]interface{}{"batchCreateMetrics": batchCreateMetricsOpts}, nil
}
// BatchCreateMetrics requests the creation of a new measures for different metrics.
func BatchCreateMetrics(client *gophercloud.ServiceClient, opts BatchCreateMetricsOpts) (r BatchCreateMetricsResult) {
b, err := opts.ToMeasuresBatchCreateMetricsMap()
if err != nil {
r.Err = err
return
}
_, r.Err = client.Post(batchCreateMetricsURL(client), b["batchCreateMetrics"], &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{202},
MoreHeaders: map[string]string{
"Accept": "application/json, */*",
},
})
return
}
// BatchCreateResourcesMetricsOptsBuilder is needed to add measures to the BatchCreateResourcesMetrics request.
type BatchCreateResourcesMetricsOptsBuilder interface {
// ToMeasuresBatchCreateResourcesMetricsMap builds a request body.
ToMeasuresBatchCreateResourcesMetricsMap() (map[string]interface{}, error)
// ToMeasuresBatchCreateResourcesMetricsQuery builds a query string.
ToMeasuresBatchCreateResourcesMetricsQuery() (string, error)
}
// BatchCreateResourcesMetricsOpts specifies a parameters for creating measures inside metrics via resource IDs and metric names.
type BatchCreateResourcesMetricsOpts struct {
// CreateMetrics allows request to create metrics that don't exist yet.
CreateMetrics bool `q:"create_metrics"`
// BatchResourcesMetrics is a map of resource IDs, metrics names and corresponding measures that needs to be created.
BatchResourcesMetrics []BatchResourcesMetricsOpts
}
// BatchResourcesMetricsOpts represents parameters of a single resource of the BatchCreateResourcesMetrics request.
type BatchResourcesMetricsOpts struct {
// ResourceID uniquely identifies the Gnocchi resource.
ResourceID string
// ResourcesMetrics specifies metrics whose measures will be updated.
ResourcesMetrics []ResourcesMetricsOpts
}
// ToMap is a helper function to convert individual BatchResourcesMetricsOpts structure into a sub-map.
func (opts BatchResourcesMetricsOpts) ToMap() (map[string]interface{}, error) {
// Check provided BatchResourcesMetricsOpts fields.
if opts.ResourceID == "" {
errMsg := "missing input for the BatchResourcesMetricsOpts 'ResourceID' argument"
return nil, fmt.Errorf(errMsg)
}
if opts.ResourcesMetrics == nil {
errMsg := "missing input for the BatchResourcesMetricsOpts 'ResourcesMetrics' argument"
return nil, fmt.Errorf(errMsg)
}
// batchResourcesMetricsOpts is an internal map representation of the BatchResourcesMetricsOpts struct.
batchResourcesMetricsOpts := make(map[string]interface{})
// resourcesMetricsMaps is a temporary slice that contains different metrics for a single resource.
resourcesMetricsMaps := make([]map[string]interface{}, len(opts.ResourcesMetrics))
// resourcesMetricsOptsMap is a temporary map that contains join of different maps from resourcesMetricsMaps slice.
resourcesMetricsOptsMap := make(map[string]interface{})
// Populate the temporary resourcesMetricsMaps slice.
for i, resourcesMetrics := range opts.ResourcesMetrics {
resourcesMetricsMap, err := resourcesMetrics.ToMap()
if err != nil {
return nil, err
}
resourcesMetricsMaps[i] = resourcesMetricsMap
}
// Populate the temporary resourcesMetricsOptsMap map.
for _, resourcesMetricsMap := range resourcesMetricsMaps {
for k, v := range resourcesMetricsMap {
resourcesMetricsOptsMap[k] = v
}
}
// Populate the final map batchResourcesMetricsOpts.
batchResourcesMetricsOpts[opts.ResourceID] = resourcesMetricsOptsMap
return batchResourcesMetricsOpts, nil
}
// ResourcesMetricsOpts represents measures of a single metric of the resource from BatchResourcesMetricsOpts.
type ResourcesMetricsOpts struct {
// MetricName is a human-readable name for the Gnocchi metric.
MetricName string
// ArchivePolicyName is a name of the Gnocchi archive policy that describes
// the aggregate storage policy of a metric.
ArchivePolicyName string
// Unit is a unit of measurement for measures of that Gnocchi metric.
Unit string
// Measures is a set of measures for a single metric that needs to be created.
Measures []MeasureOpts
}
// ToMap is a helper function to convert individual ResourcesMetricsOpts structure into a sub-map.
func (opts ResourcesMetricsOpts) ToMap() (map[string]interface{}, error) {
// Check provided ResourcesMetricsOpts fields.
if opts.MetricName == "" {
errMsg := "missing input for the ResourcesMetricsOpts 'MetricName' argument"
return nil, fmt.Errorf(errMsg)
}
if opts.Measures == nil {
errMsg := "missing input for the ResourcesMetricsOpts 'Measures' argument"
return nil, fmt.Errorf(errMsg)
}
// measures is a slice of measures maps.
measures := make([]map[string]interface{}, len(opts.Measures))
// resourcesMetricsOpts is an internal map representation of the ResourcesMetricsOpts struct.
resourcesMetricsOpts := make(map[string]interface{})
// metricOpts is an internal nested map for each metric in the resourcesMetricsOpts.
metricOpts := make(map[string]interface{})
// Populate metricOpts with values from provided opts.
if opts.ArchivePolicyName != "" {
metricOpts["archive_policy_name"] = opts.ArchivePolicyName
}
if opts.Unit != "" {
metricOpts["unit"] = opts.Unit
}
for i, measure := range opts.Measures {
measureMap, err := measure.ToMap()
if err != nil {
return nil, err
}
measures[i] = measureMap
}
metricOpts["measures"] = measures
resourcesMetricsOpts[opts.MetricName] = metricOpts
return resourcesMetricsOpts, nil
}
// ToMeasuresBatchCreateResourcesMetricsMap constructs a request body from the BatchCreateResourcesMetricsOpts.
func (opts BatchCreateResourcesMetricsOpts) ToMeasuresBatchCreateResourcesMetricsMap() (map[string]interface{}, error) {
// batchCreateResourcesMetricsOpts is an internal representation of the
// BatchCreateResourcesMetricsOpts's BatchResourcesMetrics field.
batchCreateResourcesMetricsOpts := make(map[string]interface{})
for _, resourceMetricsOpts := range opts.BatchResourcesMetrics {
resourceMetricsOptsMap, err := resourceMetricsOpts.ToMap()
if err != nil {
return nil, err
}
for k, v := range resourceMetricsOptsMap {
batchCreateResourcesMetricsOpts[k] = v
}
}
return map[string]interface{}{"batchCreateResourcesMetrics": batchCreateResourcesMetricsOpts}, nil
}
// ToMeasuresBatchCreateResourcesMetricsQuery formats the BatchCreateResourcesMetricsOpts into a query string.
func (opts BatchCreateResourcesMetricsOpts) ToMeasuresBatchCreateResourcesMetricsQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// BatchCreateResourcesMetrics requests the creation of new measures inside metrics via resource IDs and metric names.
func BatchCreateResourcesMetrics(client *gophercloud.ServiceClient, opts BatchCreateResourcesMetricsOptsBuilder) (r BatchCreateResourcesMetricsResult) {
url := batchCreateResourcesMetricsURL(client)
if opts != nil {
query, err := opts.ToMeasuresBatchCreateResourcesMetricsQuery()
if err != nil {
r.Err = err
return
}
url += query
}
b, err := opts.ToMeasuresBatchCreateResourcesMetricsMap()
if err != nil {
r.Err = err
return
}
_, r.Err = client.Post(url, b["batchCreateResourcesMetrics"], &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{202},
MoreHeaders: map[string]string{
"Accept": "application/json, */*",
},
})
return
}