blob: bc7a8fef8967fa94e7f8925861a5344e1fd5bb2e [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
Brad Isone7d6dfc2016-04-06 14:55:07 -040034// CreateOpts is a slice of CreateOpt structs that allow the user to create
35// multiple policies in a single operation.
36type CreateOpts []CreateOpt
37
38// CreateOpt represents the options to create a policy.
39type CreateOpt struct {
40 // Name [required] is a name for the policy.
41 Name string
42
43 // Type [required] of policy, i.e. either "webhook" or "schedule".
44 Type Type
45
46 // Cooldown [required] period in seconds.
47 Cooldown int
48
Brad Isonb35ef6d2016-04-09 16:54:57 -040049 // AdjustmentType [requried] is the method used to change the capacity of
50 // the group, i.e. one of: Change, ChangePercent, or DesiredCapacity.
51 AdjustmentType AdjustmentType
52
53 // AdjustmentValue [required] is the numeric value of the adjustment. For
54 // adjustments of type Change or DesiredCapacity, this will be converted to
55 // an integer.
56 AdjustmentValue float64
Brad Isone7d6dfc2016-04-06 14:55:07 -040057
58 // Additional configuration options for some types of policy.
59 Args map[string]interface{}
60}
61
62// ToPolicyCreateMap converts a slice of CreateOpt structs into a map for use
63// in the request body of a Create operation.
64func (opts CreateOpts) ToPolicyCreateMap() ([]map[string]interface{}, error) {
65 var policies []map[string]interface{}
66
67 for _, o := range opts {
68 if o.Name == "" {
69 return nil, ErrNoName
70 }
71
72 if o.Type == Schedule && o.Args == nil {
73 return nil, ErrNoArgs
74 }
75
76 policy := make(map[string]interface{})
77
78 policy["name"] = o.Name
79 policy["type"] = o.Type
80 policy["cooldown"] = o.Cooldown
81
Brad Isonb35ef6d2016-04-09 16:54:57 -040082 err := setAdjustment(o.AdjustmentType, o.AdjustmentValue, policy)
83
84 if err != nil {
Brad Ison4d1a9a62016-04-07 21:31:52 -040085 return nil, err
86 }
Brad Isone7d6dfc2016-04-06 14:55:07 -040087
88 if o.Args != nil {
89 policy["args"] = o.Args
90 }
91
92 policies = append(policies, policy)
93 }
94
95 return policies, nil
96}
97
98// Create requests a new policy be created and associated with the given group.
99func Create(client *gophercloud.ServiceClient, groupID string, opts CreateOptsBuilder) CreateResult {
100 var res CreateResult
101
102 reqBody, err := opts.ToPolicyCreateMap()
103
104 if err != nil {
105 res.Err = err
106 return res
107 }
108
109 _, res.Err = client.Post(createURL(client, groupID), reqBody, &res.Body, nil)
110
111 return res
112}
Brad Ison55523e52016-04-06 19:25:20 -0400113
114// Get requests the details of a single policy with the given ID.
115func Get(client *gophercloud.ServiceClient, groupID, policyID string) GetResult {
116 var result GetResult
117
118 _, result.Err = client.Get(getURL(client, groupID, policyID), &result.Body, nil)
119
120 return result
121}
Brad Isonac037d52016-04-07 19:41:29 -0400122
123// UpdateOptsBuilder is the interface responsible for generating the map
124// structure for producing JSON for an Update operation.
125type UpdateOptsBuilder interface {
126 ToPolicyUpdateMap() (map[string]interface{}, error)
127}
128
129// UpdateOpts represents the options for updating an existing policy.
130//
131// Update operations completely replace the configuration being updated. Empty
132// values in the update are accepted and overwrite previously specified
133// parameters.
134type UpdateOpts struct {
135 // Name [required] is a name for the policy.
136 Name string
137
138 // Type [required] of policy, i.e. either "webhook" or "schedule".
139 Type Type
140
141 // Cooldown [required] period in seconds. If you don't specify a cooldown,
142 // it will default to zero, and the policy will be configured as such.
143 Cooldown int
144
Brad Isonb35ef6d2016-04-09 16:54:57 -0400145 // AdjustmentType [requried] is the method used to change the capacity of
146 // the group, i.e. one of: Change, ChangePercent, or DesiredCapacity.
147 AdjustmentType AdjustmentType
148
149 // AdjustmentValue [required] is the numeric value of the adjustment. For
150 // adjustments of type Change or DesiredCapacity, this will be converted to
151 // an integer.
152 AdjustmentValue float64
Brad Isonac037d52016-04-07 19:41:29 -0400153
154 // Additional configuration options for some types of policy.
155 Args map[string]interface{}
156}
157
158// ToPolicyUpdateMap converts an UpdateOpts struct into a map for use as the
159// request body in an Update request.
160func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
161 if opts.Name == "" {
162 return nil, ErrNoName
163 }
164
165 if opts.Type == Schedule && opts.Args == nil {
166 return nil, ErrNoArgs
167 }
168
169 policy := make(map[string]interface{})
170
171 policy["name"] = opts.Name
172 policy["type"] = opts.Type
173 policy["cooldown"] = opts.Cooldown
174
Brad Isonb35ef6d2016-04-09 16:54:57 -0400175 err := setAdjustment(opts.AdjustmentType, opts.AdjustmentValue, policy)
176
177 if err != nil {
Brad Ison4d1a9a62016-04-07 21:31:52 -0400178 return nil, err
179 }
Brad Isonac037d52016-04-07 19:41:29 -0400180
181 if opts.Args != nil {
182 policy["args"] = opts.Args
183 }
184
185 return policy, nil
186}
187
188// Update requests the configuration of the given policy be updated.
189func Update(client *gophercloud.ServiceClient, groupID, policyID string, opts UpdateOptsBuilder) UpdateResult {
190 var result UpdateResult
191
192 url := updateURL(client, groupID, policyID)
193 reqBody, err := opts.ToPolicyUpdateMap()
194
195 if err != nil {
196 result.Err = err
197 return result
198 }
199
200 _, result.Err = client.Put(url, reqBody, nil, &gophercloud.RequestOpts{
201 OkCodes: []int{204},
202 })
203
204 return result
205}
Brad Ison124df8e2016-04-07 19:51:51 -0400206
207// Delete requests the given policy be permanently deleted.
208func Delete(client *gophercloud.ServiceClient, groupID, policyID string) DeleteResult {
209 var result DeleteResult
210
211 url := deleteURL(client, groupID, policyID)
212 _, result.Err = client.Delete(url, &gophercloud.RequestOpts{
213 OkCodes: []int{204},
214 })
215
216 return result
217}
Brad Ison42f8dfb2016-04-07 20:26:06 -0400218
219// Execute requests the given policy be executed immediately.
220func Execute(client *gophercloud.ServiceClient, groupID, policyID string) ExecuteResult {
221 var result ExecuteResult
222
223 url := executeURL(client, groupID, policyID)
224 _, result.Err = client.Post(url, nil, &result.Body, &gophercloud.RequestOpts{
225 OkCodes: []int{202},
226 })
227
228 return result
229}
Brad Ison4d1a9a62016-04-07 21:31:52 -0400230
231// Validate and set an adjustment on the given request body.
Brad Isonb35ef6d2016-04-09 16:54:57 -0400232func setAdjustment(t AdjustmentType, v float64, body map[string]interface{}) error {
233 key := string(t)
Brad Ison4d1a9a62016-04-07 21:31:52 -0400234
Brad Isonb35ef6d2016-04-09 16:54:57 -0400235 switch t {
Brad Ison4d1a9a62016-04-07 21:31:52 -0400236 case ChangePercent:
Brad Isonb35ef6d2016-04-09 16:54:57 -0400237 body[key] = v
Brad Ison4d1a9a62016-04-07 21:31:52 -0400238
239 case Change, DesiredCapacity:
Brad Isonb35ef6d2016-04-09 16:54:57 -0400240 body[key] = int(v)
Brad Ison4d1a9a62016-04-07 21:31:52 -0400241
242 default:
243 return ErrInvalidAdjustment
244 }
245
246 return nil
247}