File: results.go

package info (click to toggle)
golang-github-gophercloud-utils 0.0~git20231010.80377ec-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 816 kB
  • sloc: sh: 20; makefile: 7
file content (184 lines) | stat: -rw-r--r-- 5,450 bytes parent folder | download
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
}