github.com/pmcatominey/terraform@v0.7.0-rc2.0.20160708105029-1401a52a5cc5/builtin/providers/aws/resource_aws_autoscaling_policy.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/service/autoscaling" 10 "github.com/hashicorp/terraform/helper/hashcode" 11 "github.com/hashicorp/terraform/helper/schema" 12 ) 13 14 func resourceAwsAutoscalingPolicy() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceAwsAutoscalingPolicyCreate, 17 Read: resourceAwsAutoscalingPolicyRead, 18 Update: resourceAwsAutoscalingPolicyUpdate, 19 Delete: resourceAwsAutoscalingPolicyDelete, 20 21 Schema: map[string]*schema.Schema{ 22 "arn": &schema.Schema{ 23 Type: schema.TypeString, 24 Computed: true, 25 }, 26 "name": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: true, 29 ForceNew: true, 30 }, 31 "adjustment_type": &schema.Schema{ 32 Type: schema.TypeString, 33 Required: true, 34 }, 35 "autoscaling_group_name": &schema.Schema{ 36 Type: schema.TypeString, 37 Required: true, 38 ForceNew: true, 39 }, 40 "policy_type": &schema.Schema{ 41 Type: schema.TypeString, 42 Optional: true, 43 Default: "SimpleScaling", // preserve AWS's default to make validation easier. 44 }, 45 "cooldown": &schema.Schema{ 46 Type: schema.TypeInt, 47 Optional: true, 48 }, 49 "estimated_instance_warmup": &schema.Schema{ 50 Type: schema.TypeInt, 51 Optional: true, 52 }, 53 "metric_aggregation_type": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 }, 57 "min_adjustment_magnitude": &schema.Schema{ 58 Type: schema.TypeInt, 59 Optional: true, 60 }, 61 "min_adjustment_step": &schema.Schema{ 62 Type: schema.TypeInt, 63 Optional: true, 64 Deprecated: "Use min_adjustment_magnitude instead, otherwise you may see a perpetual diff on this resource.", 65 ConflictsWith: []string{"min_adjustment_magnitude"}, 66 }, 67 "scaling_adjustment": &schema.Schema{ 68 Type: schema.TypeInt, 69 Optional: true, 70 ConflictsWith: []string{"step_adjustment"}, 71 }, 72 "step_adjustment": &schema.Schema{ 73 Type: schema.TypeSet, 74 Optional: true, 75 ConflictsWith: []string{"scaling_adjustment"}, 76 Elem: &schema.Resource{ 77 Schema: map[string]*schema.Schema{ 78 "metric_interval_lower_bound": &schema.Schema{ 79 Type: schema.TypeString, 80 Optional: true, 81 }, 82 "metric_interval_upper_bound": &schema.Schema{ 83 Type: schema.TypeString, 84 Optional: true, 85 }, 86 "scaling_adjustment": &schema.Schema{ 87 Type: schema.TypeInt, 88 Required: true, 89 }, 90 }, 91 }, 92 Set: resourceAwsAutoscalingScalingAdjustmentHash, 93 }, 94 }, 95 } 96 } 97 98 func resourceAwsAutoscalingPolicyCreate(d *schema.ResourceData, meta interface{}) error { 99 autoscalingconn := meta.(*AWSClient).autoscalingconn 100 101 params, err := getAwsAutoscalingPutScalingPolicyInput(d) 102 if err != nil { 103 return err 104 } 105 106 log.Printf("[DEBUG] AutoScaling PutScalingPolicy: %#v", params) 107 resp, err := autoscalingconn.PutScalingPolicy(¶ms) 108 if err != nil { 109 return fmt.Errorf("Error putting scaling policy: %s", err) 110 } 111 112 d.Set("arn", resp.PolicyARN) 113 d.SetId(d.Get("name").(string)) 114 log.Printf("[INFO] AutoScaling Scaling PolicyARN: %s", d.Get("arn").(string)) 115 116 return resourceAwsAutoscalingPolicyRead(d, meta) 117 } 118 119 func resourceAwsAutoscalingPolicyRead(d *schema.ResourceData, meta interface{}) error { 120 p, err := getAwsAutoscalingPolicy(d, meta) 121 if err != nil { 122 return err 123 } 124 if p == nil { 125 d.SetId("") 126 return nil 127 } 128 129 log.Printf("[DEBUG] Read Scaling Policy: ASG: %s, SP: %s, Obj: %s", d.Get("autoscaling_group_name"), d.Get("name"), p) 130 131 d.Set("adjustment_type", p.AdjustmentType) 132 d.Set("autoscaling_group_name", p.AutoScalingGroupName) 133 d.Set("cooldown", p.Cooldown) 134 d.Set("estimated_instance_warmup", p.EstimatedInstanceWarmup) 135 d.Set("metric_aggregation_type", p.MetricAggregationType) 136 d.Set("policy_type", p.PolicyType) 137 if p.MinAdjustmentMagnitude != nil { 138 d.Set("min_adjustment_magnitude", p.MinAdjustmentMagnitude) 139 d.Set("min_adjustment_step", 0) 140 } else { 141 d.Set("min_adjustment_step", p.MinAdjustmentStep) 142 } 143 d.Set("arn", p.PolicyARN) 144 d.Set("name", p.PolicyName) 145 d.Set("scaling_adjustment", p.ScalingAdjustment) 146 d.Set("step_adjustment", flattenStepAdjustments(p.StepAdjustments)) 147 148 return nil 149 } 150 151 func resourceAwsAutoscalingPolicyUpdate(d *schema.ResourceData, meta interface{}) error { 152 autoscalingconn := meta.(*AWSClient).autoscalingconn 153 154 params, inputErr := getAwsAutoscalingPutScalingPolicyInput(d) 155 if inputErr != nil { 156 return inputErr 157 } 158 159 log.Printf("[DEBUG] Autoscaling Update Scaling Policy: %#v", params) 160 _, err := autoscalingconn.PutScalingPolicy(¶ms) 161 if err != nil { 162 return err 163 } 164 165 return resourceAwsAutoscalingPolicyRead(d, meta) 166 } 167 168 func resourceAwsAutoscalingPolicyDelete(d *schema.ResourceData, meta interface{}) error { 169 autoscalingconn := meta.(*AWSClient).autoscalingconn 170 p, err := getAwsAutoscalingPolicy(d, meta) 171 if err != nil { 172 return err 173 } 174 if p == nil { 175 return nil 176 } 177 178 params := autoscaling.DeletePolicyInput{ 179 AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), 180 PolicyName: aws.String(d.Get("name").(string)), 181 } 182 log.Printf("[DEBUG] Deleting Autoscaling Policy opts: %s", params) 183 if _, err := autoscalingconn.DeletePolicy(¶ms); err != nil { 184 return fmt.Errorf("Autoscaling Scaling Policy: %s ", err) 185 } 186 187 d.SetId("") 188 return nil 189 } 190 191 // PutScalingPolicy can safely resend all parameters without destroying the 192 // resource, so create and update can share this common function. It will error 193 // if certain mutually exclusive values are set. 194 func getAwsAutoscalingPutScalingPolicyInput(d *schema.ResourceData) (autoscaling.PutScalingPolicyInput, error) { 195 var params = autoscaling.PutScalingPolicyInput{ 196 AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), 197 PolicyName: aws.String(d.Get("name").(string)), 198 } 199 200 if v, ok := d.GetOk("adjustment_type"); ok { 201 params.AdjustmentType = aws.String(v.(string)) 202 } 203 204 if v, ok := d.GetOk("cooldown"); ok { 205 params.Cooldown = aws.Int64(int64(v.(int))) 206 } 207 208 if v, ok := d.GetOk("estimated_instance_warmup"); ok { 209 params.EstimatedInstanceWarmup = aws.Int64(int64(v.(int))) 210 } 211 212 if v, ok := d.GetOk("metric_aggregation_type"); ok { 213 params.MetricAggregationType = aws.String(v.(string)) 214 } 215 216 if v, ok := d.GetOk("policy_type"); ok { 217 params.PolicyType = aws.String(v.(string)) 218 } 219 220 if v, ok := d.GetOk("scaling_adjustment"); ok { 221 params.ScalingAdjustment = aws.Int64(int64(v.(int))) 222 } 223 224 if v, ok := d.GetOk("step_adjustment"); ok { 225 steps, err := expandStepAdjustments(v.(*schema.Set).List()) 226 if err != nil { 227 return params, fmt.Errorf("metric_interval_lower_bound and metric_interval_upper_bound must be strings!") 228 } 229 params.StepAdjustments = steps 230 } 231 232 if v, ok := d.GetOk("min_adjustment_magnitude"); ok { 233 // params.MinAdjustmentMagnitude = aws.Int64(int64(d.Get("min_adjustment_magnitude").(int))) 234 params.MinAdjustmentMagnitude = aws.Int64(int64(v.(int))) 235 } else if v, ok := d.GetOk("min_adjustment_step"); ok { 236 // params.MinAdjustmentStep = aws.Int64(int64(d.Get("min_adjustment_step").(int))) 237 params.MinAdjustmentStep = aws.Int64(int64(v.(int))) 238 } 239 240 // Validate our final input to confirm it won't error when sent to AWS. 241 // First, SimpleScaling policy types... 242 if *params.PolicyType == "SimpleScaling" && params.StepAdjustments != nil { 243 return params, fmt.Errorf("SimpleScaling policy types cannot use step_adjustments!") 244 } 245 if *params.PolicyType == "SimpleScaling" && params.MetricAggregationType != nil { 246 return params, fmt.Errorf("SimpleScaling policy types cannot use metric_aggregation_type!") 247 } 248 if *params.PolicyType == "SimpleScaling" && params.EstimatedInstanceWarmup != nil { 249 return params, fmt.Errorf("SimpleScaling policy types cannot use estimated_instance_warmup!") 250 } 251 252 // Second, StepScaling policy types... 253 if *params.PolicyType == "StepScaling" && params.ScalingAdjustment != nil { 254 return params, fmt.Errorf("StepScaling policy types cannot use scaling_adjustment!") 255 } 256 if *params.PolicyType == "StepScaling" && params.Cooldown != nil { 257 return params, fmt.Errorf("StepScaling policy types cannot use cooldown!") 258 } 259 260 return params, nil 261 } 262 263 func getAwsAutoscalingPolicy(d *schema.ResourceData, meta interface{}) (*autoscaling.ScalingPolicy, error) { 264 autoscalingconn := meta.(*AWSClient).autoscalingconn 265 266 params := autoscaling.DescribePoliciesInput{ 267 AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), 268 PolicyNames: []*string{aws.String(d.Get("name").(string))}, 269 } 270 271 log.Printf("[DEBUG] AutoScaling Scaling Policy Describe Params: %#v", params) 272 resp, err := autoscalingconn.DescribePolicies(¶ms) 273 if err != nil { 274 return nil, fmt.Errorf("Error retrieving scaling policies: %s", err) 275 } 276 277 // find scaling policy 278 name := d.Get("name") 279 for idx, sp := range resp.ScalingPolicies { 280 if *sp.PolicyName == name { 281 return resp.ScalingPolicies[idx], nil 282 } 283 } 284 285 // policy not found 286 return nil, nil 287 } 288 289 func resourceAwsAutoscalingScalingAdjustmentHash(v interface{}) int { 290 var buf bytes.Buffer 291 m := v.(map[string]interface{}) 292 if v, ok := m["metric_interval_lower_bound"]; ok { 293 buf.WriteString(fmt.Sprintf("%f-", v)) 294 } 295 if v, ok := m["metric_interval_upper_bound"]; ok { 296 buf.WriteString(fmt.Sprintf("%f-", v)) 297 } 298 buf.WriteString(fmt.Sprintf("%d-", m["scaling_adjustment"].(int))) 299 300 return hashcode.String(buf.String()) 301 }