blob: 95d03caf1c2951221ded6ebe84c3fb761364f8ce [file] [log] [blame]
Brad Ison53e997c2016-03-26 18:02:05 -04001package policies
2
3import (
4 "github.com/mitchellh/mapstructure"
5
6 "github.com/rackspace/gophercloud"
7 "github.com/rackspace/gophercloud/pagination"
8)
9
10type policyResult struct {
11 gophercloud.Result
12}
13
Brad Ison55523e52016-04-06 19:25:20 -040014// Extract interprets any policyResult as a Policy, if possible.
15func (r policyResult) Extract() (*Policy, error) {
16 if r.Err != nil {
17 return nil, r.Err
18 }
19
20 var response struct {
Brad Ison2b739162016-04-11 12:40:11 -040021 Policy policy `mapstructure:"policy"`
Brad Ison55523e52016-04-06 19:25:20 -040022 }
23
Brad Ison2b739162016-04-11 12:40:11 -040024 if err := mapstructure.Decode(r.Body, &response); err != nil {
25 return nil, err
26 }
Brad Ison55523e52016-04-06 19:25:20 -040027
Brad Ison2b739162016-04-11 12:40:11 -040028 policy := response.Policy.toExported()
29
30 return &policy, nil
Brad Ison55523e52016-04-06 19:25:20 -040031}
32
Brad Isone7d6dfc2016-04-06 14:55:07 -040033// CreateResult represents the result of a create operation.
34type CreateResult struct {
35 policyResult
36}
37
38// Extract extracts a slice of Policies from a CreateResult. Multiple policies
39// can be created in a single operation, so the result of a create is always a
40// list of policies.
41func (res CreateResult) Extract() ([]Policy, error) {
42 if res.Err != nil {
43 return nil, res.Err
44 }
45
46 return commonExtractPolicies(res.Body)
47}
48
Brad Ison55523e52016-04-06 19:25:20 -040049// GetResult temporarily contains the response from a Get call.
50type GetResult struct {
51 policyResult
52}
53
Brad Isonac037d52016-04-07 19:41:29 -040054// UpdateResult represents the result of an update operation.
55type UpdateResult struct {
56 gophercloud.ErrResult
57}
58
Brad Ison124df8e2016-04-07 19:51:51 -040059// DeleteResult represents the result of a delete operation.
60type DeleteResult struct {
61 gophercloud.ErrResult
62}
63
Brad Ison42f8dfb2016-04-07 20:26:06 -040064// ExecuteResult represents the result of an execute operation.
65type ExecuteResult struct {
66 gophercloud.ErrResult
67}
68
Brad Ison53e997c2016-03-26 18:02:05 -040069// Type represents a type of scaling policy.
70type Type string
71
72const (
73 // Schedule policies run at given times.
74 Schedule Type = "schedule"
75
76 // Webhook policies are triggered by HTTP requests.
77 Webhook Type = "webhook"
78)
79
Brad Ison2b739162016-04-11 12:40:11 -040080// AdjustmentType represents the way in which a policy will change a group.
81type AdjustmentType string
82
83// Valid types of adjustments for a policy.
84const (
85 Change AdjustmentType = "change"
86 ChangePercent AdjustmentType = "changePercent"
87 DesiredCapacity AdjustmentType = "desiredCapacity"
88)
89
90// Policy represents a scaling policy.
91type Policy struct {
92 // UUID for the policy.
93 ID string
94
95 // Name of the policy.
96 Name string
97
98 // Type of scaling policy.
99 Type Type
100
101 // Cooldown period, in seconds.
102 Cooldown int
103
104 // The type of adjustment in capacity to be made.
105 AdjustmentType AdjustmentType
106
107 // The numeric value of the adjustment in capacity.
108 AdjustmentValue float64
109
110 // Additional configuration options for some types of policy.
111 Args map[string]interface{}
112}
113
114// This is an intermediate representation of the exported Policy type. The
115// fields in API responses vary by policy type and configuration. This lets us
116// decode responses then normalize them into a Policy.
117type policy struct {
118 ID string `mapstructure:"id"`
119 Name string `mapstructure:"name"`
120 Type Type `mapstructure:"type"`
121 Cooldown int `mapstructure:"cooldown"`
122
123 // The API will respond with exactly one of these omitting the others.
124 Change interface{} `mapstructure:"change"`
125 ChangePercent interface{} `mapstructure:"changePercent"`
126 DesiredCapacity interface{} `mapstructure:"desiredCapacity"`
127
128 // Additional configuration options for schedule policies.
129 Args map[string]interface{} `mapstructure:"args"`
130}
131
132// Assemble a Policy from the intermediate policy struct.
133func (p policy) toExported() Policy {
134 policy := Policy{}
135
136 policy.ID = p.ID
137 policy.Name = p.Name
138 policy.Type = p.Type
139 policy.Cooldown = p.Cooldown
140
141 policy.Args = p.Args
142
143 if v, ok := p.Change.(float64); ok {
144 policy.AdjustmentType = Change
145 policy.AdjustmentValue = v
146 } else if v, ok := p.ChangePercent.(float64); ok {
147 policy.AdjustmentType = ChangePercent
148 policy.AdjustmentValue = v
149 } else if v, ok := p.DesiredCapacity.(float64); ok {
150 policy.AdjustmentType = DesiredCapacity
151 policy.AdjustmentValue = v
152 }
153
154 return policy
155}
156
Brad Ison53e997c2016-03-26 18:02:05 -0400157// PolicyPage is the page returned by a pager when traversing over a collection
158// of scaling policies.
159type PolicyPage struct {
160 pagination.SinglePageBase
161}
162
163// IsEmpty returns true if a page contains no Policy results.
164func (page PolicyPage) IsEmpty() (bool, error) {
165 policies, err := ExtractPolicies(page)
166
167 if err != nil {
168 return true, err
169 }
170
171 return len(policies) == 0, nil
172}
173
174// ExtractPolicies interprets the results of a single page from a List() call,
175// producing a slice of Policies.
176func ExtractPolicies(page pagination.Page) ([]Policy, error) {
Brad Isone7d6dfc2016-04-06 14:55:07 -0400177 return commonExtractPolicies(page.(PolicyPage).Body)
178}
Brad Ison53e997c2016-03-26 18:02:05 -0400179
Brad Isone7d6dfc2016-04-06 14:55:07 -0400180func commonExtractPolicies(body interface{}) ([]Policy, error) {
Brad Ison53e997c2016-03-26 18:02:05 -0400181 var response struct {
Brad Ison2b739162016-04-11 12:40:11 -0400182 Policies []policy `mapstructure:"policies"`
Brad Ison53e997c2016-03-26 18:02:05 -0400183 }
184
Brad Isone7d6dfc2016-04-06 14:55:07 -0400185 err := mapstructure.Decode(body, &response)
Brad Ison53e997c2016-03-26 18:02:05 -0400186
187 if err != nil {
188 return nil, err
189 }
190
Brad Ison2b739162016-04-11 12:40:11 -0400191 policies := make([]Policy, len(response.Policies))
192
193 for i, p := range response.Policies {
194 policies[i] = p.toExported()
195 }
196
197 return policies, nil
Brad Ison53e997c2016-03-26 18:02:05 -0400198}