Add ScheduleArgs interface for autoscale policies
diff --git a/rackspace/autoscale/v1/policies/fixtures.go b/rackspace/autoscale/v1/policies/fixtures.go
index 67967b0..9334740 100644
--- a/rackspace/autoscale/v1/policies/fixtures.go
+++ b/rackspace/autoscale/v1/policies/fixtures.go
@@ -6,6 +6,7 @@
"fmt"
"net/http"
"testing"
+ "time"
th "github.com/rackspace/gophercloud/testhelper"
"github.com/rackspace/gophercloud/testhelper/client"
@@ -81,7 +82,7 @@
"cooldown": 0,
"name": "one time",
"args": {
- "at": "2020-04-01T23:00:00.000Z"
+ "at": "2020-04-01T23:00:00Z"
},
"type": "schedule",
"change": -1
@@ -145,9 +146,7 @@
Type: Schedule,
AdjustmentType: Change,
AdjustmentValue: float64(-1),
- Args: map[string]interface{}{
- "at": "2020-04-01T23:00:00.000Z",
- },
+ Schedule: At(time.Date(2020, time.April, 01, 23, 0, 0, 0, time.UTC)),
}
// SundayAfternoonPolicy is a Policy corresponding to the third result in PolicyListBody.
@@ -157,9 +156,7 @@
Type: Schedule,
AdjustmentType: DesiredCapacity,
AdjustmentValue: float64(2),
- Args: map[string]interface{}{
- "cron": "59 15 * * 0",
- },
+ Schedule: Cron("59 15 * * 0"),
}
)
diff --git a/rackspace/autoscale/v1/policies/requests.go b/rackspace/autoscale/v1/policies/requests.go
index 52061a1..7aadf98 100644
--- a/rackspace/autoscale/v1/policies/requests.go
+++ b/rackspace/autoscale/v1/policies/requests.go
@@ -9,11 +9,12 @@
// Validation errors returned by create or update operations.
var (
- ErrNoName = errors.New("Policy name cannot by empty.")
- ErrNoArgs = errors.New("Args cannot be nil for schedule policies.")
+ ErrNoName = errors.New("Policy name cannot be empty.")
+ ErrNoSchedule = errors.New("Schedule cannot be nil for schedule policies.")
ErrCooldownRange = errors.New("Cooldown is out of range (0, 86400).")
ErrUnknownType = errors.New("Unknown policy type.")
ErrUnknownAdjustment = errors.New("Unknown adjustment type.")
+ ErrEmptyCron = errors.New("Cron argument cannot be empty.")
)
// List returns all scaling policies for a group.
@@ -57,8 +58,9 @@
// an integer.
AdjustmentValue float64
- // Additional configuration options for some types of policy.
- Args map[string]interface{}
+ // Value determining Schedule policy behavior, or nil for Webhook policies.
+ // This should be an appropriately configured Cron or an At value.
+ Schedule ScheduleArgs
}
// ToPolicyCreateMap converts a slice of CreateOpt structs into a map for use
@@ -71,8 +73,8 @@
return nil, ErrNoName
}
- if o.Type == Schedule && o.Args == nil {
- return nil, ErrNoArgs
+ if o.Type == Schedule && o.Schedule == nil {
+ return nil, ErrNoSchedule
}
if ok := validateType(o.Type); !ok {
@@ -95,8 +97,14 @@
return nil, err
}
- if o.Args != nil {
- policy["args"] = o.Args
+ if o.Schedule != nil {
+ args, err := o.Schedule.ToPolicyArgs()
+
+ if err != nil {
+ return nil, err
+ }
+
+ policy["args"] = args
}
policies = append(policies, policy)
@@ -161,8 +169,9 @@
// an integer.
AdjustmentValue float64
- // Additional configuration options for some types of policy.
- Args map[string]interface{}
+ // Value determining Schedule policy behavior, or nil for Webhook policies.
+ // This should be an appropriately configured Cron or an At value.
+ Schedule ScheduleArgs
}
// ToPolicyUpdateMap converts an UpdateOpts struct into a map for use as the
@@ -172,8 +181,8 @@
return nil, ErrNoName
}
- if opts.Type == Schedule && opts.Args == nil {
- return nil, ErrNoArgs
+ if opts.Type == Schedule && opts.Schedule == nil {
+ return nil, ErrNoSchedule
}
if ok := validateType(opts.Type); !ok {
@@ -196,8 +205,14 @@
return nil, err
}
- if opts.Args != nil {
- policy["args"] = opts.Args
+ if opts.Schedule != nil {
+ args, err := opts.Schedule.ToPolicyArgs()
+
+ if err != nil {
+ return nil, err
+ }
+
+ policy["args"] = args
}
return policy, nil
diff --git a/rackspace/autoscale/v1/policies/requests_test.go b/rackspace/autoscale/v1/policies/requests_test.go
index 3f7bb88..88a52a7 100644
--- a/rackspace/autoscale/v1/policies/requests_test.go
+++ b/rackspace/autoscale/v1/policies/requests_test.go
@@ -2,6 +2,7 @@
import (
"testing"
+ "time"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
@@ -53,6 +54,7 @@
defer th.TeardownHTTP()
HandlePolicyCreateSuccessfully(t)
+ oneTime := time.Date(2020, time.April, 01, 23, 0, 0, 0, time.UTC)
client := client.ServiceClient()
opts := CreateOpts{
{
@@ -67,18 +69,14 @@
Type: Schedule,
AdjustmentType: Change,
AdjustmentValue: -1,
- Args: map[string]interface{}{
- "at": "2020-04-01T23:00:00.000Z",
- },
+ Schedule: At(oneTime),
},
{
Name: "sunday afternoon",
Type: Schedule,
AdjustmentType: DesiredCapacity,
AdjustmentValue: 2,
- Args: map[string]interface{}{
- "cron": "59 15 * * 0",
- },
+ Schedule: Cron("59 15 * * 0"),
},
}
diff --git a/rackspace/autoscale/v1/policies/results.go b/rackspace/autoscale/v1/policies/results.go
index 95d03ca..99d8b1a 100644
--- a/rackspace/autoscale/v1/policies/results.go
+++ b/rackspace/autoscale/v1/policies/results.go
@@ -1,6 +1,8 @@
package policies
import (
+ "time"
+
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
@@ -87,6 +89,44 @@
DesiredCapacity AdjustmentType = "desiredCapacity"
)
+// ScheduleArgs is implemented by types that can be converted into arguments for
+// policies with type Schedule.
+type ScheduleArgs interface {
+ ToPolicyArgs() (map[string]string, error)
+}
+
+// At satisfies the ScheduleArgs interface and can be used to configure a policy
+// to execute a particular time.
+type At time.Time
+
+// ToPolicyArgs returns a key and value for use in constructing arguments to
+// schedule policies.
+func (at At) ToPolicyArgs() (map[string]string, error) {
+ t := time.Time(at)
+
+ args := make(map[string]string)
+ args["at"] = t.UTC().Format(time.RFC3339)
+
+ return args, nil
+}
+
+// Cron satisfies the ScheduleArgs interface and can be used to configure a
+// policy that executes at regular intervals.
+type Cron string
+
+// ToPolicyArgs returns a key and value for use in constructing arguments to
+// schedule policies.
+func (cron Cron) ToPolicyArgs() (map[string]string, error) {
+ if cron == "" {
+ return nil, ErrEmptyCron
+ }
+
+ args := make(map[string]string)
+ args["cron"] = string(cron)
+
+ return args, nil
+}
+
// Policy represents a scaling policy.
type Policy struct {
// UUID for the policy.
@@ -107,8 +147,9 @@
// The numeric value of the adjustment in capacity.
AdjustmentValue float64
- // Additional configuration options for some types of policy.
- Args map[string]interface{}
+ // Arguments determining Schedule policy behavior, or nil for Webhook
+ // policies.
+ Schedule ScheduleArgs
}
// This is an intermediate representation of the exported Policy type. The
@@ -126,7 +167,7 @@
DesiredCapacity interface{} `mapstructure:"desiredCapacity"`
// Additional configuration options for schedule policies.
- Args map[string]interface{} `mapstructure:"args"`
+ Args map[string]string `mapstructure:"args"`
}
// Assemble a Policy from the intermediate policy struct.
@@ -138,7 +179,14 @@
policy.Type = p.Type
policy.Cooldown = p.Cooldown
- policy.Args = p.Args
+ if cron, ok := p.Args["cron"]; ok {
+ policy.Schedule = Cron(cron)
+ } else if at, ok := p.Args["at"]; ok {
+ // Set an At schedule if the "at" argument parses as an RFC3339 time.
+ if t, err := time.Parse(time.RFC3339, at); err == nil {
+ policy.Schedule = At(t)
+ }
+ }
if v, ok := p.Change.(float64); ok {
policy.AdjustmentType = Change