From ceeb94e1573443d447155fa2aaf4f9155753d995 Mon Sep 17 00:00:00 2001 From: Alex Pilon Date: Sun, 7 Jun 2015 11:23:32 +0200 Subject: [PATCH 1/3] provider/aws: Add cloudwatch_metric_alarm --- builtin/providers/aws/config.go | 5 + builtin/providers/aws/provider.go | 1 + .../resource_aws_cloudwatch_metric_alarm.go | 287 ++++++++++++++++++ ...source_aws_cloudwatch_metric_alarm_test.go | 95 ++++++ 4 files changed, 388 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_metric_alarm_test.go diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 658e0ec914eb..93f7db919043 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ecs" @@ -37,6 +38,7 @@ type Config struct { } type AWSClient struct { + cloudwatchconn *cloudwatch.CloudWatch dynamodbconn *dynamodb.DynamoDB ec2conn *ec2.EC2 ecsconn *ecs.ECS @@ -143,6 +145,9 @@ func (c *Config) Client() (interface{}, error) { log.Println("[INFO] Initializing Lambda Connection") client.lambdaconn = lambda.New(awsConfig) + + log.Println("[INFO] Initializing CloudWatch SDK connection") + client.cloudwatchconn = cloudwatch.New(awsConfig) } if len(errs) > 0 { diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index f28cf69ea089..44f881debe63 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_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), "aws_customer_gateway": resourceAwsCustomerGateway(), "aws_db_instance": resourceAwsDbInstance(), "aws_db_parameter_group": resourceAwsDbParameterGroup(), diff --git a/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go new file mode 100644 index 000000000000..9f9d60ce8af1 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go @@ -0,0 +1,287 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatch" +) + +func resourceAwsCloudWatchMetricAlarm() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCloudWatchMetricAlarmCreate, + Read: resourceAwsCloudWatchMetricAlarmRead, + Update: resourceAwsCloudWatchMetricAlarmUpdate, + Delete: resourceAwsCloudWatchMetricAlarmDelete, + + Schema: map[string]*schema.Schema{ + "alarm_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "comparison_operator": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "evaluation_periods": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "metric_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "namespace": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "period": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + "statistic": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "threshold": &schema.Schema{ + Type: schema.TypeFloat, + Required: true, + }, + "actions_enabled": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + }, + "alarm_actions": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, + "alarm_description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "dimensions": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, + "insufficient_data_actions": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, + "ok_actions": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, + "unit": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceAwsCloudWatchMetricAlarmCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchconn + + params := getAwsCloudWatchPutMetricAlarmInput(d) + + log.Printf("[DEBUG] Creating CloudWatch Metric Alarm: %#v", params) + _, err := conn.PutMetricAlarm(¶ms) + if err != nil { + return fmt.Errorf("Creating metric alarm failed: %s", err) + } + d.SetId(d.Get("alarm_name").(string)) + log.Println("[INFO] CloudWatch Metric Alarm created") + + return resourceAwsCloudWatchMetricAlarmRead(d, meta) +} + +func resourceAwsCloudWatchMetricAlarmRead(d *schema.ResourceData, meta interface{}) error { + a, err := getAwsCloudWatchMetricAlarm(d, meta) + if err != nil { + return err + } + if a == nil { + d.SetId("") + return nil + } + + log.Printf("[DEBUG] Reading CloudWatch Metric Alarm: %s", d.Get("alarm_name")) + + d.Set("actions_enabled", a.ActionsEnabled) + + if err := d.Set("alarm_actions", _strArrPtrToList(a.AlarmActions)); err != nil { + log.Printf("[WARN] Error setting Alarm Actions: %s", err) + } + d.Set("alarm_description", a.AlarmDescription) + d.Set("alarm_name", a.AlarmName) + d.Set("comparison_operator", a.ComparisonOperator) + d.Set("dimensions", a.Dimensions) + d.Set("evaluation_periods", a.EvaluationPeriods) + + if err := d.Set("insufficient_data_actions", _strArrPtrToList(a.InsufficientDataActions)); err != nil { + log.Printf("[WARN] Error setting Insufficient Data Actions: %s", err) + } + d.Set("metric_name", a.MetricName) + d.Set("namespace", a.Namespace) + + if err := d.Set("ok_actions", _strArrPtrToList(a.OKActions)); err != nil { + log.Printf("[WARN] Error setting OK Actions: %s", err) + } + d.Set("period", a.Period) + d.Set("statistic", a.Statistic) + d.Set("threshold", a.Threshold) + d.Set("unit", a.Unit) + + return nil +} + +func resourceAwsCloudWatchMetricAlarmUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchconn + params := getAwsCloudWatchPutMetricAlarmInput(d) + + log.Printf("[DEBUG] Updating CloudWatch Metric Alarm: %#v", params) + _, err := conn.PutMetricAlarm(¶ms) + if err != nil { + return fmt.Errorf("Updating metric alarm failed: %s", err) + } + log.Println("[INFO] CloudWatch Metric Alarm updated") + + return resourceAwsCloudWatchMetricAlarmRead(d, meta) +} + +func resourceAwsCloudWatchMetricAlarmDelete(d *schema.ResourceData, meta interface{}) error { + p, err := getAwsCloudWatchMetricAlarm(d, meta) + if err != nil { + return err + } + if p == nil { + log.Printf("[DEBUG] CloudWatch Metric Alarm %s is already gone", d.Id()) + return nil + } + + log.Printf("[INFO] Deleting CloudWatch Metric Alarm: %s", d.Id()) + + conn := meta.(*AWSClient).cloudwatchconn + params := cloudwatch.DeleteAlarmsInput{ + AlarmNames: []*string{aws.String(d.Id())}, + } + + if _, err := conn.DeleteAlarms(¶ms); err != nil { + return fmt.Errorf("Error deleting CloudWatch Metric Alarm: %s", err) + } + log.Println("[INFO] CloudWatch Metric Alarm deleted") + + d.SetId("") + return nil +} + +func getAwsCloudWatchPutMetricAlarmInput(d *schema.ResourceData) cloudwatch.PutMetricAlarmInput { + params := cloudwatch.PutMetricAlarmInput{ + AlarmName: aws.String(d.Get("alarm_name").(string)), + ComparisonOperator: aws.String(d.Get("comparison_operator").(string)), + EvaluationPeriods: aws.Long(int64(d.Get("evaluation_periods").(int))), + MetricName: aws.String(d.Get("metric_name").(string)), + Namespace: aws.String(d.Get("namespace").(string)), + Period: aws.Long(int64(d.Get("period").(int))), + Statistic: aws.String(d.Get("statistic").(string)), + Threshold: aws.Double(d.Get("threshold").(float64)), + } + + if v := d.Get("actions_enabled"); v != nil { + params.ActionsEnabled = aws.Boolean(v.(bool)) + } + + if v, ok := d.GetOk("alarm_description"); ok { + params.AlarmDescription = aws.String(v.(string)) + } + + if v, ok := d.GetOk("unit"); ok { + params.Unit = aws.String(v.(string)) + } + + var alarmActions []*string + if v := d.Get("alarm_actions"); v != nil { + for _, v := range v.(*schema.Set).List() { + str := v.(string) + alarmActions = append(alarmActions, aws.String(str)) + } + params.AlarmActions = alarmActions + } + + var insufficientDataActions []*string + if v := d.Get("insufficient_data_actions"); v != nil { + for _, v := range v.(*schema.Set).List() { + str := v.(string) + insufficientDataActions = append(insufficientDataActions, aws.String(str)) + } + params.InsufficientDataActions = insufficientDataActions + } + + var okActions []*string + if v := d.Get("ok_actions"); v != nil { + for _, v := range v.(*schema.Set).List() { + str := v.(string) + okActions = append(okActions, aws.String(str)) + } + params.OKActions = okActions + } + + a := d.Get("dimensions").(map[string]interface{}) + dimensions := make([]*cloudwatch.Dimension, 0, len(a)) + for k, v := range a { + dimensions = append(dimensions, &cloudwatch.Dimension{ + Name: aws.String(k), + Value: aws.String(v.(string)), + }) + } + params.Dimensions = dimensions + + return params +} + +func getAwsCloudWatchMetricAlarm(d *schema.ResourceData, meta interface{}) (*cloudwatch.MetricAlarm, error) { + conn := meta.(*AWSClient).cloudwatchconn + + params := cloudwatch.DescribeAlarmsInput{ + AlarmNames: []*string{aws.String(d.Id())}, + } + + resp, err := conn.DescribeAlarms(¶ms) + if err != nil { + return nil, nil + } + + // Find it and return it + for idx, ma := range resp.MetricAlarms { + if *ma.AlarmName == d.Id() { + return resp.MetricAlarms[idx], nil + } + } + + return nil, nil +} + +func _strArrPtrToList(strArrPtr []*string) []string { + var result []string + for _, elem := range strArrPtr { + result = append(result, *elem) + } + return result +} diff --git a/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm_test.go b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm_test.go new file mode 100644 index 000000000000..8d9a53c360e9 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm_test.go @@ -0,0 +1,95 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatch" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSCloudWatchMetricAlarm_basic(t *testing.T) { + var alarm cloudwatch.MetricAlarm + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudWatchMetricAlarmDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSCloudWatchMetricAlarmConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudWatchMetricAlarmExists("aws_cloudwatch_metric_alarm.foobar", &alarm), + resource.TestCheckResourceAttr("aws_cloudwatch_metric_alarm.foobar", "metric_name", "CPUUtilization"), + resource.TestCheckResourceAttr("aws_cloudwatch_metric_alarm.foobar", "statistic", "Average"), + ), + }, + }, + }) +} + +func testAccCheckCloudWatchMetricAlarmExists(n string, alarm *cloudwatch.MetricAlarm) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).cloudwatchconn + params := cloudwatch.DescribeAlarmsInput{ + AlarmNames: []*string{aws.String(rs.Primary.ID)}, + } + resp, err := conn.DescribeAlarms(¶ms) + if err != nil { + return err + } + if len(resp.MetricAlarms) == 0 { + return fmt.Errorf("Alarm not found") + } + *alarm = *resp.MetricAlarms[0] + + return nil + } +} + +func testAccCheckAWSCloudWatchMetricAlarmDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).cloudwatchconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cloudwatch_metric_alarm" { + continue + } + + params := cloudwatch.DescribeAlarmsInput{ + AlarmNames: []*string{aws.String(rs.Primary.ID)}, + } + + resp, err := conn.DescribeAlarms(¶ms) + + if err == nil { + if len(resp.MetricAlarms) != 0 && + *resp.MetricAlarms[0].AlarmName == rs.Primary.ID { + return fmt.Errorf("Alarm Still Exists: %s", rs.Primary.ID) + } + } + } + + return nil +} + +var testAccAWSCloudWatchMetricAlarmConfig = fmt.Sprintf(` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar5" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitor ec2 cpu utilization" + insufficient_data_actions = [] +} +`) From 05f4b9bfd940d717fa3b6646a5d71c6de41541f6 Mon Sep 17 00:00:00 2001 From: Alex Pilon Date: Sun, 7 Jun 2015 11:18:34 +0200 Subject: [PATCH 2/3] provider/aws: Add autoscaling_policy --- builtin/providers/aws/provider.go | 1 + .../aws/resource_aws_autoscaling_policy.go | 181 ++++++++++++++++++ .../resource_aws_autoscaling_policy_test.go | 118 ++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_autoscaling_policy.go create mode 100644 builtin/providers/aws/resource_aws_autoscaling_policy_test.go diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 44f881debe63..0e54e7b501a4 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 000000000000..d2f6d2d47b13 --- /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 000000000000..2254640b08fc --- /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}" +} +`) From 14f4e5fe54584fb6e7a2212217a9d5d9d753dd59 Mon Sep 17 00:00:00 2001 From: Alex Pilon Date: Sun, 7 Jun 2015 11:19:57 +0200 Subject: [PATCH 3/3] provider/aws: Add docs for autoscaling_policy + cloudwatch_metric_alarm --- .../resource_aws_autoscaling_policy_test.go | 3 - .../resource_aws_cloudwatch_metric_alarm.go | 1 + .../aws/r/autoscaling_policy.html.markdown | 53 +++++++++++++ .../r/cloudwatch_metric_alarm.html.markdown | 75 +++++++++++++++++++ website/source/layouts/aws.erb | 8 ++ 5 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 website/source/docs/providers/aws/r/autoscaling_policy.html.markdown create mode 100644 website/source/docs/providers/aws/r/cloudwatch_metric_alarm.html.markdown diff --git a/builtin/providers/aws/resource_aws_autoscaling_policy_test.go b/builtin/providers/aws/resource_aws_autoscaling_policy_test.go index 2254640b08fc..0a7aeff916dc 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_policy_test.go +++ b/builtin/providers/aws/resource_aws_autoscaling_policy_test.go @@ -51,8 +51,6 @@ func testAccCheckScalingPolicyExists(n string, policy *autoscaling.ScalingPolicy return fmt.Errorf("ScalingPolicy not found") } - *policy = *resp.ScalingPolicies[0] - return nil } } @@ -97,7 +95,6 @@ resource "aws_autoscaling_group" "foobar" { 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}" diff --git a/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go index 9f9d60ce8af1..4c8b401400e2 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_metric_alarm.go @@ -55,6 +55,7 @@ func resourceAwsCloudWatchMetricAlarm() *schema.Resource { "actions_enabled": &schema.Schema{ Type: schema.TypeBool, Optional: true, + Default: true, }, "alarm_actions": &schema.Schema{ Type: schema.TypeSet, diff --git a/website/source/docs/providers/aws/r/autoscaling_policy.html.markdown b/website/source/docs/providers/aws/r/autoscaling_policy.html.markdown new file mode 100644 index 000000000000..2543c0220d8f --- /dev/null +++ b/website/source/docs/providers/aws/r/autoscaling_policy.html.markdown @@ -0,0 +1,53 @@ +--- +layout: "aws" +page_title: "AWS: aws_autoscaling_policy" +sidebar_current: "docs-aws-resource-autoscaling-policy" +description: |- + Provides an AutoScaling Scaling Group resource. +--- + +# aws\_autoscaling\_policy + +Provides an AutoScaling Scaling Policy resource. + +~> **NOTE:** You may want to omit `desired_capacity` attribute from attached `aws_autoscaling_group` +when using autoscaling policies. It's good practice to pick either +[manual](http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-manual-scaling.html) +or [dynamic](http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/as-scale-based-on-demand.html) +(policy-based) scaling. + +## Example Usage +``` +resource "aws_autoscaling_policy" "bat" { + name = "foobar3-terraform-test" + scaling_adjustment = 4 + adjustment_type = "ChangeInCapacity" + cooldown = 300 + autoscaling_group_name = "${aws_autoscaling_group.bar.name}" +} + +resource "aws_autoscaling_group" "bar" { + availability_zones = ["us-east-1a"] + name = "foobar3-terraform-test" + max_size = 5 + min_size = 2 + health_check_grace_period = 300 + health_check_type = "ELB" + force_delete = true + launch_configuration = "${aws_launch_configuration.foo.name}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the policy. +* `autoscaling_group_name` - (Required) The name or ARN of the group. +* `adjustment_type` - (Required) Specifies whether the `scaling_adjustment` is an absolute number or a percentage of the current capacity. Valid values are `ChangeInCapacity`, `ExactCapacity`, and `PercentChangeInCapacity`. +* `scaling_adjustment` - (Required) The number of instances by which to scale. `adjustment_type` determines the interpretation of this number (e.g., as an absolute number or as a percentage of the existing Auto Scaling group size). A positive increment adds to the current capacity and a negative value removes from the current capacity. +* `cooldown` - (Optional) The amount of time, in seconds, after a scaling activity completes and before the next scaling activity can start. +* `min_adjustment_step` - (Optional) Used with `adjustment_type` with the value `PercentChangeInCapacity`, the scaling policy changes the `desired_capacity` of the Auto Scaling group by at least the number of instances specified in the value. + +## Attribute Reference +* `arn` - The ARN assigned by AWS to the scaling policy. diff --git a/website/source/docs/providers/aws/r/cloudwatch_metric_alarm.html.markdown b/website/source/docs/providers/aws/r/cloudwatch_metric_alarm.html.markdown new file mode 100644 index 000000000000..e6ede269fc6b --- /dev/null +++ b/website/source/docs/providers/aws/r/cloudwatch_metric_alarm.html.markdown @@ -0,0 +1,75 @@ +--- +layout: "aws" +page_title: "AWS: cloudwatch_metric_alarm" +sidebar_current: "docs-aws-resource-cloudwatch-metric-alarm" +description: |- + Provides an AutoScaling Scaling Group resource. +--- + +# aws\_cloudwatch\_metric\_alarm + +Provides a CloudWatch Metric Alarm resource. + +## Example Usage +``` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar5" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitor ec2 cpu utilization" + insufficient_data_actions = [] +} +``` + +## Example in Conjuction with Scaling Policies +``` +resource "aws_autoscaling_policy" "bat" { + name = "foobar3-terraform-test" + scaling_adjustment = 4 + adjustment_type = "ChangeInCapacity" + cooldown = 300 + autoscaling_group_name = "${aws_autoscaling_group.bar.name}" +} + +resource "aws_cloudwatch_metric_alarm" "bat" { + alarm_name = "terraform-test-foobar5" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitor ec2 cpu utilization" + alarm_actions = ["${aws_autoscaling_policy.bat.arn}"] +} +``` +## Argument Reference + +See [related part of AWS Docs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_PutMetricAlarm.html) +for details about valid values. + +The following arguments are supported: + +* `alarm_name` - (Required) The descriptive name for the alarm. This name must be unique within the user's AWS account +* `comparison_operator` - (Required) The arithmetic operation to use when comparing the specified Statistic and Threshold. The specified Statistic value is used as the first operand. Either of the following is supported: `GreaterThanOrEqualToThreshold`, `GreaterThanThreshold`, `LessThanThreshold`, `LessThanOrEqualToThreshold`. +* `evaluation_periods` - (Required) The number of periods over which data is compared to the specified threshold. +* `metric_name` - (Required) The name for the alarm's associated metric. + See docs for [supported metrics]([valid metrics](http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html)). +* `namespace` - (Required) The namespace for the alarm's associated metric. +* `period` - (Required) The period in seconds over which the specified `statistic` is applied. +* `statistic` - (Required) The statistic to apply to the alarm's associated metric. + Either of the following is supported: `SampleCount`, `Average`, `Sum`, `Minimum`, `Maximum` +* `threshold` - (Required) The value against which the specified statistic is compared. +* `actions_enabled` - (Optional) Indicates whether or not actions should be executed during any changes to the alarm's state. Defaults to `true`. +* `alarm_actions` - (Optional) The list of actions to execute when this alarm transitions into an ALARM state from any other state. Each action is specified as an Amazon Resource Number (ARN). +* `alarm_description` - (Optional) The description for the alarm. +* `dimensions` - (Optional) The dimensions for the alarm's associated metric. +* `insufficient_data_actions` - (Optional) The list of actions to execute when this alarm transitions into an INSUFFICIENT_DATA state from any other state. Each action is specified as an Amazon Resource Number (ARN). +* `ok_actions` - (Optional) The list of actions to execute when this alarm transitions into an OK state from any other state. Each action is specified as an Amazon Resource Number (ARN). +* `unit` - (Optional) The unit for the alarm's associated metric. diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 7afd00060b55..801945dec969 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -21,6 +21,14 @@ aws_autoscaling_notification + > + aws_autoscaling_policy + + + > + aws_cloudwatch_metric_alarm + + > aws_customer_gateway