From da5abccfd9184af08c2d02ec64cb5b4f54b2f2a3 Mon Sep 17 00:00:00 2001 From: stack72 Date: Fri, 19 Aug 2016 13:00:45 +0100 Subject: [PATCH] provider/aws: Implement support for CloudWatch Metric in `aws_route53_health_check` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #7830 ``` % make testacc TEST=./builtin/providers/aws % TESTARGS='-run=TestAccAWSRoute53HealthCheck_' ✚ ==> Checking that code complies with gofmt requirements... /Users/stacko/Code/go/bin/stringer go generate $(go list ./... | grep -v /terraform/vendor/) 2016/08/19 12:58:00 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSRoute53HealthCheck_ -timeout 120m === RUN TestAccAWSRoute53HealthCheck_importBasic --- PASS: TestAccAWSRoute53HealthCheck_importBasic (20.03s) === RUN TestAccAWSRoute53HealthCheck_basic --- PASS: TestAccAWSRoute53HealthCheck_basic (31.42s) === RUN TestAccAWSRoute53HealthCheck_withChildHealthChecks --- PASS: TestAccAWSRoute53HealthCheck_withChildHealthChecks (26.88s) === RUN TestAccAWSRoute53HealthCheck_IpConfig --- PASS: TestAccAWSRoute53HealthCheck_IpConfig (30.27s) === RUN TestAccAWSRoute53HealthCheck_CloudWatchAlarmCheck --- PASS: TestAccAWSRoute53HealthCheck_CloudWatchAlarmCheck (26.08s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 134.692s ``` --- .../aws/resource_aws_route53_health_check.go | 55 ++++++++++++++++++- .../resource_aws_route53_health_check_test.go | 39 +++++++++++++ .../aws/r/route53_health_check.html.markdown | 29 +++++++++- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route53_health_check.go b/builtin/providers/aws/resource_aws_route53_health_check.go index 0c16770ae..e9d2e3d22 100644 --- a/builtin/providers/aws/resource_aws_route53_health_check.go +++ b/builtin/providers/aws/resource_aws_route53_health_check.go @@ -69,6 +69,7 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "measure_latency": &schema.Schema{ Type: schema.TypeBool, Optional: true, @@ -95,6 +96,21 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { }, }, + "cloudwatch_alarm_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + + "cloudwatch_alarm_region": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + + "insufficient_data_health_status": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "tags": tagsSchema(), }, } @@ -135,6 +151,19 @@ func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{ updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) } + if d.HasChange("cloudwatch_alarm_name") || d.HasChange("cloudwatch_alarm_region") { + cloudwatchAlarm := &route53.AlarmIdentifier{ + Name: aws.String(d.Get("cloudwatch_alarm_name").(string)), + Region: aws.String(d.Get("cloudwatch_alarm_region").(string)), + } + + updateHealthCheck.AlarmIdentifier = cloudwatchAlarm + } + + if d.HasChange("insufficient_data_health_status") { + updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string)) + } + _, err := conn.UpdateHealthCheck(updateHealthCheck) if err != nil { return err @@ -182,7 +211,7 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ healthConfig.ResourcePath = aws.String(v.(string)) } - if *healthConfig.Type != route53.HealthCheckTypeCalculated { + if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric { if v, ok := d.GetOk("measure_latency"); ok { healthConfig.MeasureLatency = aws.Bool(v.(bool)) } @@ -202,6 +231,24 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ } } + if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric { + cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{} + + if v, ok := d.GetOk("cloudwatch_alarm_name"); ok { + cloudwatchAlarmIdentifier.Name = aws.String(v.(string)) + } + + if v, ok := d.GetOk("cloudwatch_alarm_region"); ok { + cloudwatchAlarmIdentifier.Region = aws.String(v.(string)) + } + + healthConfig.AlarmIdentifier = cloudwatchAlarmIdentifier + + if v, ok := d.GetOk("insufficient_data_health_status"); ok { + healthConfig.InsufficientDataHealthStatus = aws.String(v.(string)) + } + } + input := &route53.CreateHealthCheckInput{ CallerReference: aws.String(time.Now().Format(time.RFC3339Nano)), HealthCheckConfig: healthConfig, @@ -252,6 +299,12 @@ func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) d.Set("invert_healthcheck", updated.Inverted) d.Set("child_healthchecks", updated.ChildHealthChecks) d.Set("child_health_threshold", updated.HealthThreshold) + d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus) + + if updated.AlarmIdentifier != nil { + d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name) + d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region) + } // read the tags req := &route53.ListTagsForResourceInput{ diff --git a/builtin/providers/aws/resource_aws_route53_health_check_test.go b/builtin/providers/aws/resource_aws_route53_health_check_test.go index 9792ac10f..e18965546 100644 --- a/builtin/providers/aws/resource_aws_route53_health_check_test.go +++ b/builtin/providers/aws/resource_aws_route53_health_check_test.go @@ -73,6 +73,24 @@ func TestAccAWSRoute53HealthCheck_IpConfig(t *testing.T) { }) } +func TestAccAWSRoute53HealthCheck_CloudWatchAlarmCheck(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRoute53HealthCheckDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRoute53HealthCheckCloudWatchAlarm, + Check: resource.ComposeTestCheckFunc( + testAccCheckRoute53HealthCheckExists("aws_route53_health_check.foo"), + resource.TestCheckResourceAttr( + "aws_route53_health_check.foo", "cloudwatch_alarm_name", "cloudwatch-healthcheck-alarm"), + ), + }, + }, + }) +} + func testAccCheckRoute53HealthCheckDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).r53conn @@ -208,3 +226,24 @@ resource "aws_route53_health_check" "foo" { } } ` + +const testAccRoute53HealthCheckCloudWatchAlarm = ` +resource "aws_cloudwatch_metric_alarm" "foobar" { + alarm_name = "cloudwatch-healthcheck-alarm" + 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" +} + +resource "aws_route53_health_check" "foo" { + type = "CLOUDWATCH_METRIC" + cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.foobar.alarm_name}" + cloudwatch_alarm_region = "us-west-2" + insufficient_data_health_status = "Healthy" +} +` diff --git a/website/source/docs/providers/aws/r/route53_health_check.html.markdown b/website/source/docs/providers/aws/r/route53_health_check.html.markdown index 6d2c66a5c..283e978d0 100644 --- a/website/source/docs/providers/aws/r/route53_health_check.html.markdown +++ b/website/source/docs/providers/aws/r/route53_health_check.html.markdown @@ -36,6 +36,29 @@ resource "aws_route53_health_check" "foo" { } ``` +## CloudWatch Alarm Example + +``` +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" +} + +resource "aws_route53_health_check" "foo" { + type = "CLOUDWATCH_METRIC" + cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.foobar.alarm_name}" + cloudwatch_alarm_region = "us-west-2" + insufficient_data_health_status = "Healthy" +} +``` + ## Argument Reference The following arguments are supported: @@ -43,7 +66,7 @@ The following arguments are supported: * `fqdn` - (Optional) The fully qualified domain name of the endpoint to be checked. * `ip_address` - (Optional) The IP address of the endpoint to be checked. * `port` - (Optional) The port of the endpoint to be checked. -* `type` - (Required) The protocol to use when performing health checks. Valid values are `HTTP`, `HTTPS`, `HTTP_STR_MATCH`, `HTTPS_STR_MATCH`, `TCP` and `CALCULATED`. +* `type` - (Required) The protocol to use when performing health checks. Valid values are `HTTP`, `HTTPS`, `HTTP_STR_MATCH`, `HTTPS_STR_MATCH`, `TCP`, `CALCULATED` and `CLOUDWATCH_METRIC`. * `failure_threshold` - (Required) The number of consecutive health checks that an endpoint must pass or fail. * `request_interval` - (Required) The number of seconds between the time that Amazon Route 53 gets a response from your endpoint and the time that it sends the next health-check request. * `resource_path` - (Optional) The path that you want Amazon Route 53 to request when performing health checks. @@ -52,6 +75,10 @@ The following arguments are supported: * `invert_healthcheck` - (Optional) A boolean value that indicates whether the status of health check should be inverted. For example, if a health check is healthy but Inverted is True , then Route 53 considers the health check to be unhealthy. * `child_healthchecks` - (Optional) For a specified parent health check, a list of HealthCheckId values for the associated child health checks. * `child_health_threshold` - (Optional) The minimum number of child health checks that must be healthy for Route 53 to consider the parent health check to be healthy. Valid values are integers between 0 and 256, inclusive +* `cloudwatch_alarm_name` - (Optional) The name of the CloudWatch alarm. +* `cloudwatch_alarm_region` - (Optional) The CloudWatchRegion that the CloudWatch alarm was created in. +* `insufficient_data_health_status` - (Optional) The status of the health check when CloudWatch has insufficient data about the state of associated alarm. Valid values are `Healthy` , `Unhealthy` and `LastKnownStatus`. + * `tags` - (Optional) A mapping of tags to assign to the health check. At least one of either `fqdn` or `ip_address` must be specified.