blob: 95d03caf1c2951221ded6ebe84c3fb761364f8ce [file] [log] [blame]
package policies
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type policyResult struct {
gophercloud.Result
}
// Extract interprets any policyResult as a Policy, if possible.
func (r policyResult) Extract() (*Policy, error) {
if r.Err != nil {
return nil, r.Err
}
var response struct {
Policy policy `mapstructure:"policy"`
}
if err := mapstructure.Decode(r.Body, &response); err != nil {
return nil, err
}
policy := response.Policy.toExported()
return &policy, nil
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
policyResult
}
// Extract extracts a slice of Policies from a CreateResult. Multiple policies
// can be created in a single operation, so the result of a create is always a
// list of policies.
func (res CreateResult) Extract() ([]Policy, error) {
if res.Err != nil {
return nil, res.Err
}
return commonExtractPolicies(res.Body)
}
// GetResult temporarily contains the response from a Get call.
type GetResult struct {
policyResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
gophercloud.ErrResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// ExecuteResult represents the result of an execute operation.
type ExecuteResult struct {
gophercloud.ErrResult
}
// Type represents a type of scaling policy.
type Type string
const (
// Schedule policies run at given times.
Schedule Type = "schedule"
// Webhook policies are triggered by HTTP requests.
Webhook Type = "webhook"
)
// AdjustmentType represents the way in which a policy will change a group.
type AdjustmentType string
// Valid types of adjustments for a policy.
const (
Change AdjustmentType = "change"
ChangePercent AdjustmentType = "changePercent"
DesiredCapacity AdjustmentType = "desiredCapacity"
)
// Policy represents a scaling policy.
type Policy struct {
// UUID for the policy.
ID string
// Name of the policy.
Name string
// Type of scaling policy.
Type Type
// Cooldown period, in seconds.
Cooldown int
// The type of adjustment in capacity to be made.
AdjustmentType AdjustmentType
// The numeric value of the adjustment in capacity.
AdjustmentValue float64
// Additional configuration options for some types of policy.
Args map[string]interface{}
}
// This is an intermediate representation of the exported Policy type. The
// fields in API responses vary by policy type and configuration. This lets us
// decode responses then normalize them into a Policy.
type policy struct {
ID string `mapstructure:"id"`
Name string `mapstructure:"name"`
Type Type `mapstructure:"type"`
Cooldown int `mapstructure:"cooldown"`
// The API will respond with exactly one of these omitting the others.
Change interface{} `mapstructure:"change"`
ChangePercent interface{} `mapstructure:"changePercent"`
DesiredCapacity interface{} `mapstructure:"desiredCapacity"`
// Additional configuration options for schedule policies.
Args map[string]interface{} `mapstructure:"args"`
}
// Assemble a Policy from the intermediate policy struct.
func (p policy) toExported() Policy {
policy := Policy{}
policy.ID = p.ID
policy.Name = p.Name
policy.Type = p.Type
policy.Cooldown = p.Cooldown
policy.Args = p.Args
if v, ok := p.Change.(float64); ok {
policy.AdjustmentType = Change
policy.AdjustmentValue = v
} else if v, ok := p.ChangePercent.(float64); ok {
policy.AdjustmentType = ChangePercent
policy.AdjustmentValue = v
} else if v, ok := p.DesiredCapacity.(float64); ok {
policy.AdjustmentType = DesiredCapacity
policy.AdjustmentValue = v
}
return policy
}
// PolicyPage is the page returned by a pager when traversing over a collection
// of scaling policies.
type PolicyPage struct {
pagination.SinglePageBase
}
// IsEmpty returns true if a page contains no Policy results.
func (page PolicyPage) IsEmpty() (bool, error) {
policies, err := ExtractPolicies(page)
if err != nil {
return true, err
}
return len(policies) == 0, nil
}
// ExtractPolicies interprets the results of a single page from a List() call,
// producing a slice of Policies.
func ExtractPolicies(page pagination.Page) ([]Policy, error) {
return commonExtractPolicies(page.(PolicyPage).Body)
}
func commonExtractPolicies(body interface{}) ([]Policy, error) {
var response struct {
Policies []policy `mapstructure:"policies"`
}
err := mapstructure.Decode(body, &response)
if err != nil {
return nil, err
}
policies := make([]Policy, len(response.Policies))
for i, p := range response.Policies {
policies[i] = p.toExported()
}
return policies, nil
}