Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 4d9f5d7

Browse files
carlpettDSpeichert
authored andcommitted
Add support for reading meters
1 parent 0792eb7 commit 4d9f5d7

File tree

4 files changed

+140
-3
lines changed

4 files changed

+140
-3
lines changed

openstack/telemetry/v2/meters/fixtures.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ package meters
44

55
import (
66
"fmt"
7-
"net/http"
8-
"testing"
9-
107
th "github.com/rackspace/gophercloud/testhelper"
118
"github.com/rackspace/gophercloud/testhelper/client"
9+
"net/http"
10+
"testing"
11+
"time"
1212
)
1313

1414
// MeterListBody contains the canned body of a meters.List response.
@@ -119,6 +119,23 @@ var (
119119
UserId: "7ya0f7a33717400b951037d55b929c53",
120120
}
121121

122+
ShowHerp = OldSample{
123+
Name: "instance",
124+
Type: "gauge",
125+
Unit: "instance",
126+
Volume: 1.0,
127+
MessageId: "5460acce-4fd6-480d-ab18-9735ec7b1996",
128+
ProjectId: "35b17138-b364-4e6a-a131-8f3099c5be68",
129+
ResourceId: "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
130+
ResourceMetadata: map[string]string{
131+
"name1": "value1",
132+
"name2": "value2",
133+
},
134+
Source: "openstack",
135+
Timestamp: time.Date(2013, time.November, 21, 12, 33, 8, 323533000, time.UTC),
136+
UserId: "efd87807-12d2-4b38-9c70-5f5c2ac427ff",
137+
}
138+
122139
// StatisticsHerp is a Statistics struct that should correspond to the first result in *[]Statistics.
123140
StatisticsHerp = Statistics{
124141
Avg: 4.5,

openstack/telemetry/v2/meters/requests.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,51 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) ListResult {
4343
return res
4444
}
4545

46+
// ShowOptsBuilder allows extensions to add additional parameters to the
47+
// Show request.
48+
type ShowOptsBuilder interface {
49+
ToShowQuery() (string, error)
50+
}
51+
52+
// ShowOpts allows the filtering and sorting of collections through
53+
// the API. Filtering is achieved by passing in struct field values that map to
54+
// the server attributes you want to see returned.
55+
type ShowOpts struct {
56+
QueryField string `q:"q.field"`
57+
QueryOp string `q:"q.op"`
58+
QueryValue string `q:"q.value"`
59+
60+
// Optional, maximum number of results to return
61+
Limit int `q:"limit"`
62+
}
63+
64+
// ToMeterShowQuery formats a ShowOpts into a query string.
65+
func (opts ShowOpts) ToShowQuery() (string, error) {
66+
q, err := gophercloud.BuildQueryString(opts)
67+
if err != nil {
68+
return "", err
69+
}
70+
return q.String(), nil
71+
}
72+
73+
// Show makes a request against the API to show a specific meter
74+
func Show(client *gophercloud.ServiceClient, meterName string, opts ShowOptsBuilder) ShowResult {
75+
var res ShowResult
76+
url := showURL(client, meterName)
77+
78+
if opts != nil {
79+
query, err := opts.ToShowQuery()
80+
if err != nil {
81+
res.Err = err
82+
return res
83+
}
84+
url += query
85+
}
86+
87+
_, res.Err = client.Get(url, &res.Body, &gophercloud.RequestOpts{})
88+
return res
89+
}
90+
4691
// StatisticsOptsBuilder allows extensions to add additional parameters to the
4792
// List request.
4893
type MeterStatisticsOptsBuilder interface {

openstack/telemetry/v2/meters/requests_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ func TestListMeters(t *testing.T) {
2222
th.CheckDeepEquals(t, MeterDerp, (list)[1])
2323
}
2424

25+
func TestShowMeters(t *testing.T) {
26+
th.SetupHTTP()
27+
defer th.TeardownHTTP()
28+
HandleMeterShowSuccessfully(t)
29+
30+
meters, err := Show(client.ServiceClient(), "instance", ShowOpts{}).Extract()
31+
th.AssertNoErr(t, err)
32+
33+
if len(meters) != 1 {
34+
t.Fatalf("Expected 1 meters, got %d", len(meters))
35+
}
36+
th.CheckDeepEquals(t, ShowHerp, (meters)[0])
37+
}
38+
2539
func TestMeterStatistics(t *testing.T) {
2640
th.SetupHTTP()
2741
defer th.TeardownHTTP()

openstack/telemetry/v2/meters/results.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package meters
22

33
import (
44
"reflect"
5+
"time"
56

67
"github.com/mitchellh/mapstructure"
78
"github.com/rackspace/gophercloud"
@@ -18,6 +19,21 @@ type Meter struct {
1819
UserId string `mapstructure:"user_id"`
1920
}
2021

22+
type OldSample struct {
23+
Name string `mapstructure:"counter_name"`
24+
Type string `mapstructure:"counter_type"`
25+
Unit string `mapstructure:"counter_unit"`
26+
Volume float32 `mapstructure:"counter_volume"`
27+
MessageId string `mapstructure:"message_id"`
28+
ProjectId string `mapstructure:"project_id"`
29+
RecordedAt time.Time `mapstructure:"recorded_at"`
30+
ResourceId string `mapstructure:"resource_id"`
31+
ResourceMetadata map[string]string `mapstructure:"resource_metadata"`
32+
Source string `mapstructure:"source"`
33+
Timestamp time.Time `mapstructure:"timestamp"`
34+
UserId string `mapstructure:"user_id"`
35+
}
36+
2137
type ListResult struct {
2238
gophercloud.Result
2339
}
@@ -47,6 +63,34 @@ func (r ListResult) Extract() ([]Meter, error) {
4763
return response, nil
4864
}
4965

66+
type ShowResult struct {
67+
gophercloud.Result
68+
}
69+
70+
func (r ShowResult) Extract() ([]OldSample, error) {
71+
if r.Err != nil {
72+
return nil, r.Err
73+
}
74+
75+
var response []OldSample
76+
77+
config := &mapstructure.DecoderConfig{
78+
DecodeHook: decoderHooks,
79+
Result: &response,
80+
}
81+
decoder, err := mapstructure.NewDecoder(config)
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
err = decoder.Decode(r.Body)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
return response, nil
92+
}
93+
5094
type Statistics struct {
5195
Avg float32 `json:"avg"`
5296
Count int `json:"count"`
@@ -91,9 +135,26 @@ func (r StatisticsResult) Extract() ([]Statistics, error) {
91135
return response, nil
92136
}
93137

138+
func decoderHooks(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
139+
if (from.Kind() == reflect.String) && (to.Kind() == reflect.Map) {
140+
return toMapFromString(from.Kind(), to.Kind(), data)
141+
} else if to == reflect.TypeOf(time.Time{}) && from == reflect.TypeOf("") {
142+
return toDateFromString(from, to, data)
143+
}
144+
return data, nil
145+
}
94146
func toMapFromString(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) {
95147
if (from == reflect.String) && (to == reflect.Map) {
96148
return map[string]interface{}{}, nil
97149
}
98150
return data, nil
99151
}
152+
153+
// From https://github.com/mitchellh/mapstructure/issues/41
154+
func toDateFromString(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
155+
if to == reflect.TypeOf(time.Time{}) && from == reflect.TypeOf("") {
156+
return time.Parse("2006-01-02T15:04:05.999999999", data.(string))
157+
}
158+
159+
return data, nil
160+
}

0 commit comments

Comments
 (0)