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
|
package resources
import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
"github.com/gophercloud/utils/gnocchi"
"github.com/gophercloud/utils/internal"
)
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a Gnocchi resource.
func (r commonResult) Extract() (*Resource, error) {
var s *Resource
err := r.ExtractInto(&s)
return s, err
}
// GetResult represents the result of a get operation. Call its Extract
// method to interpret it as a Gnocchi resource.
type GetResult struct {
commonResult
}
// CreateResult represents the result of a create operation. Call its Extract
// method to interpret it as a Gnocchi resource.
type CreateResult struct {
commonResult
}
// UpdateResult represents the result of an update operation. Call its Extract
// method to interpret it as a Gnocchi resource.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// Resource is an entity representing anything in your infrastructure
// that you will associate metric(s) with.
// It is identified by a unique ID and can contain attributes.
type Resource struct {
// CreatedByProjectID contains the id of the Identity project that
// was used for a resource creation.
CreatedByProjectID string `json:"created_by_project_id"`
// CreatedByUserID contains the id of the Identity user
// that created the Gnocchi resource.
CreatedByUserID string `json:"created_by_user_id"`
// Creator shows who created the resource.
// Usually it contains concatenated string with values from
// "created_by_user_id" and "created_by_project_id" fields.
Creator string `json:"creator"`
// ID uniquely identifies the Gnocchi resource.
ID string `json:"id"`
// Metrics are entities that store aggregates.
Metrics map[string]string `json:"metrics"`
// OriginalResourceID is the orginal resource id. It can be different from the
// regular ID field.
OriginalResourceID string `json:"original_resource_id"`
// ProjectID is the Identity project of the resource.
ProjectID string `json:"project_id"`
// RevisionStart is a staring timestamp of the current resource revision.
RevisionStart time.Time `json:"-"`
// RevisionEnd is an ending timestamp of the last resource revision.
RevisionEnd time.Time `json:"-"`
// StartedAt is a resource creation timestamp.
StartedAt time.Time `json:"-"`
// EndedAt is a timestamp of when the resource has ended.
EndedAt time.Time `json:"-"`
// Type is a type of the resource.
Type string `json:"type"`
// UserID is the Identity user of the resource.
UserID string `json:"user_id"`
// ExtraAttributes is a collection of keys and values that can be found in resources
// of different resource types.
ExtraAttributes map[string]interface{} `json:"-"`
}
// UnmarshalJSON helps to unmarshal Resource fields into needed values.
func (r *Resource) UnmarshalJSON(b []byte) error {
type tmp Resource
var s struct {
tmp
ExtraAttributes map[string]interface{} `json:"extra_attributes"`
RevisionStart gnocchi.JSONRFC3339NanoTimezone `json:"revision_start"`
RevisionEnd gnocchi.JSONRFC3339NanoTimezone `json:"revision_end"`
StartedAt gnocchi.JSONRFC3339NanoTimezone `json:"started_at"`
EndedAt gnocchi.JSONRFC3339NanoTimezone `json:"ended_at"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Resource(s.tmp)
// Collect Gnocchi timestamps.
r.RevisionStart = time.Time(s.RevisionStart)
r.RevisionEnd = time.Time(s.RevisionEnd)
r.StartedAt = time.Time(s.StartedAt)
r.EndedAt = time.Time(s.EndedAt)
// Collect other resource fields
// and bundle them into ExtraAttributes.
if s.ExtraAttributes != nil {
r.ExtraAttributes = s.ExtraAttributes
} else {
var result interface{}
err := json.Unmarshal(b, &result)
if err != nil {
return err
}
if resultMap, ok := result.(map[string]interface{}); ok {
delete(resultMap, "revision_start")
delete(resultMap, "revision_end")
delete(resultMap, "started_at")
delete(resultMap, "ended_at")
r.ExtraAttributes = internal.RemainingKeys(Resource{}, resultMap)
}
}
return err
}
// ResourcePage abstracts the raw results of making a List() request against
// the Gnocchi API.
//
// As Gnocchi API may freely alter the response bodies of structures
// returned to the client, you may only safely access the data provided through
// the ExtractResources call.
type ResourcePage struct {
pagination.MarkerPageBase
}
// IsEmpty checks whether a ResourcePage struct is empty.
func (r ResourcePage) IsEmpty() (bool, error) {
is, err := ExtractResources(r)
return len(is) == 0, err
}
// LastMarker returns the last resource ID in a ListResult.
func (r ResourcePage) LastMarker() (string, error) {
resources, err := ExtractResources(r)
if err != nil {
return "", err
}
if len(resources) == 0 {
return "", nil
}
return resources[len(resources)-1].ID, nil
}
// ExtractResources interprets the results of a single page from a List() call,
// producing a slice of Resource structs.
func ExtractResources(r pagination.Page) ([]Resource, error) {
var s []Resource
err := (r.(ResourcePage)).ExtractInto(&s)
if err != nil {
return nil, err
}
return s, err
}
|