@ -1,11 +1,13 @@
package aws
import (
"bytes"
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
@ -35,17 +37,59 @@ func resourceAwsAutoscalingPolicy() *schema.Resource {
Required : true ,
ForceNew : true ,
} ,
"policy_type" : & schema . Schema {
Type : schema . TypeString ,
Optional : true ,
Default : "SimpleScaling" , // preserve AWS's default to make validation easier.
} ,
"cooldown" : & schema . Schema {
Type : schema . TypeInt ,
Optional : true ,
} ,
"min_adjustment_step" : & schema . Schema {
" estimated_instance_warmu p": & schema . Schema {
Type : schema . TypeInt ,
Optional : true ,
} ,
"scaling_adjustment" : & schema . Schema {
"metric_aggregation_type" : & schema . Schema {
Type : schema . TypeString ,
Optional : true ,
} ,
"min_adjustment_magnitude" : & schema . Schema {
Type : schema . TypeInt ,
Required : true ,
Optional : true ,
} ,
"min_adjustment_step" : & schema . Schema {
Type : schema . TypeInt ,
Optional : true ,
Deprecated : "Use min_adjustment_magnitude instead." ,
ConflictsWith : [ ] string { "min_adjustment_magnitude" } ,
} ,
"scaling_adjustment" : & schema . Schema {
Type : schema . TypeInt ,
Optional : true ,
ConflictsWith : [ ] string { "step_adjustment" } ,
} ,
"step_adjustment" : & schema . Schema {
Type : schema . TypeSet ,
Optional : true ,
ConflictsWith : [ ] string { "scaling_adjustment" } ,
Elem : & schema . Resource {
Schema : map [ string ] * schema . Schema {
"metric_interval_lower_bound" : & schema . Schema {
Type : schema . TypeString ,
Optional : true ,
} ,
"metric_interval_upper_bound" : & schema . Schema {
Type : schema . TypeString ,
Optional : true ,
} ,
"scaling_adjustment" : & schema . Schema {
Type : schema . TypeInt ,
Required : true ,
} ,
} ,
} ,
Set : resourceAwsAutoscalingScalingAdjustmentHash ,
} ,
} ,
}
@ -54,7 +98,10 @@ func resourceAwsAutoscalingPolicy() *schema.Resource {
func resourceAwsAutoscalingPolicyCreate ( d * schema . ResourceData , meta interface { } ) error {
autoscalingconn := meta . ( * AWSClient ) . autoscalingconn
params := getAwsAutoscalingPutScalingPolicyInput ( d )
params , err := getAwsAutoscalingPutScalingPolicyInput ( d )
if err != nil {
return err
}
log . Printf ( "[DEBUG] AutoScaling PutScalingPolicy: %#v" , params )
resp , err := autoscalingconn . PutScalingPolicy ( & params )
@ -84,10 +131,15 @@ func resourceAwsAutoscalingPolicyRead(d *schema.ResourceData, meta interface{})
d . Set ( "adjustment_type" , p . AdjustmentType )
d . Set ( "autoscaling_group_name" , p . AutoScalingGroupName )
d . Set ( "cooldown" , p . Cooldown )
d . Set ( "estimated_instance_warmup" , p . EstimatedInstanceWarmup )
d . Set ( "metric_aggregation_type" , p . MetricAggregationType )
d . Set ( "policy_type" , p . PolicyType )
d . Set ( "min_adjustment_magnitude" , p . MinAdjustmentMagnitude )
d . Set ( "min_adjustment_step" , p . MinAdjustmentStep )
d . Set ( "arn" , p . PolicyARN )
d . Set ( "name" , p . PolicyName )
d . Set ( "scaling_adjustment" , p . ScalingAdjustment )
d . Set ( "step_adjustment" , flattenStepAdjustments ( p . StepAdjustments ) )
return nil
}
@ -95,7 +147,10 @@ func resourceAwsAutoscalingPolicyRead(d *schema.ResourceData, meta interface{})
func resourceAwsAutoscalingPolicyUpdate ( d * schema . ResourceData , meta interface { } ) error {
autoscalingconn := meta . ( * AWSClient ) . autoscalingconn
params := getAwsAutoscalingPutScalingPolicyInput ( d )
params , inputErr := getAwsAutoscalingPutScalingPolicyInput ( d )
if inputErr != nil {
return inputErr
}
log . Printf ( "[DEBUG] Autoscaling Update Scaling Policy: %#v" , params )
_ , err := autoscalingconn . PutScalingPolicy ( & params )
@ -128,8 +183,10 @@ func resourceAwsAutoscalingPolicyDelete(d *schema.ResourceData, meta interface{}
return nil
}
// PutScalingPolicy seems to require all params to be resent, so create and update can share this common function
func getAwsAutoscalingPutScalingPolicyInput ( d * schema . ResourceData ) autoscaling . PutScalingPolicyInput {
// PutScalingPolicy can safely resend all parameters without destroying the
// resource, so create and update can share this common function. It will error
// if certain mutually exclusive values are set.
func getAwsAutoscalingPutScalingPolicyInput ( d * schema . ResourceData ) ( autoscaling . PutScalingPolicyInput , error ) {
var params = autoscaling . PutScalingPolicyInput {
AutoScalingGroupName : aws . String ( d . Get ( "autoscaling_group_name" ) . ( string ) ) ,
PolicyName : aws . String ( d . Get ( "name" ) . ( string ) ) ,
@ -143,15 +200,59 @@ func getAwsAutoscalingPutScalingPolicyInput(d *schema.ResourceData) autoscaling.
params . Cooldown = aws . Int64 ( int64 ( v . ( int ) ) )
}
if v , ok := d . GetOk ( "estimated_instance_warmup" ) ; ok {
params . EstimatedInstanceWarmup = aws . Int64 ( int64 ( v . ( int ) ) )
}
if v , ok := d . GetOk ( "metric_aggregation_type" ) ; ok {
params . MetricAggregationType = aws . String ( v . ( string ) )
}
if v , ok := d . GetOk ( "policy_type" ) ; ok {
params . PolicyType = aws . String ( v . ( string ) )
}
if v , ok := d . GetOk ( "scaling_adjustment" ) ; ok {
params . ScalingAdjustment = aws . Int64 ( int64 ( v . ( int ) ) )
}
if v , ok := d . GetOk ( "step_adjustment" ) ; ok {
steps , err := expandStepAdjustments ( v . ( * schema . Set ) . List ( ) )
if err != nil {
return params , fmt . Errorf ( "metric_interval_lower_bound and metric_interval_upper_bound must be strings!" )
}
params . StepAdjustments = steps
}
if v , ok := d . GetOk ( "min_adjustment_magnitude" ) ; ok {
params . MinAdjustmentMagnitude = aws . Int64 ( int64 ( v . ( int ) ) )
}
if v , ok := d . GetOk ( "min_adjustment_step" ) ; ok {
params . MinAdjustmentStep = aws . Int64 ( int64 ( v . ( int ) ) )
}
return params
// Validate our final input to confirm it won't error when sent to AWS.
// First, SimpleScaling policy types...
if * params . PolicyType == "SimpleScaling" && params . StepAdjustments != nil {
return params , fmt . Errorf ( "SimpleScaling policy types cannot use step_adjustments!" )
}
if * params . PolicyType == "SimpleScaling" && params . MetricAggregationType != nil {
return params , fmt . Errorf ( "SimpleScaling policy types cannot use metric_aggregation_type!" )
}
if * params . PolicyType == "SimpleScaling" && params . EstimatedInstanceWarmup != nil {
return params , fmt . Errorf ( "SimpleScaling policy types cannot use estimated_instance_warmup!" )
}
// Second, StepScaling policy types...
if * params . PolicyType == "StepScaling" && params . ScalingAdjustment != nil {
return params , fmt . Errorf ( "StepScaling policy types cannot use scaling_adjustment!" )
}
if * params . PolicyType == "StepScaling" && params . Cooldown != nil {
return params , fmt . Errorf ( "StepScaling policy types cannot use cooldown!" )
}
return params , nil
}
func getAwsAutoscalingPolicy ( d * schema . ResourceData , meta interface { } ) ( * autoscaling . ScalingPolicy , error ) {
@ -179,3 +280,17 @@ func getAwsAutoscalingPolicy(d *schema.ResourceData, meta interface{}) (*autosca
// policy not found
return nil , nil
}
func resourceAwsAutoscalingScalingAdjustmentHash ( v interface { } ) int {
var buf bytes . Buffer
m := v . ( map [ string ] interface { } )
if v , ok := m [ "metric_interval_lower_bound" ] ; ok {
buf . WriteString ( fmt . Sprintf ( "%f-" , v ) )
}
if v , ok := m [ "metric_interval_upper_bound" ] ; ok {
buf . WriteString ( fmt . Sprintf ( "%f-" , v ) )
}
buf . WriteString ( fmt . Sprintf ( "%d-" , m [ "scaling_adjustment" ] . ( int ) ) )
return hashcode . String ( buf . String ( ) )
}