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