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