Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit a06e2ca

Browse files
committed
Add ScheduleArgs interface for autoscale policies
1 parent eedc8d9 commit a06e2ca

File tree

4 files changed

+89
-31
lines changed

4 files changed

+89
-31
lines changed

rackspace/autoscale/v1/policies/fixtures.go

+4-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"net/http"
88
"testing"
9+
"time"
910

1011
th "github.com/rackspace/gophercloud/testhelper"
1112
"github.com/rackspace/gophercloud/testhelper/client"
@@ -81,7 +82,7 @@ const PolicyCreateRequest = `
8182
"cooldown": 0,
8283
"name": "one time",
8384
"args": {
84-
"at": "2020-04-01T23:00:00.000Z"
85+
"at": "2020-04-01T23:00:00Z"
8586
},
8687
"type": "schedule",
8788
"change": -1
@@ -145,9 +146,7 @@ var (
145146
Type: Schedule,
146147
AdjustmentType: Change,
147148
AdjustmentValue: float64(-1),
148-
Args: map[string]interface{}{
149-
"at": "2020-04-01T23:00:00.000Z",
150-
},
149+
Schedule: At(time.Date(2020, time.April, 01, 23, 0, 0, 0, time.UTC)),
151150
}
152151

153152
// SundayAfternoonPolicy is a Policy corresponding to the third result in PolicyListBody.
@@ -157,9 +156,7 @@ var (
157156
Type: Schedule,
158157
AdjustmentType: DesiredCapacity,
159158
AdjustmentValue: float64(2),
160-
Args: map[string]interface{}{
161-
"cron": "59 15 * * 0",
162-
},
159+
Schedule: Cron("59 15 * * 0"),
163160
}
164161
)
165162

rackspace/autoscale/v1/policies/requests.go

+29-14
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import (
99

1010
// Validation errors returned by create or update operations.
1111
var (
12-
ErrNoName = errors.New("Policy name cannot by empty.")
13-
ErrNoArgs = errors.New("Args cannot be nil for schedule policies.")
12+
ErrNoName = errors.New("Policy name cannot be empty.")
13+
ErrNoSchedule = errors.New("Schedule cannot be nil for schedule policies.")
1414
ErrCooldownRange = errors.New("Cooldown is out of range (0, 86400).")
1515
ErrUnknownType = errors.New("Unknown policy type.")
1616
ErrUnknownAdjustment = errors.New("Unknown adjustment type.")
17+
ErrEmptyCron = errors.New("Cron argument cannot be empty.")
1718
)
1819

1920
// List returns all scaling policies for a group.
@@ -57,8 +58,9 @@ type CreateOpt struct {
5758
// an integer.
5859
AdjustmentValue float64
5960

60-
// Additional configuration options for some types of policy.
61-
Args map[string]interface{}
61+
// Value determining Schedule policy behavior, or nil for Webhook policies.
62+
// This should be an appropriately configured Cron or an At value.
63+
Schedule ScheduleArgs
6264
}
6365

6466
// ToPolicyCreateMap converts a slice of CreateOpt structs into a map for use
@@ -71,8 +73,8 @@ func (opts CreateOpts) ToPolicyCreateMap() ([]map[string]interface{}, error) {
7173
return nil, ErrNoName
7274
}
7375

74-
if o.Type == Schedule && o.Args == nil {
75-
return nil, ErrNoArgs
76+
if o.Type == Schedule && o.Schedule == nil {
77+
return nil, ErrNoSchedule
7678
}
7779

7880
if ok := validateType(o.Type); !ok {
@@ -95,8 +97,14 @@ func (opts CreateOpts) ToPolicyCreateMap() ([]map[string]interface{}, error) {
9597
return nil, err
9698
}
9799

98-
if o.Args != nil {
99-
policy["args"] = o.Args
100+
if o.Schedule != nil {
101+
args, err := o.Schedule.ToPolicyArgs()
102+
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
policy["args"] = args
100108
}
101109

102110
policies = append(policies, policy)
@@ -161,8 +169,9 @@ type UpdateOpts struct {
161169
// an integer.
162170
AdjustmentValue float64
163171

164-
// Additional configuration options for some types of policy.
165-
Args map[string]interface{}
172+
// Value determining Schedule policy behavior, or nil for Webhook policies.
173+
// This should be an appropriately configured Cron or an At value.
174+
Schedule ScheduleArgs
166175
}
167176

168177
// ToPolicyUpdateMap converts an UpdateOpts struct into a map for use as the
@@ -172,8 +181,8 @@ func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
172181
return nil, ErrNoName
173182
}
174183

175-
if opts.Type == Schedule && opts.Args == nil {
176-
return nil, ErrNoArgs
184+
if opts.Type == Schedule && opts.Schedule == nil {
185+
return nil, ErrNoSchedule
177186
}
178187

179188
if ok := validateType(opts.Type); !ok {
@@ -196,8 +205,14 @@ func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
196205
return nil, err
197206
}
198207

199-
if opts.Args != nil {
200-
policy["args"] = opts.Args
208+
if opts.Schedule != nil {
209+
args, err := opts.Schedule.ToPolicyArgs()
210+
211+
if err != nil {
212+
return nil, err
213+
}
214+
215+
policy["args"] = args
201216
}
202217

203218
return policy, nil

rackspace/autoscale/v1/policies/requests_test.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package policies
22

33
import (
44
"testing"
5+
"time"
56

67
"github.com/rackspace/gophercloud/pagination"
78
th "github.com/rackspace/gophercloud/testhelper"
@@ -53,6 +54,7 @@ func TestCreate(t *testing.T) {
5354
defer th.TeardownHTTP()
5455
HandlePolicyCreateSuccessfully(t)
5556

57+
oneTime := time.Date(2020, time.April, 01, 23, 0, 0, 0, time.UTC)
5658
client := client.ServiceClient()
5759
opts := CreateOpts{
5860
{
@@ -67,18 +69,14 @@ func TestCreate(t *testing.T) {
6769
Type: Schedule,
6870
AdjustmentType: Change,
6971
AdjustmentValue: -1,
70-
Args: map[string]interface{}{
71-
"at": "2020-04-01T23:00:00.000Z",
72-
},
72+
Schedule: At(oneTime),
7373
},
7474
{
7575
Name: "sunday afternoon",
7676
Type: Schedule,
7777
AdjustmentType: DesiredCapacity,
7878
AdjustmentValue: 2,
79-
Args: map[string]interface{}{
80-
"cron": "59 15 * * 0",
81-
},
79+
Schedule: Cron("59 15 * * 0"),
8280
},
8381
}
8482

rackspace/autoscale/v1/policies/results.go

+52-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package policies
22

33
import (
4+
"time"
5+
46
"github.com/mitchellh/mapstructure"
57

68
"github.com/rackspace/gophercloud"
@@ -87,6 +89,44 @@ const (
8789
DesiredCapacity AdjustmentType = "desiredCapacity"
8890
)
8991

92+
// ScheduleArgs is implemented by types that can be converted into arguments for
93+
// policies with type Schedule.
94+
type ScheduleArgs interface {
95+
ToPolicyArgs() (map[string]string, error)
96+
}
97+
98+
// At satisfies the ScheduleArgs interface and can be used to configure a policy
99+
// to execute a particular time.
100+
type At time.Time
101+
102+
// ToPolicyArgs returns a key and value for use in constructing arguments to
103+
// schedule policies.
104+
func (at At) ToPolicyArgs() (map[string]string, error) {
105+
t := time.Time(at)
106+
107+
args := make(map[string]string)
108+
args["at"] = t.UTC().Format(time.RFC3339)
109+
110+
return args, nil
111+
}
112+
113+
// Cron satisfies the ScheduleArgs interface and can be used to configure a
114+
// policy that executes at regular intervals.
115+
type Cron string
116+
117+
// ToPolicyArgs returns a key and value for use in constructing arguments to
118+
// schedule policies.
119+
func (cron Cron) ToPolicyArgs() (map[string]string, error) {
120+
if cron == "" {
121+
return nil, ErrEmptyCron
122+
}
123+
124+
args := make(map[string]string)
125+
args["cron"] = string(cron)
126+
127+
return args, nil
128+
}
129+
90130
// Policy represents a scaling policy.
91131
type Policy struct {
92132
// UUID for the policy.
@@ -107,8 +147,9 @@ type Policy struct {
107147
// The numeric value of the adjustment in capacity.
108148
AdjustmentValue float64
109149

110-
// Additional configuration options for some types of policy.
111-
Args map[string]interface{}
150+
// Arguments determining Schedule policy behavior, or nil for Webhook
151+
// policies.
152+
Schedule ScheduleArgs
112153
}
113154

114155
// This is an intermediate representation of the exported Policy type. The
@@ -126,7 +167,7 @@ type policy struct {
126167
DesiredCapacity interface{} `mapstructure:"desiredCapacity"`
127168

128169
// Additional configuration options for schedule policies.
129-
Args map[string]interface{} `mapstructure:"args"`
170+
Args map[string]string `mapstructure:"args"`
130171
}
131172

132173
// Assemble a Policy from the intermediate policy struct.
@@ -138,7 +179,14 @@ func (p policy) toExported() Policy {
138179
policy.Type = p.Type
139180
policy.Cooldown = p.Cooldown
140181

141-
policy.Args = p.Args
182+
if cron, ok := p.Args["cron"]; ok {
183+
policy.Schedule = Cron(cron)
184+
} else if at, ok := p.Args["at"]; ok {
185+
// Set an At schedule if the "at" argument parses as an RFC3339 time.
186+
if t, err := time.Parse(time.RFC3339, at); err == nil {
187+
policy.Schedule = At(t)
188+
}
189+
}
142190

143191
if v, ok := p.Change.(float64); ok {
144192
policy.AdjustmentType = Change

0 commit comments

Comments
 (0)