blob: 0ebdf5fdb8adce6660c53e7866a0f33f7743b5f0 [file] [log] [blame]
Brad Ison53e997c2016-03-26 18:02:05 -04001package policies
2
3import (
Brad Isone7d6dfc2016-04-06 14:55:07 -04004 "errors"
5
Brad Ison53e997c2016-03-26 18:02:05 -04006 "github.com/rackspace/gophercloud"
7 "github.com/rackspace/gophercloud/pagination"
8)
9
Brad Isone7d6dfc2016-04-06 14:55:07 -040010// Validation errors returned by create or update operations.
11var (
Brad Ison4d1a9a62016-04-07 21:31:52 -040012 ErrNoName = errors.New("Policy name cannot by empty.")
13 ErrNoArgs = errors.New("Args cannot be nil for schedule policies.")
14 ErrInvalidAdjustment = errors.New("Invalid adjustment type.")
Brad Isone7d6dfc2016-04-06 14:55:07 -040015)
16
Brad Ison53e997c2016-03-26 18:02:05 -040017// List returns all scaling policies for a group.
18func List(client *gophercloud.ServiceClient, groupID string) pagination.Pager {
19 url := listURL(client, groupID)
20
21 createPageFn := func(r pagination.PageResult) pagination.Page {
22 return PolicyPage{pagination.SinglePageBase(r)}
23 }
24
25 return pagination.NewPager(client, url, createPageFn)
26}
Brad Isone7d6dfc2016-04-06 14:55:07 -040027
28// CreateOptsBuilder is the interface responsible for generating the map that
29// will be marshalled to JSON for a Create operation.
30type CreateOptsBuilder interface {
31 ToPolicyCreateMap() ([]map[string]interface{}, error)
32}
33
34// Adjustment represents the change in capacity associated with a policy.
35type Adjustment struct {
36 // The type for this adjustment.
37 Type AdjustmentType
38
39 // The value of the adjustment. For adjustments of type Change or
40 // DesiredCapacity, this will be converted to an integer.
41 Value float64
42}
43
44// AdjustmentType represents the way in which a policy will change a group.
45type AdjustmentType string
46
47// Valid types of adjustments for a policy.
48const (
49 Change AdjustmentType = "change"
50 ChangePercent AdjustmentType = "changePercent"
51 DesiredCapacity AdjustmentType = "desiredCapacity"
52)
53
54// CreateOpts is a slice of CreateOpt structs that allow the user to create
55// multiple policies in a single operation.
56type CreateOpts []CreateOpt
57
58// CreateOpt represents the options to create a policy.
59type CreateOpt struct {
60 // Name [required] is a name for the policy.
61 Name string
62
63 // Type [required] of policy, i.e. either "webhook" or "schedule".
64 Type Type
65
66 // Cooldown [required] period in seconds.
67 Cooldown int
68
69 // Adjustment [requried] type and value for the policy.
70 Adjustment Adjustment
71
72 // Additional configuration options for some types of policy.
73 Args map[string]interface{}
74}
75
76// ToPolicyCreateMap converts a slice of CreateOpt structs into a map for use
77// in the request body of a Create operation.
78func (opts CreateOpts) ToPolicyCreateMap() ([]map[string]interface{}, error) {
79 var policies []map[string]interface{}
80
81 for _, o := range opts {
82 if o.Name == "" {
83 return nil, ErrNoName
84 }
85
86 if o.Type == Schedule && o.Args == nil {
87 return nil, ErrNoArgs
88 }
89
90 policy := make(map[string]interface{})
91
92 policy["name"] = o.Name
93 policy["type"] = o.Type
94 policy["cooldown"] = o.Cooldown
95
Brad Ison4d1a9a62016-04-07 21:31:52 -040096 if err := setAdjustment(o.Adjustment, policy); err != nil {
97 return nil, err
98 }
Brad Isone7d6dfc2016-04-06 14:55:07 -040099
100 if o.Args != nil {
101 policy["args"] = o.Args
102 }
103
104 policies = append(policies, policy)
105 }
106
107 return policies, nil
108}
109
110// Create requests a new policy be created and associated with the given group.
111func Create(client *gophercloud.ServiceClient, groupID string, opts CreateOptsBuilder) CreateResult {
112 var res CreateResult
113
114 reqBody, err := opts.ToPolicyCreateMap()
115
116 if err != nil {
117 res.Err = err
118 return res
119 }
120
121 _, res.Err = client.Post(createURL(client, groupID), reqBody, &res.Body, nil)
122
123 return res
124}
Brad Ison55523e52016-04-06 19:25:20 -0400125
126// Get requests the details of a single policy with the given ID.
127func Get(client *gophercloud.ServiceClient, groupID, policyID string) GetResult {
128 var result GetResult
129
130 _, result.Err = client.Get(getURL(client, groupID, policyID), &result.Body, nil)
131
132 return result
133}
Brad Isonac037d52016-04-07 19:41:29 -0400134
135// UpdateOptsBuilder is the interface responsible for generating the map
136// structure for producing JSON for an Update operation.
137type UpdateOptsBuilder interface {
138 ToPolicyUpdateMap() (map[string]interface{}, error)
139}
140
141// UpdateOpts represents the options for updating an existing policy.
142//
143// Update operations completely replace the configuration being updated. Empty
144// values in the update are accepted and overwrite previously specified
145// parameters.
146type UpdateOpts struct {
147 // Name [required] is a name for the policy.
148 Name string
149
150 // Type [required] of policy, i.e. either "webhook" or "schedule".
151 Type Type
152
153 // Cooldown [required] period in seconds. If you don't specify a cooldown,
154 // it will default to zero, and the policy will be configured as such.
155 Cooldown int
156
157 // Adjustment [requried] type and value for the policy.
158 Adjustment Adjustment
159
160 // Additional configuration options for some types of policy.
161 Args map[string]interface{}
162}
163
164// ToPolicyUpdateMap converts an UpdateOpts struct into a map for use as the
165// request body in an Update request.
166func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
167 if opts.Name == "" {
168 return nil, ErrNoName
169 }
170
171 if opts.Type == Schedule && opts.Args == nil {
172 return nil, ErrNoArgs
173 }
174
175 policy := make(map[string]interface{})
176
177 policy["name"] = opts.Name
178 policy["type"] = opts.Type
179 policy["cooldown"] = opts.Cooldown
180
Brad Ison4d1a9a62016-04-07 21:31:52 -0400181 if err := setAdjustment(opts.Adjustment, policy); err != nil {
182 return nil, err
183 }
Brad Isonac037d52016-04-07 19:41:29 -0400184
185 if opts.Args != nil {
186 policy["args"] = opts.Args
187 }
188
189 return policy, nil
190}
191
192// Update requests the configuration of the given policy be updated.
193func Update(client *gophercloud.ServiceClient, groupID, policyID string, opts UpdateOptsBuilder) UpdateResult {
194 var result UpdateResult
195
196 url := updateURL(client, groupID, policyID)
197 reqBody, err := opts.ToPolicyUpdateMap()
198
199 if err != nil {
200 result.Err = err
201 return result
202 }
203
204 _, result.Err = client.Put(url, reqBody, nil, &gophercloud.RequestOpts{
205 OkCodes: []int{204},
206 })
207
208 return result
209}
Brad Ison124df8e2016-04-07 19:51:51 -0400210
211// Delete requests the given policy be permanently deleted.
212func Delete(client *gophercloud.ServiceClient, groupID, policyID string) DeleteResult {
213 var result DeleteResult
214
215 url := deleteURL(client, groupID, policyID)
216 _, result.Err = client.Delete(url, &gophercloud.RequestOpts{
217 OkCodes: []int{204},
218 })
219
220 return result
221}
Brad Ison42f8dfb2016-04-07 20:26:06 -0400222
223// Execute requests the given policy be executed immediately.
224func Execute(client *gophercloud.ServiceClient, groupID, policyID string) ExecuteResult {
225 var result ExecuteResult
226
227 url := executeURL(client, groupID, policyID)
228 _, result.Err = client.Post(url, nil, &result.Body, &gophercloud.RequestOpts{
229 OkCodes: []int{202},
230 })
231
232 return result
233}
Brad Ison4d1a9a62016-04-07 21:31:52 -0400234
235// Validate and set an adjustment on the given request body.
236func setAdjustment(adjustment Adjustment, reqBody map[string]interface{}) error {
237 key := string(adjustment.Type)
238
239 switch adjustment.Type {
240 case ChangePercent:
241 reqBody[key] = adjustment.Value
242
243 case Change, DesiredCapacity:
244 reqBody[key] = int(adjustment.Value)
245
246 default:
247 return ErrInvalidAdjustment
248 }
249
250 return nil
251}