Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/autoscaling_policy: fix conditional logic based on policy type #3739

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 86 additions & 92 deletions aws/resource_aws_autoscaling_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,151 +21,156 @@ func resourceAwsAutoscalingPolicy() *schema.Resource {
Delete: resourceAwsAutoscalingPolicyDelete,

Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"adjustment_type": &schema.Schema{
"adjustment_type": {
Type: schema.TypeString,
Optional: true,
},
"autoscaling_group_name": &schema.Schema{
"autoscaling_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"policy_type": &schema.Schema{
"policy_type": {
Type: schema.TypeString,
Optional: true,
Default: "SimpleScaling", // preserve AWS's default to make validation easier.
ValidateFunc: validation.StringInSlice([]string{
"SimpleScaling",
"StepScaling",
"TargetTrackingScaling",
}, false),
},
"cooldown": &schema.Schema{
"cooldown": {
Type: schema.TypeInt,
Optional: true,
},
"estimated_instance_warmup": &schema.Schema{
"estimated_instance_warmup": {
Type: schema.TypeInt,
Optional: true,
},
"metric_aggregation_type": &schema.Schema{
"metric_aggregation_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"min_adjustment_magnitude": &schema.Schema{
"min_adjustment_magnitude": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
},
"min_adjustment_step": &schema.Schema{
"min_adjustment_step": {
Type: schema.TypeInt,
Optional: true,
Deprecated: "Use min_adjustment_magnitude instead, otherwise you may see a perpetual diff on this resource.",
ConflictsWith: []string{"min_adjustment_magnitude"},
},
"scaling_adjustment": &schema.Schema{
"scaling_adjustment": {
Type: schema.TypeInt,
Optional: true,
ConflictsWith: []string{"step_adjustment"},
},
"step_adjustment": &schema.Schema{
"step_adjustment": {
Type: schema.TypeSet,
Optional: true,
ConflictsWith: []string{"scaling_adjustment"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"metric_interval_lower_bound": &schema.Schema{
"metric_interval_lower_bound": {
Type: schema.TypeString,
Optional: true,
},
"metric_interval_upper_bound": &schema.Schema{
"metric_interval_upper_bound": {
Type: schema.TypeString,
Optional: true,
},
"scaling_adjustment": &schema.Schema{
"scaling_adjustment": {
Type: schema.TypeInt,
Required: true,
},
},
},
Set: resourceAwsAutoscalingScalingAdjustmentHash,
},
"target_tracking_configuration": &schema.Schema{
"target_tracking_configuration": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"predefined_metric_specification": &schema.Schema{
"predefined_metric_specification": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"target_tracking_configuration.0.customized_metric_specification"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"predefined_metric_type": &schema.Schema{
"predefined_metric_type": {
Type: schema.TypeString,
Required: true,
},
"resource_label": &schema.Schema{
"resource_label": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"customized_metric_specification": &schema.Schema{
"customized_metric_specification": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"target_tracking_configuration.0.predefined_metric_specification"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"metric_dimension": &schema.Schema{
"metric_dimension": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"value": &schema.Schema{
"value": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"metric_name": &schema.Schema{
"metric_name": {
Type: schema.TypeString,
Required: true,
},
"namespace": &schema.Schema{
"namespace": {
Type: schema.TypeString,
Required: true,
},
"statistic": &schema.Schema{
"statistic": {
Type: schema.TypeString,
Required: true,
},
"unit": &schema.Schema{
"unit": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"target_value": &schema.Schema{
"target_value": {
Type: schema.TypeFloat,
Required: true,
},
"disable_scale_in": &schema.Schema{
"disable_scale_in": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Expand All @@ -181,11 +186,11 @@ func resourceAwsAutoscalingPolicyCreate(d *schema.ResourceData, meta interface{}
autoscalingconn := meta.(*AWSClient).autoscalingconn

params, err := getAwsAutoscalingPutScalingPolicyInput(d)
log.Printf("[DEBUG] AutoScaling PutScalingPolicy on Create: %#v", params)
if err != nil {
return err
}

log.Printf("[DEBUG] AutoScaling PutScalingPolicy: %#v", params)
resp, err := autoscalingconn.PutScalingPolicy(&params)
if err != nil {
return fmt.Errorf("Error putting scaling policy: %s", err)
Expand Down Expand Up @@ -236,11 +241,11 @@ func resourceAwsAutoscalingPolicyUpdate(d *schema.ResourceData, meta interface{}
autoscalingconn := meta.(*AWSClient).autoscalingconn

params, inputErr := getAwsAutoscalingPutScalingPolicyInput(d)
log.Printf("[DEBUG] AutoScaling PutScalingPolicy on Update: %#v", params)
if inputErr != nil {
return inputErr
}

log.Printf("[DEBUG] Autoscaling Update Scaling Policy: %#v", params)
_, err := autoscalingconn.PutScalingPolicy(&params)
if err != nil {
return err
Expand Down Expand Up @@ -281,95 +286,84 @@ func getAwsAutoscalingPutScalingPolicyInput(d *schema.ResourceData) (autoscaling
PolicyName: aws.String(d.Get("name").(string)),
}

if v, ok := d.GetOk("adjustment_type"); ok {
// get policy_type first as parameter support depends on policy type
policyType := d.Get("policy_type")
params.PolicyType = aws.String(policyType.(string))

// This parameter is supported if the policy type is SimpleScaling or StepScaling.
if v, ok := d.GetOk("adjustment_type"); ok && (policyType == "SimpleScaling" || policyType == "StepScaling") {
params.AdjustmentType = aws.String(v.(string))
}

// This parameter is supported if the policy type is SimpleScaling.
if v, ok := d.GetOkExists("cooldown"); ok {
// 0 is allowed as placeholder even if policyType is not supported
params.Cooldown = aws.Int64(int64(v.(int)))
if v.(int) != 0 && policyType != "SimpleScaling" {
return params, fmt.Errorf("cooldown is only supported for policy type SimpleScaling")
}
}

// This parameter is supported if the policy type is StepScaling or TargetTrackingScaling.
if v, ok := d.GetOkExists("estimated_instance_warmup"); ok {
params.EstimatedInstanceWarmup = aws.Int64(int64(v.(int)))
// 0 is NOT allowed as placeholder if policyType is not supported
if policyType == "StepScaling" || policyType == "TargetTrackingScaling" {
params.EstimatedInstanceWarmup = aws.Int64(int64(v.(int)))
}
if v.(int) != 0 && policyType != "StepScaling" && policyType != "TargetTrackingScaling" {
return params, fmt.Errorf("estimated_instance_warmup is only supported for policy type StepScaling and TargetTrackingScaling")
}
}

if v, ok := d.GetOk("metric_aggregation_type"); ok {
// This parameter is supported if the policy type is StepScaling.
if v, ok := d.GetOk("metric_aggregation_type"); ok && policyType == "StepScaling" {
params.MetricAggregationType = aws.String(v.(string))
}

if v, ok := d.GetOk("policy_type"); ok {
params.PolicyType = aws.String(v.(string))
// MinAdjustmentMagnitude is supported if the policy type is SimpleScaling or StepScaling.
// MinAdjustmentStep is available for backward compatibility. Use MinAdjustmentMagnitude instead.
if v, ok := d.GetOkExists("min_adjustment_magnitude"); ok && v.(int) != 0 && (policyType == "SimpleScaling" || policyType == "StepScaling") {
params.MinAdjustmentMagnitude = aws.Int64(int64(v.(int)))
} else if v, ok := d.GetOkExists("min_adjustment_step"); ok && v.(int) != 0 && (policyType == "SimpleScaling" || policyType == "StepScaling") {
params.MinAdjustmentStep = aws.Int64(int64(v.(int)))
}

// This parameter is required if the policy type is SimpleScaling and not supported otherwise.
//if policy_type=="SimpleScaling" then scaling_adjustment is required and 0 is allowed
if v, ok := d.GetOkExists("scaling_adjustment"); ok || *params.PolicyType == "SimpleScaling" {
params.ScalingAdjustment = aws.Int64(int64(v.(int)))
if v, ok := d.GetOkExists("scaling_adjustment"); ok {
// 0 is NOT allowed as placeholder if policyType is not supported
if policyType == "SimpleScaling" {
params.ScalingAdjustment = aws.Int64(int64(v.(int)))
}
if v.(int) != 0 && policyType != "SimpleScaling" {
return params, fmt.Errorf("scaling_adjustment is only supported for policy type SimpleScaling")
}
} else if !ok && policyType == "SimpleScaling" {
return params, fmt.Errorf("scaling_adjustment is required for policy type SimpleScaling")
}

// This parameter is required if the policy type is StepScaling and not supported otherwise.
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 len(steps) != 0 && policyType != "StepScaling" {
return params, fmt.Errorf("step_adjustment is only supported for policy type StepScaling")
}
} else if !ok && policyType == "StepScaling" {
return params, fmt.Errorf("step_adjustment is required for policy type StepScaling")
}

if v, ok := d.GetOkExists("min_adjustment_magnitude"); ok {
// params.MinAdjustmentMagnitude = aws.Int64(int64(d.Get("min_adjustment_magnitude").(int)))
params.MinAdjustmentMagnitude = aws.Int64(int64(v.(int)))
} else if v, ok := d.GetOkExists("min_adjustment_step"); ok {
// params.MinAdjustmentStep = aws.Int64(int64(d.Get("min_adjustment_step").(int)))
params.MinAdjustmentStep = aws.Int64(int64(v.(int)))
}

// This parameter is required if the policy type is TargetTrackingScaling and not supported otherwise.
if v, ok := d.GetOk("target_tracking_configuration"); ok {
params.TargetTrackingConfiguration = expandTargetTrackingConfiguration(v.([]interface{}))
}

// 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!")
}
if *params.PolicyType == "SimpleScaling" && params.TargetTrackingConfiguration != nil {
return params, fmt.Errorf("SimpleScaling policy types cannot use target_tracking_configuration!")
}

// 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!")
}
if *params.PolicyType == "StepScaling" && params.TargetTrackingConfiguration != nil {
return params, fmt.Errorf("StepScaling policy types cannot use target_tracking_configuration!")
}

// Third, TargetTrackingScaling policy types...
if *params.PolicyType == "TargetTrackingScaling" && params.AdjustmentType != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use adjustment_type!")
}
if *params.PolicyType == "TargetTrackingScaling" && params.Cooldown != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use cooldown!")
}
if *params.PolicyType == "TargetTrackingScaling" && params.MetricAggregationType != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use metric_aggregation_type!")
}
if *params.PolicyType == "TargetTrackingScaling" && params.MinAdjustmentMagnitude != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use min_adjustment_magnitude!")
}
if *params.PolicyType == "TargetTrackingScaling" && params.ScalingAdjustment != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use scaling_adjustment!")
}
if *params.PolicyType == "TargetTrackingScaling" && params.StepAdjustments != nil {
return params, fmt.Errorf("TargetTrackingScaling policy types cannot use step_adjustments!")
if policyType != "TargetTrackingScaling" {
return params, fmt.Errorf("target_tracking_configuration is only supported for policy type TargetTrackingScaling")
}
} else if !ok && policyType == "TargetTrackingScaling" {
return params, fmt.Errorf("target_tracking_configuration is required for policy type TargetTrackingScaling")
}

return params, nil
Expand Down
Loading