diff --git a/builtin/providers/aws/resource_aws_autoscaling_group.go b/builtin/providers/aws/resource_aws_autoscaling_group.go index 73752c795..7c5b38769 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group.go @@ -147,6 +147,19 @@ func resourceAwsAutoscalingGroup() *schema.Resource { Optional: true, }, + "enabled_metrics": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "metrics_granularity": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "1Minute", + }, + "tag": autoscalingTagsSchema(), }, } @@ -226,6 +239,13 @@ func resourceAwsAutoscalingGroupCreate(d *schema.ResourceData, meta interface{}) return err } + if _, ok := d.GetOk("enabled_metrics"); ok { + metricsErr := enableASGMetricsCollection(d, conn) + if metricsErr != nil { + return metricsErr + } + } + return resourceAwsAutoscalingGroupRead(d, meta) } @@ -266,6 +286,13 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e d.Set("termination_policies", flattenStringList(g.TerminationPolicies)) } + if g.EnabledMetrics != nil { + if err := d.Set("enabled_metrics", flattenAsgEnabledMetrics(g.EnabledMetrics)); err != nil { + log.Printf("[WARN] Error setting metrics for (%s): %s", d.Id(), err) + } + d.Set("metrics_granularity", g.EnabledMetrics[0].Granularity) + } + return nil } @@ -386,6 +413,10 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) waitForASGCapacity(d, meta, capacitySatifiedUpdate) } + if d.HasChange("enabled_metrics") { + updateASGMetricsCollection(d, conn) + } + return resourceAwsAutoscalingGroupRead(d, meta) } @@ -519,6 +550,64 @@ func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{}) }) } +func enableASGMetricsCollection(d *schema.ResourceData, conn *autoscaling.AutoScaling) error { + props := &autoscaling.EnableMetricsCollectionInput{ + AutoScalingGroupName: aws.String(d.Id()), + Granularity: aws.String(d.Get("metrics_granularity").(string)), + Metrics: expandStringList(d.Get("enabled_metrics").(*schema.Set).List()), + } + + log.Printf("[INFO] Enabling metrics collection for the ASG: %s", d.Id()) + _, metricsErr := conn.EnableMetricsCollection(props) + if metricsErr != nil { + return metricsErr + } + + return nil +} + +func updateASGMetricsCollection(d *schema.ResourceData, conn *autoscaling.AutoScaling) error { + + o, n := d.GetChange("enabled_metrics") + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + + os := o.(*schema.Set) + ns := n.(*schema.Set) + + disableMetrics := os.Difference(ns) + if disableMetrics.Len() != 0 { + props := &autoscaling.DisableMetricsCollectionInput{ + AutoScalingGroupName: aws.String(d.Id()), + Metrics: expandStringList(disableMetrics.List()), + } + + _, err := conn.DisableMetricsCollection(props) + if err != nil { + return fmt.Errorf("Failure to Disable metrics collection types for ASG %s: %s", d.Id(), err) + } + } + + enabledMetrics := ns.Difference(os) + if enabledMetrics.Len() != 0 { + props := &autoscaling.EnableMetricsCollectionInput{ + AutoScalingGroupName: aws.String(d.Id()), + Metrics: expandStringList(enabledMetrics.List()), + } + + _, err := conn.EnableMetricsCollection(props) + if err != nil { + return fmt.Errorf("Failure to Enable metrics collection types for ASG %s: %s", d.Id(), err) + } + } + + return nil +} + // Returns a mapping of the instance states of all the ELBs attached to the // provided ASG. // diff --git a/builtin/providers/aws/resource_aws_autoscaling_group_test.go b/builtin/providers/aws/resource_aws_autoscaling_group_test.go index 4292baca8..bb23f570a 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group_test.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group_test.go @@ -247,6 +247,35 @@ func TestAccAWSAutoScalingGroup_withPlacementGroup(t *testing.T) { }) } +func TestAccAWSAutoScalingGroup_withMetrics(t *testing.T) { + var group autoscaling.Group + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAutoScalingGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSAutoscalingMetricsCollectionConfig_allMetricsCollected, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "enabled_metrics.#", "7"), + ), + }, + + resource.TestStep{ + Config: testAccAWSAutoscalingMetricsCollectionConfig_updatingMetricsCollected, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group), + resource.TestCheckResourceAttr( + "aws_autoscaling_group.bar", "enabled_metrics.#", "5"), + ), + }, + }, + }) +} + func testAccCheckAWSAutoScalingGroupDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).autoscalingconn @@ -751,3 +780,57 @@ resource "aws_autoscaling_group" "bar" { } } ` + +const testAccAWSAutoscalingMetricsCollectionConfig_allMetricsCollected = ` +resource "aws_launch_configuration" "foobar" { + image_id = "ami-21f78e11" + instance_type = "t1.micro" +} + +resource "aws_autoscaling_group" "bar" { + availability_zones = ["us-west-2a"] + max_size = 1 + min_size = 0 + health_check_grace_period = 300 + health_check_type = "EC2" + desired_capacity = 0 + force_delete = true + termination_policies = ["OldestInstance","ClosestToNextInstanceHour"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + enabled_metrics = ["GroupTotalInstances", + "GroupPendingInstances", + "GroupTerminatingInstances", + "GroupDesiredCapacity", + "GroupInServiceInstances", + "GroupMinSize", + "GroupMaxSize" + ] + metrics_granularity = "1Minute" +} +` + +const testAccAWSAutoscalingMetricsCollectionConfig_updatingMetricsCollected = ` +resource "aws_launch_configuration" "foobar" { + image_id = "ami-21f78e11" + instance_type = "t1.micro" +} + +resource "aws_autoscaling_group" "bar" { + availability_zones = ["us-west-2a"] + max_size = 1 + min_size = 0 + health_check_grace_period = 300 + health_check_type = "EC2" + desired_capacity = 0 + force_delete = true + termination_policies = ["OldestInstance","ClosestToNextInstanceHour"] + launch_configuration = "${aws_launch_configuration.foobar.name}" + enabled_metrics = ["GroupTotalInstances", + "GroupPendingInstances", + "GroupTerminatingInstances", + "GroupDesiredCapacity", + "GroupMaxSize" + ] + metrics_granularity = "1Minute" +} +` diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index 6facdf792..7937322f8 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/directoryservice" "github.com/aws/aws-sdk-go/service/ec2" @@ -772,3 +773,13 @@ func flattenCloudFormationOutputs(cfOutputs []*cloudformation.Output) map[string } return outputs } + +func flattenAsgEnabledMetrics(list []*autoscaling.EnabledMetric) []string { + strs := make([]string, 0, len(list)) + for _, r := range list { + if r.Metric != nil { + strs = append(strs, *r.Metric) + } + } + return strs +} diff --git a/builtin/providers/aws/structure_test.go b/builtin/providers/aws/structure_test.go index 998a25747..898d93ce7 100644 --- a/builtin/providers/aws/structure_test.go +++ b/builtin/providers/aws/structure_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/elasticache" "github.com/aws/aws-sdk-go/service/elb" @@ -700,3 +701,24 @@ func TestFlattenResourceRecords(t *testing.T) { t.Fatal("expected result to have value, but got nil") } } + +func TestFlattenAsgEnabledMetrics(t *testing.T) { + expanded := []*autoscaling.EnabledMetric{ + &autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupTotalInstances")}, + &autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupMaxSize")}, + } + + result := flattenAsgEnabledMetrics(expanded) + + if len(result) != 2 { + t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) + } + + if result[0] != "GroupTotalInstances" { + t.Fatalf("expected id to be GroupTotalInstances, but was %s", result[0]) + } + + if result[1] != "GroupMaxSize" { + t.Fatalf("expected id to be GroupMaxSize, but was %s", result[1]) + } +} diff --git a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown index e71ab0750..cd0c5ccb5 100644 --- a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown +++ b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown @@ -70,6 +70,8 @@ The following arguments are supported: * `termination_policies` (Optional) A list of policies to decide how the instances in the auto scale group should be terminated. * `tag` (Optional) A list of tag blocks. Tags documented below. * `placement_group` (Optional) The name of the placement group into which you'll launch your instances, if any. +* `metrics_granularity` - (Required) The granularity to associate with the metrics to collect. The only valid value is `1Minute`. +* `enabled_metrics` - (Required) A list of metrics to collect. The allowed values are `GroupMinSize`, `GroupMaxSize`, `GroupDesiredCapacity`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupTerminatingInstances`, `GroupTotalInstances`. * `wait_for_capacity_timeout` (Default: "10m") A maximum [duration](https://golang.org/pkg/time/#ParseDuration) that Terraform should wait for ASG instances to be healthy before timing out. (See also [Waiting