/
results.go
179 lines (148 loc) · 4.63 KB
/
results.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
package users
import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/internal"
"github.com/gophercloud/gophercloud/pagination"
)
// User represents a User in the OpenStack Identity Service.
type User struct {
// DefaultProjectID is the ID of the default project of the user.
DefaultProjectID string `json:"default_project_id"`
// Description is the description of the user.
Description string `json:"description"`
// DomainID is the domain ID the user belongs to.
DomainID string `json:"domain_id"`
// Enabled is whether or not the user is enabled.
Enabled bool `json:"enabled"`
// Extra is a collection of miscellaneous key/values.
Extra map[string]interface{} `json:"-"`
// ID is the unique ID of the user.
ID string `json:"id"`
// Links contains referencing links to the user.
Links map[string]interface{} `json:"links"`
// Name is the name of the user.
Name string `json:"name"`
// Options are a set of defined options of the user.
Options map[string]interface{} `json:"options"`
// PasswordExpiresAt is the timestamp when the user's password expires.
PasswordExpiresAt time.Time `json:"-"`
}
func (r *User) UnmarshalJSON(b []byte) error {
type tmp User
var s struct {
tmp
Extra map[string]interface{} `json:"extra"`
PasswordExpiresAt gophercloud.JSONRFC3339MilliNoZ `json:"password_expires_at"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = User(s.tmp)
r.PasswordExpiresAt = time.Time(s.PasswordExpiresAt)
// Collect other fields and bundle them into Extra
// but only if a field titled "extra" wasn't sent.
if s.Extra != nil {
r.Extra = s.Extra
} else {
var result interface{}
err := json.Unmarshal(b, &result)
if err != nil {
return err
}
if resultMap, ok := result.(map[string]interface{}); ok {
delete(resultMap, "password_expires_at")
r.Extra = internal.RemainingKeys(User{}, resultMap)
}
}
return err
}
type userResult struct {
gophercloud.Result
}
// GetResult is the response from a Get operation. Call its Extract method
// to interpret it as a User.
type GetResult struct {
userResult
}
// CreateResult is the response from a Create operation. Call its Extract method
// to interpret it as a User.
type CreateResult struct {
userResult
}
// UpdateResult is the response from an Update operation. Call its Extract
// method to interpret it as a User.
type UpdateResult struct {
userResult
}
// ChangePasswordResult is the response from a ChangePassword operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type ChangePasswordResult struct {
gophercloud.ErrResult
}
// DeleteResult is the response from a Delete operation. Call its ExtractErr to
// determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// AddToGroupResult is the response from a AddToGroup operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type AddToGroupResult struct {
gophercloud.ErrResult
}
// IsMemberOfGroupResult is the response from a IsMemberOfGroup operation. Call its
// Extract method to determine if the request succeeded or failed.
type IsMemberOfGroupResult struct {
isMember bool
gophercloud.Result
}
// RemoveFromGroupResult is the response from a RemoveFromGroup operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type RemoveFromGroupResult struct {
gophercloud.ErrResult
}
// UserPage is a single page of User results.
type UserPage struct {
pagination.LinkedPageBase
}
// IsEmpty determines whether or not a UserPage contains any results.
func (r UserPage) IsEmpty() (bool, error) {
users, err := ExtractUsers(r)
return len(users) == 0, err
}
// NextPageURL extracts the "next" link from the links section of the result.
func (r UserPage) NextPageURL() (string, error) {
var s struct {
Links struct {
Next string `json:"next"`
Previous string `json:"previous"`
} `json:"links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return s.Links.Next, err
}
// ExtractUsers returns a slice of Users contained in a single page of results.
func ExtractUsers(r pagination.Page) ([]User, error) {
var s struct {
Users []User `json:"users"`
}
err := (r.(UserPage)).ExtractInto(&s)
return s.Users, err
}
// Extract interprets any user results as a User.
func (r userResult) Extract() (*User, error) {
var s struct {
User *User `json:"user"`
}
err := r.ExtractInto(&s)
return s.User, err
}
// Extract extracts IsMemberOfGroupResult as bool and error values
func (r IsMemberOfGroupResult) Extract() (bool, error) {
return r.isMember, r.Err
}