diff --git a/aws/resource_aws_cloudwatch_metric_alarm.go b/aws/resource_aws_cloudwatch_metric_alarm.go index f99afa391df..df07b1345a1 100644 --- a/aws/resource_aws_cloudwatch_metric_alarm.go +++ b/aws/resource_aws_cloudwatch_metric_alarm.go @@ -190,6 +190,8 @@ func resourceAwsCloudWatchMetricAlarm() *schema.Resource { Computed: true, ValidateFunc: validation.StringInSlice([]string{"evaluate", "ignore"}, true), }, + + "tags": tagsSchema(), }, } } @@ -310,6 +312,10 @@ func resourceAwsCloudWatchMetricAlarmRead(d *schema.ResourceData, meta interface d.Set("treat_missing_data", a.TreatMissingData) d.Set("evaluate_low_sample_count_percentiles", a.EvaluateLowSampleCountPercentile) + if err := saveTagsCloudWatch(meta.(*AWSClient).cloudwatchconn, d, aws.StringValue(a.AlarmArn)); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + return nil } @@ -324,6 +330,11 @@ func resourceAwsCloudWatchMetricAlarmUpdate(d *schema.ResourceData, meta interfa } log.Println("[INFO] CloudWatch Metric Alarm updated") + // Tags are cannot update by PutMetricAlarm. + if err := setTagsCloudWatch(conn, d, d.Get("arn").(string)); err != nil { + return fmt.Errorf("error updating tags for %s: %s", d.Id(), err) + } + return resourceAwsCloudWatchMetricAlarmRead(d, meta) } @@ -359,6 +370,7 @@ func getAwsCloudWatchPutMetricAlarmInput(d *schema.ResourceData) cloudwatch.PutM EvaluationPeriods: aws.Int64(int64(d.Get("evaluation_periods").(int))), Threshold: aws.Float64(d.Get("threshold").(float64)), TreatMissingData: aws.String(d.Get("treat_missing_data").(string)), + Tags: tagsFromMapCloudWatch(d.Get("tags").(map[string]interface{})), } if v := d.Get("actions_enabled"); v != nil { diff --git a/aws/resource_aws_cloudwatch_metric_alarm_test.go b/aws/resource_aws_cloudwatch_metric_alarm_test.go index 4f6010aa9a3..d91c0aaf9c5 100644 --- a/aws/resource_aws_cloudwatch_metric_alarm_test.go +++ b/aws/resource_aws_cloudwatch_metric_alarm_test.go @@ -301,6 +301,55 @@ func TestAccAWSCloudWatchMetricAlarm_missingStatistic(t *testing.T) { }) } +func TestAccAWSCloudWatchMetricAlarm_tags(t *testing.T) { + var alarm cloudwatch.MetricAlarm + resourceName := "aws_cloudwatch_metric_alarm.foobar" + rInt := acctest.RandInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudWatchMetricAlarmDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCloudWatchMetricAlarmConfigTags(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudWatchMetricAlarmExists(resourceName, &alarm), + resource.TestCheckResourceAttr(resourceName, "tags.%", "3"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", fmt.Sprintf("terraform-test-foobar%d", rInt)), + resource.TestCheckResourceAttr(resourceName, "tags.fizz", "buzz"), + resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar"), + ), + }, + { + Config: testAccAWSCloudWatchMetricAlarmConfigUpdateTags(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudWatchMetricAlarmExists(resourceName, &alarm), + resource.TestCheckResourceAttr(resourceName, "tags.%", "4"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", fmt.Sprintf("terraform-test-foobar%d", rInt)), + resource.TestCheckResourceAttr(resourceName, "tags.fizz", "buzz"), + resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar2"), + resource.TestCheckResourceAttr(resourceName, "tags.good", "bad"), + ), + }, + { + Config: testAccAWSCloudWatchMetricAlarmConfigRemoveTags(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudWatchMetricAlarmExists(resourceName, &alarm), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", fmt.Sprintf("terraform-test-foobar%d", rInt)), + resource.TestCheckResourceAttr(resourceName, "tags.fizz", "buzz"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckCloudWatchMetricAlarmDimension(n, k, v string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -771,3 +820,75 @@ resource "aws_cloudwatch_metric_alarm" "test" { } `, rName) } + +func testAccAWSCloudWatchMetricAlarmConfigTags(rInt int) string { + return fmt.Sprintf(` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar%[1]d" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitors ec2 cpu utilization" + insufficient_data_actions = [] + dimensions = { + InstanceId = "i-abc123" + } + tags = { + Name = "terraform-test-foobar%[1]d" + fizz = "buzz" + foo = "bar" + } +}`, rInt) +} + +func testAccAWSCloudWatchMetricAlarmConfigUpdateTags(rInt int) string { + return fmt.Sprintf(` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar%[1]d" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitors ec2 cpu utilization" + insufficient_data_actions = [] + dimensions = { + InstanceId = "i-abc123" + } + tags = { + Name = "terraform-test-foobar%[1]d" + fizz = "buzz" + foo = "bar2" + good = "bad" + } +}`, rInt) +} + +func testAccAWSCloudWatchMetricAlarmConfigRemoveTags(rInt int) string { + return fmt.Sprintf(` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "terraform-test-foobar%[1]d" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "120" + statistic = "Average" + threshold = "80" + alarm_description = "This metric monitors ec2 cpu utilization" + insufficient_data_actions = [] + dimensions = { + InstanceId = "i-abc123" + } + tags = { + Name = "terraform-test-foobar%[1]d" + fizz = "buzz" + } +}`, rInt) +} diff --git a/website/docs/r/cloudwatch_metric_alarm.html.markdown b/website/docs/r/cloudwatch_metric_alarm.html.markdown index 39baad3c503..52f83a6a55b 100644 --- a/website/docs/r/cloudwatch_metric_alarm.html.markdown +++ b/website/docs/r/cloudwatch_metric_alarm.html.markdown @@ -140,6 +140,7 @@ If you specify `evaluate` or omit this parameter, the alarm will always be evaluated and possibly change state no matter how many data points are available. The following values are supported: `ignore`, and `evaluate`. * `metric_query` (Optional) Enables you to create an alarm based on a metric math expression. You may specify at most 20. +* `tags` - (Optional) A mapping of tags to assign to the resource. ~> **NOTE:** If you specify at least one `metric_query`, you may not specify a `metric_name`, `namespace`, `period` or `statistic`. If you do not specify a `metric_query`, you must specify each of these (although you may use `extended_statistic` instead of `statistic`).