From 4d5833450adf9a699f57c44adaa9335fe2f6047f Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Sat, 4 Sep 2021 15:46:15 +0300 Subject: [PATCH 1/9] allow updating ip address + sweeper --- aws/resource_aws_route53_health_check.go | 124 ++++++++++-------- aws/resource_aws_route53_health_check_test.go | 70 ++++++++++ 2 files changed, 141 insertions(+), 53 deletions(-) diff --git a/aws/resource_aws_route53_health_check.go b/aws/resource_aws_route53_health_check.go index c5b9f6bfe59..8ff824251b1 100644 --- a/aws/resource_aws_route53_health_check.go +++ b/aws/resource_aws_route53_health_check.go @@ -42,7 +42,7 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { "failure_threshold": { Type: schema.TypeInt, Optional: true, - Computed: true, + Default: 3, ValidateFunc: validation.IntBetween(1, 10), }, "request_interval": { @@ -54,7 +54,6 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { "ip_address": { Type: schema.TypeString, Optional: true, - ForceNew: true, ValidateFunc: validation.IsIPAddress, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { return net.ParseIP(old).Equal(net.ParseIP(new)) @@ -144,9 +143,22 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { "regions": { Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, + MinItems: 3, + MaxItems: 64, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "us-east-1", + "us-west-1", + "us-west-2", + "eu-west-1", + "ap-southeast-1", + "ap-southeast-2", + "ap-northeast-1", + "sa-east-1", + }, true), + }, Optional: true, - Set: schema.HashString, }, "disabled": { @@ -173,70 +185,76 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).r53conn - updateHealthCheck := &route53.UpdateHealthCheckInput{ - HealthCheckId: aws.String(d.Id()), - } + if d.HasChangeExcept("tags_all") { + updateHealthCheck := &route53.UpdateHealthCheckInput{ + HealthCheckId: aws.String(d.Id()), + } - if d.HasChange("failure_threshold") { - updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int))) - } + if d.HasChange("failure_threshold") { + updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int))) + } - if d.HasChange("fqdn") { - updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string)) - } + if d.HasChange("fqdn") { + updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string)) + } - if d.HasChange("port") { - updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int))) - } + if d.HasChange("port") { + updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int))) + } - if d.HasChange("resource_path") { - updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string)) - } + if d.HasChange("resource_path") { + updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string)) + } - if d.HasChange("invert_healthcheck") { - updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool)) - } + if d.HasChange("invert_healthcheck") { + updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool)) + } - if d.HasChange("child_healthchecks") { - updateHealthCheck.ChildHealthChecks = expandStringSet(d.Get("child_healthchecks").(*schema.Set)) + if d.HasChange("child_healthchecks") { + updateHealthCheck.ChildHealthChecks = expandStringSet(d.Get("child_healthchecks").(*schema.Set)) + } - } - if d.HasChange("child_health_threshold") { - updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) - } + if d.HasChange("child_health_threshold") { + updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) + } - if d.HasChange("search_string") { - updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string)) - } + if d.HasChange("search_string") { + updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string)) + } - if d.HasChanges("cloudwatch_alarm_name", "cloudwatch_alarm_region") { - cloudwatchAlarm := &route53.AlarmIdentifier{ - Name: aws.String(d.Get("cloudwatch_alarm_name").(string)), - Region: aws.String(d.Get("cloudwatch_alarm_region").(string)), + if d.HasChanges("cloudwatch_alarm_name", "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 } - updateHealthCheck.AlarmIdentifier = cloudwatchAlarm - } + if d.HasChange("insufficient_data_health_status") { + updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string)) + } - if d.HasChange("insufficient_data_health_status") { - updateHealthCheck.InsufficientDataHealthStatus = aws.String(d.Get("insufficient_data_health_status").(string)) - } + if d.HasChange("enable_sni") { + updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool)) + } - if d.HasChange("enable_sni") { - updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool)) - } + if d.HasChange("regions") { + updateHealthCheck.Regions = expandStringSet(d.Get("regions").(*schema.Set)) + } - if d.HasChange("regions") { - updateHealthCheck.Regions = expandStringSet(d.Get("regions").(*schema.Set)) - } + if d.HasChange("disabled") { + updateHealthCheck.Disabled = aws.Bool(d.Get("disabled").(bool)) + } - if d.HasChange("disabled") { - updateHealthCheck.Disabled = aws.Bool(d.Get("disabled").(bool)) - } + if d.HasChange("ip_address") { + updateHealthCheck.IPAddress = aws.String(d.Get("ip_address").(string)) + } - _, err := conn.UpdateHealthCheck(updateHealthCheck) - if err != nil { - return err + _, err := conn.UpdateHealthCheck(updateHealthCheck) + if err != nil { + return fmt.Errorf("error updating Route53 Health Check (%s): %w", d.Id(), err) + } } if d.HasChange("tags_all") { @@ -356,7 +374,7 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ resp, err := conn.CreateHealthCheck(input) if err != nil { - return err + return fmt.Errorf("error creating Route53 Health Check (%s): %w", d.Id(), err) } d.SetId(aws.StringValue(resp.HealthCheck.Id)) diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index b3a59ce1423..f93d14acb58 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -1,18 +1,81 @@ package aws import ( + "context" "fmt" + "log" "regexp" "strings" "testing" + "time" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/service/route53" + multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) +func init() { + resource.AddTestSweepers("aws_route53_health_check", &resource.Sweeper{ + Name: "aws_route53_health_check", + F: testSweepRoute53Healthchecks, + }) +} + +func testSweepRoute53Healthchecks(region string) error { + client, err := sharedClientForRegion(region) + + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + + conn := client.(*AWSClient).r53conn + sweepResources := make([]*testSweepResource, 0) + var errs *multierror.Error + + input := &route53.ListHealthChecksInput{} + + err = conn.ListHealthChecksPages(input, func(page *route53.ListHealthChecksOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, detail := range page.HealthChecks { + if detail == nil { + continue + } + + id := aws.StringValue(detail.Id) + + r := resourceAwsRoute53HealthCheck() + d := r.Data(nil) + d.SetId(id) + + sweepResources = append(sweepResources, NewTestSweepResource(r, d, client)) + } + + return !lastPage + }) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error describing Route53 Health Checks for %s: %w", region, err)) + } + + if err = testSweepResourceOrchestratorContext(context.Background(), sweepResources, 0*time.Minute, 1*time.Minute, 10*time.Second, 18*time.Second, 10*time.Minute); err != nil { + errs = multierror.Append(errs, fmt.Errorf("error sweeping Route53 Health Checks for %s: %w", region, err)) + } + + if testSweepSkipSweepError(errs.ErrorOrNil()) { + log.Printf("[WARN] Skipping Route53 Health Checks sweep for %s: %s", region, errs) + return nil + } + + return errs.ErrorOrNil() +} + func TestAccAWSRoute53HealthCheck_basic(t *testing.T) { var check route53.HealthCheck resourceName := "aws_route53_health_check.test" @@ -197,6 +260,13 @@ func TestAccAWSRoute53HealthCheck_IpConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccRoute53HealthCheckIpConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRoute53HealthCheckExists(resourceName, &check), + resource.TestCheckResourceAttr(resourceName, "ip_address", "1.2.3.5"), + ), + }, }, }) } From 2118ab83f7c51d2688e327c3af2d21d1ea97bd64 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Sat, 4 Sep 2021 16:11:21 +0300 Subject: [PATCH 2/9] DRY tests configs --- aws/resource_aws_route53_health_check_test.go | 100 ++++-------------- 1 file changed, 20 insertions(+), 80 deletions(-) diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index f93d14acb58..790c10d4906 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -166,7 +166,7 @@ func TestAccAWSRoute53HealthCheck_withSearchString(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckConfigWithSearchString, + Config: testAccRoute53HealthCheckSearchStringConfig("OK"), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "invert_healthcheck", "false"), @@ -179,7 +179,7 @@ func TestAccAWSRoute53HealthCheck_withSearchString(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckConfigWithSearchStringUpdate, + Config: testAccRoute53HealthCheckSearchStringConfig("FAILED"), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "invert_healthcheck", "true"), @@ -249,7 +249,7 @@ func TestAccAWSRoute53HealthCheck_IpConfig(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckIpConfig, + Config: testAccRoute53HealthCheckIpConfig("1.2.3.4"), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "ip_address", "1.2.3.4"), @@ -261,7 +261,7 @@ func TestAccAWSRoute53HealthCheck_IpConfig(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckIpConfig, + Config: testAccRoute53HealthCheckIpConfig("1.2.3.5"), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "ip_address", "1.2.3.5"), @@ -281,7 +281,7 @@ func TestAccAWSRoute53HealthCheck_Ipv6Config(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckIpv6Config, + Config: testAccRoute53HealthCheckIpConfig("1234:5678:9abc:6811:0:0:0:4"), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "ip_address", "1234:5678:9abc:6811:0:0:0:4"), @@ -293,7 +293,7 @@ func TestAccAWSRoute53HealthCheck_Ipv6Config(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckIpv6ExpandedConfig, + Config: testAccRoute53HealthCheckIpConfig("1234:5678:9abc:6811:0:0:0:4"), PlanOnly: true, }, }, @@ -347,14 +347,14 @@ func TestAccAWSRoute53HealthCheck_withSNI(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckConfigWithSNIDisabled, + Config: testAccRoute53HealthCheckSNIConfig(false), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "enable_sni", "false"), ), }, { - Config: testAccRoute53HealthCheckConfigWithSNI, + Config: testAccRoute53HealthCheckSNIConfig(true), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "enable_sni", "true"), @@ -577,9 +577,10 @@ resource "aws_route53_health_check" "test" { } ` -const testAccRoute53HealthCheckIpConfig = ` +func testAccRoute53HealthCheckIpConfig(ip string) string { + return fmt.Sprintf(` resource "aws_route53_health_check" "test" { - ip_address = "1.2.3.4" + ip_address = %[1]q port = 80 type = "HTTP" resource_path = "/" @@ -590,37 +591,8 @@ resource "aws_route53_health_check" "test" { Name = "tf-test-health-check" } } -` - -const testAccRoute53HealthCheckIpv6Config = ` -resource "aws_route53_health_check" "test" { - ip_address = "1234:5678:9abc:6811::4" - port = 80 - type = "HTTP" - resource_path = "/" - failure_threshold = "2" - request_interval = "30" - - tags = { - Name = "tf-test-health-check" - } +`, ip) } -` - -const testAccRoute53HealthCheckIpv6ExpandedConfig = ` -resource "aws_route53_health_check" "test" { - ip_address = "1234:5678:9abc:6811:0:0:0:4" - port = 80 - type = "HTTP" - resource_path = "/" - failure_threshold = "2" - request_interval = "30" - - tags = { - Name = "tf-test-health-check" - } -} -` const testAccRoute53HealthCheckConfig_withChildHealthChecks = ` resource "aws_route53_health_check" "child1" { @@ -685,7 +657,8 @@ resource "aws_route53_health_check" "test" { } ` -const testAccRoute53HealthCheckConfigWithSearchString = ` +func testAccRoute53HealthCheckSearchStringConfig(search string) string { + return fmt.Sprintf(` resource "aws_route53_health_check" "test" { fqdn = "dev.example.com" port = 80 @@ -695,31 +668,14 @@ resource "aws_route53_health_check" "test" { request_interval = "30" measure_latency = true invert_healthcheck = false - search_string = "OK" + search_string = %[1]q tags = { Name = "tf-test-health-check" } } -` - -const testAccRoute53HealthCheckConfigWithSearchStringUpdate = ` -resource "aws_route53_health_check" "test" { - fqdn = "dev.example.com" - port = 80 - type = "HTTP_STR_MATCH" - resource_path = "/" - failure_threshold = "5" - request_interval = "30" - measure_latency = true - invert_healthcheck = true - search_string = "FAILED" - - tags = { - Name = "tf-test-health-check" - } +`, search) } -` const testAccRoute53HealthCheckConfigWithoutSNI = ` resource "aws_route53_health_check" "test" { @@ -738,7 +694,8 @@ resource "aws_route53_health_check" "test" { } ` -const testAccRoute53HealthCheckConfigWithSNI = ` +func testAccRoute53HealthCheckSNIConfig(enable bool) string { + return fmt.Sprintf(` resource "aws_route53_health_check" "test" { fqdn = "dev.example.com" port = 443 @@ -748,31 +705,14 @@ resource "aws_route53_health_check" "test" { request_interval = "30" measure_latency = true invert_healthcheck = true - enable_sni = true + enable_sni = %[1]t tags = { Name = "tf-test-health-check" } } -` - -const testAccRoute53HealthCheckConfigWithSNIDisabled = ` -resource "aws_route53_health_check" "test" { - fqdn = "dev.example.com" - port = 443 - type = "HTTPS" - resource_path = "/" - failure_threshold = "2" - request_interval = "30" - measure_latency = true - invert_healthcheck = true - enable_sni = false - - tags = { - Name = "tf-test-health-check" - } +`, enable) } -` func testAccRoute53HealthCheckConfigDisabled(disabled bool) string { return fmt.Sprintf(` From 142226a4b46fb7c52aa5b9ff968aca2a1bb61aa1 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Sat, 4 Sep 2021 16:34:43 +0300 Subject: [PATCH 3/9] changelog --- .changelog/20795.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/20795.txt diff --git a/.changelog/20795.txt b/.changelog/20795.txt new file mode 100644 index 00000000000..e8a7c3a5320 --- /dev/null +++ b/.changelog/20795.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource_aws_route53_health_check: Add plan time validation for `regions`. +``` + +```release-note:bug +resource_aws_route53_health_check: fix update for `ip_address` +``` \ No newline at end of file From 0482e4defe860905bedaa50c860817ccb4f61b62 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Sat, 4 Sep 2021 16:40:23 +0300 Subject: [PATCH 4/9] hardcoded regions --- aws/resource_aws_route53_health_check.go | 19 ++++----- aws/resource_aws_route53_health_check_test.go | 39 +++++++------------ 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/aws/resource_aws_route53_health_check.go b/aws/resource_aws_route53_health_check.go index 8ff824251b1..1b3de4127ee 100644 --- a/aws/resource_aws_route53_health_check.go +++ b/aws/resource_aws_route53_health_check.go @@ -8,6 +8,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/service/route53" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -42,7 +43,7 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { "failure_threshold": { Type: schema.TypeInt, Optional: true, - Default: 3, + Computed: true, ValidateFunc: validation.IntBetween(1, 10), }, "request_interval": { @@ -148,14 +149,14 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: validation.StringInSlice([]string{ - "us-east-1", - "us-west-1", - "us-west-2", - "eu-west-1", - "ap-southeast-1", - "ap-southeast-2", - "ap-northeast-1", - "sa-east-1", + endpoints.UsWest1RegionID, + endpoints.UsWest2RegionID, + endpoints.UsEast1RegionID, + endpoints.EuWest1RegionID, + endpoints.SaEast1RegionID, + endpoints.ApSoutheast1RegionID, + endpoints.ApSoutheast2RegionID, + endpoints.ApNortheast1RegionID, }, true), }, Optional: true, diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index 790c10d4906..e58f3e74a50 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -86,12 +86,13 @@ func TestAccAWSRoute53HealthCheck_basic(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckConfig, + Config: testAccRoute53HealthCheckConfigBasic("2", true), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), testAccMatchResourceAttrGlobalARNNoAccount(resourceName, "arn", "route53", regexp.MustCompile("healthcheck/.+")), resource.TestCheckResourceAttr(resourceName, "measure_latency", "true"), resource.TestCheckResourceAttr(resourceName, "port", "80"), + resource.TestCheckResourceAttr(resourceName, "failure_threshold", "2"), resource.TestCheckResourceAttr(resourceName, "invert_healthcheck", "true"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), @@ -102,7 +103,7 @@ func TestAccAWSRoute53HealthCheck_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckConfigUpdate, + Config: testAccRoute53HealthCheckConfigBasic("5", false), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "failure_threshold", "5"), @@ -166,7 +167,7 @@ func TestAccAWSRoute53HealthCheck_withSearchString(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckSearchStringConfig("OK"), + Config: testAccRoute53HealthCheckSearchStringConfig("OK", false), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "invert_healthcheck", "false"), @@ -179,7 +180,7 @@ func TestAccAWSRoute53HealthCheck_withSearchString(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRoute53HealthCheckSearchStringConfig("FAILED"), + Config: testAccRoute53HealthCheckSearchStringConfig("FAILED", true), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), resource.TestCheckResourceAttr(resourceName, "invert_healthcheck", "true"), @@ -440,7 +441,7 @@ func TestAccAWSRoute53HealthCheck_disappears(t *testing.T) { CheckDestroy: testAccCheckRoute53HealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccRoute53HealthCheckConfig, + Config: testAccRoute53HealthCheckConfigBasic("2", true), Check: resource.ComposeTestCheckFunc( testAccCheckRoute53HealthCheckExists(resourceName, &check), testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute53HealthCheck(), resourceName), @@ -512,18 +513,19 @@ func testAccCheckRoute53HealthCheckExists(n string, hCheck *route53.HealthCheck) } } -const testAccRoute53HealthCheckConfig = ` +func testAccRoute53HealthCheckConfigBasic(thershold string, invert bool) string { + return fmt.Sprintf(` resource "aws_route53_health_check" "test" { fqdn = "dev.example.com" port = 80 type = "HTTP" resource_path = "/" - failure_threshold = "2" + failure_threshold = %[1]q request_interval = "30" measure_latency = true - invert_healthcheck = true } -` +`, thershold, invert) +} func testAccRoute53HealthCheckConfigTags1(tag1Key, tag1Value string) string { return fmt.Sprintf(` @@ -564,19 +566,6 @@ resource "aws_route53_health_check" "test" { `, tag1Key, tag1Value, tagKey2, tagValue2) } -const testAccRoute53HealthCheckConfigUpdate = ` -resource "aws_route53_health_check" "test" { - fqdn = "dev.example.com" - port = 80 - type = "HTTP" - resource_path = "/" - failure_threshold = "5" - request_interval = "30" - measure_latency = true - invert_healthcheck = false -} -` - func testAccRoute53HealthCheckIpConfig(ip string) string { return fmt.Sprintf(` resource "aws_route53_health_check" "test" { @@ -657,7 +646,7 @@ resource "aws_route53_health_check" "test" { } ` -func testAccRoute53HealthCheckSearchStringConfig(search string) string { +func testAccRoute53HealthCheckSearchStringConfig(search string, invert bool) string { return fmt.Sprintf(` resource "aws_route53_health_check" "test" { fqdn = "dev.example.com" @@ -667,14 +656,14 @@ resource "aws_route53_health_check" "test" { failure_threshold = "2" request_interval = "30" measure_latency = true - invert_healthcheck = false + invert_healthcheck = %[2]t search_string = %[1]q tags = { Name = "tf-test-health-check" } } -`, search) +`, search, invert) } const testAccRoute53HealthCheckConfigWithoutSNI = ` From 0c026bf70dec2e07469cf3b07a6d32ef65c369f1 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Sat, 4 Sep 2021 16:56:11 +0300 Subject: [PATCH 5/9] hardcoded regions --- aws/resource_aws_route53_health_check_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index e58f3e74a50..3d183c08ba3 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -523,6 +523,7 @@ resource "aws_route53_health_check" "test" { failure_threshold = %[1]q request_interval = "30" measure_latency = true + invert_healthcheck = %[2]t } `, thershold, invert) } From 70462d4a852e3b58834d79306c73c667798d040b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Sep 2021 10:02:59 -0400 Subject: [PATCH 6/9] Tweak CHANGELOG entries. --- .changelog/20795.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changelog/20795.txt b/.changelog/20795.txt index e8a7c3a5320..4aaf1f5f128 100644 --- a/.changelog/20795.txt +++ b/.changelog/20795.txt @@ -1,7 +1,7 @@ ```release-note:enhancement -resource_aws_route53_health_check: Add plan time validation for `regions`. +resource/aws_route53_health_check: Add plan time validation for `regions` ``` ```release-note:bug -resource_aws_route53_health_check: fix update for `ip_address` +resource/aws_route53_health_check: Fix update for `ip_address` ``` \ No newline at end of file From aa550f84f53f534b08cc7c012974b9effbb1c7e2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Sep 2021 10:08:31 -0400 Subject: [PATCH 7/9] Correct non-tags change detection (#20868). --- aws/resource_aws_route53_health_check.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_route53_health_check.go b/aws/resource_aws_route53_health_check.go index 1b3de4127ee..74a79ff9cea 100644 --- a/aws/resource_aws_route53_health_check.go +++ b/aws/resource_aws_route53_health_check.go @@ -186,7 +186,7 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).r53conn - if d.HasChangeExcept("tags_all") { + if d.HasChangesExcept("tags", "tags_all") { updateHealthCheck := &route53.UpdateHealthCheckInput{ HealthCheckId: aws.String(d.Id()), } @@ -253,6 +253,7 @@ func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{ } _, err := conn.UpdateHealthCheck(updateHealthCheck) + if err != nil { return fmt.Errorf("error updating Route53 Health Check (%s): %w", d.Id(), err) } @@ -465,8 +466,9 @@ func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) func resourceAwsRoute53HealthCheckDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).r53conn - log.Printf("[DEBUG] Deleting Route53 health check: %s", d.Id()) + log.Printf("[DEBUG] Deleting Route53 Health Check: %s", d.Id()) _, err := conn.DeleteHealthCheck(&route53.DeleteHealthCheckInput{HealthCheckId: aws.String(d.Id())}) + if isAWSErr(err, route53.ErrCodeNoSuchHealthCheck, "") { return nil } From c4a91839534ef9e1ac72586a4dae6bffb5e53af1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Sep 2021 10:40:27 -0400 Subject: [PATCH 8/9] r/aws_route53_health_check: Use internal finder package. --- aws/internal/service/route53/finder/finder.go | 24 ++ aws/resource_aws_route53_health_check.go | 272 +++++++++--------- aws/resource_aws_route53_health_check_test.go | 46 ++- 3 files changed, 177 insertions(+), 165 deletions(-) diff --git a/aws/internal/service/route53/finder/finder.go b/aws/internal/service/route53/finder/finder.go index 7273c85ead6..bbd8b9e43db 100644 --- a/aws/internal/service/route53/finder/finder.go +++ b/aws/internal/service/route53/finder/finder.go @@ -5,9 +5,33 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/route53" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" tfroute53 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/route53" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) +func HealthCheckByID(conn *route53.Route53, id string) (*route53.HealthCheck, error) { + input := &route53.GetHealthCheckInput{ + HealthCheckId: aws.String(id), + } + + output, err := conn.GetHealthCheck(input) + + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchHealthCheck) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if output == nil || output.HealthCheck == nil || output.HealthCheck.HealthCheckConfig == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.HealthCheck, nil +} + func HostedZoneDnssec(conn *route53.Route53, hostedZoneID string) (*route53.GetDNSSECOutput, error) { input := &route53.GetDNSSECInput{ HostedZoneId: aws.String(hostedZoneID), diff --git a/aws/resource_aws_route53_health_check.go b/aws/resource_aws_route53_health_check.go index 74a79ff9cea..377475a858a 100644 --- a/aws/resource_aws_route53_health_check.go +++ b/aws/resource_aws_route53_health_check.go @@ -10,10 +10,13 @@ import ( "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/service/route53" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/route53/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func resourceAwsRoute53HealthCheck() *schema.Resource { @@ -183,100 +186,14 @@ func resourceAwsRoute53HealthCheck() *schema.Resource { } } -func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).r53conn - - if d.HasChangesExcept("tags", "tags_all") { - updateHealthCheck := &route53.UpdateHealthCheckInput{ - HealthCheckId: aws.String(d.Id()), - } - - if d.HasChange("failure_threshold") { - updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int))) - } - - if d.HasChange("fqdn") { - updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string)) - } - - if d.HasChange("port") { - updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int))) - } - - if d.HasChange("resource_path") { - updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string)) - } - - if d.HasChange("invert_healthcheck") { - updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool)) - } - - if d.HasChange("child_healthchecks") { - updateHealthCheck.ChildHealthChecks = expandStringSet(d.Get("child_healthchecks").(*schema.Set)) - } - - if d.HasChange("child_health_threshold") { - updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) - } - - if d.HasChange("search_string") { - updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string)) - } - - if d.HasChanges("cloudwatch_alarm_name", "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)) - } - - if d.HasChange("enable_sni") { - updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool)) - } - - if d.HasChange("regions") { - updateHealthCheck.Regions = expandStringSet(d.Get("regions").(*schema.Set)) - } - - if d.HasChange("disabled") { - updateHealthCheck.Disabled = aws.Bool(d.Get("disabled").(bool)) - } - - if d.HasChange("ip_address") { - updateHealthCheck.IPAddress = aws.String(d.Get("ip_address").(string)) - } - - _, err := conn.UpdateHealthCheck(updateHealthCheck) - - if err != nil { - return fmt.Errorf("error updating Route53 Health Check (%s): %w", d.Id(), err) - } - } - - if d.HasChange("tags_all") { - o, n := d.GetChange("tags_all") - - if err := keyvaluetags.Route53UpdateTags(conn, d.Id(), route53.TagResourceTypeHealthcheck, o, n); err != nil { - return fmt.Errorf("error updating Route53 Health Check (%s) tags: %w", d.Id(), err) - } - } - - return resourceAwsRoute53HealthCheckRead(d, meta) -} - func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).r53conn defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) + healthCheckType := d.Get("type").(string) healthConfig := &route53.HealthCheckConfig{ - Type: aws.String(d.Get("type").(string)), + Type: aws.String(healthCheckType), } if v, ok := d.GetOk("request_interval"); ok { @@ -307,12 +224,6 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ healthConfig.ResourcePath = aws.String(v.(string)) } - if *healthConfig.Type != route53.HealthCheckTypeCalculated && *healthConfig.Type != route53.HealthCheckTypeCloudwatchMetric { - if v, ok := d.GetOk("measure_latency"); ok { - healthConfig.MeasureLatency = aws.Bool(v.(bool)) - } - } - if v, ok := d.GetOk("invert_healthcheck"); ok { healthConfig.Inverted = aws.Bool(v.(bool)) } @@ -321,7 +232,8 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ healthConfig.EnableSNI = aws.Bool(v.(bool)) } - if *healthConfig.Type == route53.HealthCheckTypeCalculated { + switch healthCheckType { + case route53.HealthCheckTypeCalculated: if v, ok := d.GetOk("child_healthchecks"); ok { healthConfig.ChildHealthChecks = expandStringSet(v.(*schema.Set)) } @@ -329,9 +241,7 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ if v, ok := d.GetOk("child_health_threshold"); ok { healthConfig.HealthThreshold = aws.Int64(int64(v.(int))) } - } - - if *healthConfig.Type == route53.HealthCheckTypeCloudwatchMetric { + case route53.HealthCheckTypeCloudwatchMetric: cloudwatchAlarmIdentifier := &route53.AlarmIdentifier{} if v, ok := d.GetOk("cloudwatch_alarm_name"); ok { @@ -347,6 +257,15 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ if v, ok := d.GetOk("insufficient_data_health_status"); ok { healthConfig.InsufficientDataHealthStatus = aws.String(v.(string)) } + case route53.HealthCheckTypeRecoveryControl: + if v, ok := d.GetOk("routing_control_arn"); ok { + healthConfig.RoutingControlArn = aws.String(v.(string)) + } + fallthrough + default: + if v, ok := d.GetOk("measure_latency"); ok { + healthConfig.MeasureLatency = aws.Bool(v.(bool)) + } } if v, ok := d.GetOk("regions"); ok { @@ -362,12 +281,6 @@ func resourceAwsRoute53HealthCheckCreate(d *schema.ResourceData, meta interface{ healthConfig.Disabled = aws.Bool(v.(bool)) } - if *healthConfig.Type == route53.HealthCheckTypeRecoveryControl { - if v, ok := d.GetOk("routing_control_arn"); ok { - healthConfig.RoutingControlArn = aws.String(v.(string)) - } - } - input := &route53.CreateHealthCheckInput{ CallerReference: aws.String(callerRef), HealthCheckConfig: healthConfig, @@ -393,47 +306,45 @@ func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig - read, err := conn.GetHealthCheck(&route53.GetHealthCheckInput{HealthCheckId: aws.String(d.Id())}) - if err != nil { - if isAWSErr(err, route53.ErrCodeNoSuchHealthCheck, "") { - d.SetId("") - return nil + output, err := finder.HealthCheckByID(conn, d.Id()) - } - return err - } - - if read == nil { + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Route53 Health Check (%s) not found, removing from state", d.Id()) + d.SetId("") return nil } - updated := read.HealthCheck.HealthCheckConfig - d.Set("type", updated.Type) - d.Set("failure_threshold", updated.FailureThreshold) - d.Set("request_interval", updated.RequestInterval) - d.Set("fqdn", updated.FullyQualifiedDomainName) - d.Set("search_string", updated.SearchString) - d.Set("ip_address", updated.IPAddress) - d.Set("port", updated.Port) - d.Set("resource_path", updated.ResourcePath) - d.Set("measure_latency", updated.MeasureLatency) - d.Set("invert_healthcheck", updated.Inverted) - d.Set("disabled", updated.Disabled) - d.Set("routing_control_arn", updated.RoutingControlArn) - - if err := d.Set("child_healthchecks", flattenStringList(updated.ChildHealthChecks)); err != nil { + if err != nil { + return fmt.Errorf("error reading Route53 Health Check (%s): %w", d.Id(), err) + } + + healthCheckConfig := output.HealthCheckConfig + d.Set("type", healthCheckConfig.Type) + d.Set("failure_threshold", healthCheckConfig.FailureThreshold) + d.Set("request_interval", healthCheckConfig.RequestInterval) + d.Set("fqdn", healthCheckConfig.FullyQualifiedDomainName) + d.Set("search_string", healthCheckConfig.SearchString) + d.Set("ip_address", healthCheckConfig.IPAddress) + d.Set("port", healthCheckConfig.Port) + d.Set("resource_path", healthCheckConfig.ResourcePath) + d.Set("measure_latency", healthCheckConfig.MeasureLatency) + d.Set("invert_healthcheck", healthCheckConfig.Inverted) + d.Set("disabled", healthCheckConfig.Disabled) + d.Set("routing_control_arn", healthCheckConfig.RoutingControlArn) + + if err := d.Set("child_healthchecks", flattenStringList(healthCheckConfig.ChildHealthChecks)); err != nil { return fmt.Errorf("error setting child_healthchecks: %w", err) } - d.Set("child_health_threshold", updated.HealthThreshold) - d.Set("insufficient_data_health_status", updated.InsufficientDataHealthStatus) - d.Set("enable_sni", updated.EnableSNI) + d.Set("child_health_threshold", healthCheckConfig.HealthThreshold) + d.Set("insufficient_data_health_status", healthCheckConfig.InsufficientDataHealthStatus) + d.Set("enable_sni", healthCheckConfig.EnableSNI) - d.Set("regions", flattenStringList(updated.Regions)) + d.Set("regions", flattenStringList(healthCheckConfig.Regions)) - if updated.AlarmIdentifier != nil { - d.Set("cloudwatch_alarm_name", updated.AlarmIdentifier.Name) - d.Set("cloudwatch_alarm_region", updated.AlarmIdentifier.Region) + if healthCheckConfig.AlarmIdentifier != nil { + d.Set("cloudwatch_alarm_name", healthCheckConfig.AlarmIdentifier.Name) + d.Set("cloudwatch_alarm_region", healthCheckConfig.AlarmIdentifier.Region) } tags, err := keyvaluetags.Route53ListTags(conn, d.Id(), route53.TagResourceTypeHealthcheck) @@ -463,13 +374,100 @@ func resourceAwsRoute53HealthCheckRead(d *schema.ResourceData, meta interface{}) return nil } +func resourceAwsRoute53HealthCheckUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).r53conn + + if d.HasChangesExcept("tags", "tags_all") { + updateHealthCheck := &route53.UpdateHealthCheckInput{ + HealthCheckId: aws.String(d.Id()), + } + + if d.HasChange("failure_threshold") { + updateHealthCheck.FailureThreshold = aws.Int64(int64(d.Get("failure_threshold").(int))) + } + + if d.HasChange("fqdn") { + updateHealthCheck.FullyQualifiedDomainName = aws.String(d.Get("fqdn").(string)) + } + + if d.HasChange("port") { + updateHealthCheck.Port = aws.Int64(int64(d.Get("port").(int))) + } + + if d.HasChange("resource_path") { + updateHealthCheck.ResourcePath = aws.String(d.Get("resource_path").(string)) + } + + if d.HasChange("invert_healthcheck") { + updateHealthCheck.Inverted = aws.Bool(d.Get("invert_healthcheck").(bool)) + } + + if d.HasChange("child_healthchecks") { + updateHealthCheck.ChildHealthChecks = expandStringSet(d.Get("child_healthchecks").(*schema.Set)) + } + + if d.HasChange("child_health_threshold") { + updateHealthCheck.HealthThreshold = aws.Int64(int64(d.Get("child_health_threshold").(int))) + } + + if d.HasChange("search_string") { + updateHealthCheck.SearchString = aws.String(d.Get("search_string").(string)) + } + + if d.HasChanges("cloudwatch_alarm_name", "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)) + } + + if d.HasChange("enable_sni") { + updateHealthCheck.EnableSNI = aws.Bool(d.Get("enable_sni").(bool)) + } + + if d.HasChange("regions") { + updateHealthCheck.Regions = expandStringSet(d.Get("regions").(*schema.Set)) + } + + if d.HasChange("disabled") { + updateHealthCheck.Disabled = aws.Bool(d.Get("disabled").(bool)) + } + + if d.HasChange("ip_address") { + updateHealthCheck.IPAddress = aws.String(d.Get("ip_address").(string)) + } + + _, err := conn.UpdateHealthCheck(updateHealthCheck) + + if err != nil { + return fmt.Errorf("error updating Route53 Health Check (%s): %w", d.Id(), err) + } + } + + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + + if err := keyvaluetags.Route53UpdateTags(conn, d.Id(), route53.TagResourceTypeHealthcheck, o, n); err != nil { + return fmt.Errorf("error updating Route53 Health Check (%s) tags: %w", d.Id(), err) + } + } + + return resourceAwsRoute53HealthCheckRead(d, meta) +} + func resourceAwsRoute53HealthCheckDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).r53conn log.Printf("[DEBUG] Deleting Route53 Health Check: %s", d.Id()) _, err := conn.DeleteHealthCheck(&route53.DeleteHealthCheckInput{HealthCheckId: aws.String(d.Id())}) - if isAWSErr(err, route53.ErrCodeNoSuchHealthCheck, "") { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchHealthCheck) { return nil } diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index 3d183c08ba3..ddb23a0065e 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -16,6 +16,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/route53/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func init() { @@ -460,56 +462,44 @@ func testAccCheckRoute53HealthCheckDestroy(s *terraform.State) error { continue } - lopts := &route53.ListHealthChecksInput{} - resp, err := conn.ListHealthChecks(lopts) - if err != nil { - return err - } - if len(resp.HealthChecks) == 0 { - return nil - } + _, err := finder.HealthCheckByID(conn, rs.Primary.ID) - for _, check := range resp.HealthChecks { - if *check.Id == rs.Primary.ID { - return fmt.Errorf("Record still exists: %#v", check) - } + if tfresource.NotFound(err) { + continue + } + if err != nil { + return err } + return fmt.Errorf("Route53 Health Check %s still exists", rs.Primary.ID) } + return nil } -func testAccCheckRoute53HealthCheckExists(n string, hCheck *route53.HealthCheck) resource.TestCheckFunc { +func testAccCheckRoute53HealthCheckExists(n string, v *route53.HealthCheck) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).r53conn - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { - return fmt.Errorf("No health check ID is set") + return fmt.Errorf("No Route53 Health Check ID is set") } - lopts := &route53.ListHealthChecksInput{} - resp, err := conn.ListHealthChecks(lopts) + conn := testAccProvider.Meta().(*AWSClient).r53conn + + output, err := finder.HealthCheckByID(conn, rs.Primary.ID) + if err != nil { return err } - if len(resp.HealthChecks) == 0 { - return fmt.Errorf("Health Check does not exist") - } - for _, check := range resp.HealthChecks { - if *check.Id == rs.Primary.ID { - *hCheck = *check - return nil - } + *v = *output - } - return fmt.Errorf("Health Check does not exist") + return nil } } From 833966efe1a8bd414858c5d39c0eb3ed2eb224d0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Sep 2021 10:56:17 -0400 Subject: [PATCH 9/9] Add route53recoverycontrolconfig endpoint check. --- aws/resource_aws_route53_health_check_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_route53_health_check_test.go b/aws/resource_aws_route53_health_check_test.go index ddb23a0065e..c04108d144b 100644 --- a/aws/resource_aws_route53_health_check_test.go +++ b/aws/resource_aws_route53_health_check_test.go @@ -12,6 +12,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/service/route53" + r53rcc "github.com/aws/aws-sdk-go/service/route53recoverycontrolconfig" multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -412,7 +413,7 @@ func TestAccAWSRoute53HealthCheck_withRoutingControlArn(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_route53_health_check.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(r53rcc.EndpointsID, t) }, ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckRoute53HealthCheckDestroy,