diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 44f881deb..0e54e7b50 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -86,6 +86,7 @@ func Provider() terraform.ResourceProvider { "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), "aws_autoscaling_group": resourceAwsAutoscalingGroup(), "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), + "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), "aws_customer_gateway": resourceAwsCustomerGateway(), "aws_db_instance": resourceAwsDbInstance(), diff --git a/builtin/providers/aws/resource_aws_autoscaling_policy.go b/builtin/providers/aws/resource_aws_autoscaling_policy.go new file mode 100644 index 000000000..d2f6d2d47 --- /dev/null +++ b/builtin/providers/aws/resource_aws_autoscaling_policy.go @@ -0,0 +1,181 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsAutoscalingPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAutoscalingPolicyCreate, + Read: resourceAwsAutoscalingPolicyRead, + Update: resourceAwsAutoscalingPolicyUpdate, + Delete: resourceAwsAutoscalingPolicyDelete, + + Schema: map[string]*schema.Schema{ + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "adjustment_type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "autoscaling_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "cooldown": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, + "min_adjustment_step": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, + "scaling_adjustment": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + }, + } +} + +func resourceAwsAutoscalingPolicyCreate(d *schema.ResourceData, meta interface{}) error { + autoscalingconn := meta.(*AWSClient).autoscalingconn + + params := getAwsAutoscalingPutScalingPolicyInput(d) + + log.Printf("[DEBUG] AutoScaling PutScalingPolicy: %#v", params) + resp, err := autoscalingconn.PutScalingPolicy(¶ms) + if err != nil { + return fmt.Errorf("Error putting scaling policy: %s", err) + } + + d.Set("arn", resp.PolicyARN) + d.SetId(d.Get("name").(string)) + log.Printf("[INFO] AutoScaling Scaling PolicyARN: %s", d.Get("arn").(string)) + + return resourceAwsAutoscalingPolicyRead(d, meta) +} + +func resourceAwsAutoscalingPolicyRead(d *schema.ResourceData, meta interface{}) error { + p, err := getAwsAutoscalingPolicy(d, meta) + if err != nil { + return err + } + if p == nil { + d.SetId("") + return nil + } + + log.Printf("[DEBUG] Read Scaling Policy: ASG: %s, SP: %s, Obj: %#v", d.Get("autoscaling_group_name"), d.Get("name"), p) + + d.Set("adjustment_type", p.AdjustmentType) + d.Set("autoscaling_group_name", p.AutoScalingGroupName) + d.Set("cooldown", p.Cooldown) + d.Set("min_adjustment_step", p.MinAdjustmentStep) + d.Set("arn", p.PolicyARN) + d.Set("name", p.PolicyName) + d.Set("scaling_adjustment", p.ScalingAdjustment) + + return nil +} + +func resourceAwsAutoscalingPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + autoscalingconn := meta.(*AWSClient).autoscalingconn + + params := getAwsAutoscalingPutScalingPolicyInput(d) + + log.Printf("[DEBUG] Autoscaling Update Scaling Policy: %#v", params) + _, err := autoscalingconn.PutScalingPolicy(¶ms) + if err != nil { + return err + } + + return resourceAwsAutoscalingPolicyRead(d, meta) +} + +func resourceAwsAutoscalingPolicyDelete(d *schema.ResourceData, meta interface{}) error { + autoscalingconn := meta.(*AWSClient).autoscalingconn + p, err := getAwsAutoscalingPolicy(d, meta) + if err != nil { + return err + } + if p == nil { + return nil + } + + params := autoscaling.DeletePolicyInput{ + AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), + PolicyName: aws.String(d.Get("name").(string)), + } + if _, err := autoscalingconn.DeletePolicy(¶ms); err != nil { + return fmt.Errorf("Autoscaling Scaling Policy: %s ", err) + } + + d.SetId("") + return nil +} + +// PutScalingPolicy seems to require all params to be resent, so create and update can share this common function +func getAwsAutoscalingPutScalingPolicyInput(d *schema.ResourceData) autoscaling.PutScalingPolicyInput { + var params = autoscaling.PutScalingPolicyInput{ + AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), + PolicyName: aws.String(d.Get("name").(string)), + } + + if v, ok := d.GetOk("adjustment_type"); ok { + params.AdjustmentType = aws.String(v.(string)) + } + + if v, ok := d.GetOk("cooldown"); ok { + params.Cooldown = aws.Long(int64(v.(int))) + } + + if v, ok := d.GetOk("scaling_adjustment"); ok { + params.ScalingAdjustment = aws.Long(int64(v.(int))) + } + + if v, ok := d.GetOk("min_adjustment_step"); ok { + params.MinAdjustmentStep = aws.Long(int64(v.(int))) + } + + return params +} + +func getAwsAutoscalingPolicy(d *schema.ResourceData, meta interface{}) (*autoscaling.ScalingPolicy, error) { + autoscalingconn := meta.(*AWSClient).autoscalingconn + + params := autoscaling.DescribePoliciesInput{ + AutoScalingGroupName: aws.String(d.Get("autoscaling_group_name").(string)), + PolicyNames: []*string{aws.String(d.Get("name").(string))}, + } + + log.Printf("[DEBUG] AutoScaling Scaling Policy Describe Params: %#v", params) + resp, err := autoscalingconn.DescribePolicies(¶ms) + if err != nil { + return nil, fmt.Errorf("Error retrieving scaling policies: %s", err) + } + + // find scaling policy + name := d.Get("name") + for idx, sp := range resp.ScalingPolicies { + if *sp.PolicyName == name { + return resp.ScalingPolicies[idx], nil + } + } + + // policy not found + return nil, nil +} diff --git a/builtin/providers/aws/resource_aws_autoscaling_policy_test.go b/builtin/providers/aws/resource_aws_autoscaling_policy_test.go new file mode 100644 index 000000000..2254640b0 --- /dev/null +++ b/builtin/providers/aws/resource_aws_autoscaling_policy_test.go @@ -0,0 +1,118 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSAutoscalingPolicy_basic(t *testing.T) { + var policy autoscaling.ScalingPolicy + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAutoscalingPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSAutoscalingPolicyConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckScalingPolicyExists("aws_autoscaling_policy.foobar", &policy), + resource.TestCheckResourceAttr("aws_autoscaling_policy.foobar", "adjustment_type", "ChangeInCapacity"), + resource.TestCheckResourceAttr("aws_autoscaling_policy.foobar", "cooldown", "300"), + ), + }, + }, + }) +} + +func testAccCheckScalingPolicyExists(n string, policy *autoscaling.ScalingPolicy) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + rs = rs + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).autoscalingconn + params := &autoscaling.DescribePoliciesInput{ + AutoScalingGroupName: aws.String(rs.Primary.Attributes["autoscaling_group_name"]), + PolicyNames: []*string{aws.String(rs.Primary.ID)}, + } + resp, err := conn.DescribePolicies(params) + if err != nil { + return err + } + if len(resp.ScalingPolicies) == 0 { + return fmt.Errorf("ScalingPolicy not found") + } + + *policy = *resp.ScalingPolicies[0] + + return nil + } +} + +func testAccCheckAWSAutoscalingPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).autoscalingconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_autoscaling_group" { + continue + } + + params := autoscaling.DescribePoliciesInput{ + AutoScalingGroupName: aws.String(rs.Primary.Attributes["autoscaling_group_name"]), + PolicyNames: []*string{aws.String(rs.Primary.ID)}, + } + + resp, err := conn.DescribePolicies(¶ms) + + if err == nil { + if len(resp.ScalingPolicies) != 0 && + *resp.ScalingPolicies[0].PolicyName == rs.Primary.ID { + return fmt.Errorf("Scaling Policy Still Exists: %s", rs.Primary.ID) + } + } + } + + return nil +} + +var testAccAWSAutoscalingPolicyConfig = fmt.Sprintf(` +resource "aws_launch_configuration" "foobar" { + name = "terraform-test-foobar5" + image_id = "ami-21f78e11" + instance_type = "t1.micro" +} + +resource "aws_autoscaling_group" "foobar" { + availability_zones = ["us-west-2a"] + name = "terraform-test-foobar5" + max_size = 5 + min_size = 2 + health_check_grace_period = 300 + health_check_type = "ELB" + desired_capacity = 4 + force_delete = true + termination_policies = ["OldestInstance"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + tag { + key = "Foo" + value = "foo-bar" + propagate_at_launch = true + } +} + +resource "aws_autoscaling_policy" "foobar" { + name = "foobar" + scaling_adjustment = 4 + adjustment_type = "ChangeInCapacity" + cooldown = 300 + autoscaling_group_name = "${aws_autoscaling_group.foobar.name}" +} +`)