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(&params)
   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(&params)
   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(&params); 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(&params)
   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  }