From 89eba4d98244b7145ed76d7b16985d15fd5f510e Mon Sep 17 00:00:00 2001 From: Edgar Lopez Date: Wed, 25 Aug 2021 15:21:35 -0600 Subject: [PATCH 1/5] WIP: route53 traffic policy --- aws/internal/service/route53/waiter/waiter.go | 2 + aws/resource_aws_route53_traffic_policy.go | 232 ++++++++++++++++++ ...esource_aws_route53_traffic_policy_test.go | 83 +++++++ .../r/route53_traffic_policy.html.markdown | 57 +++++ 4 files changed, 374 insertions(+) create mode 100644 aws/resource_aws_route53_traffic_policy.go create mode 100644 aws/resource_aws_route53_traffic_policy_test.go create mode 100644 website/docs/r/route53_traffic_policy.html.markdown diff --git a/aws/internal/service/route53/waiter/waiter.go b/aws/internal/service/route53/waiter/waiter.go index 130d3202d1a5..6f87140ab2a6 100644 --- a/aws/internal/service/route53/waiter/waiter.go +++ b/aws/internal/service/route53/waiter/waiter.go @@ -19,6 +19,8 @@ const ( HostedZoneDnssecStatusTimeout = 5 * time.Minute KeySigningKeyStatusTimeout = 5 * time.Minute + + TrafficPolicyTimeout = 5 * time.Minute ) func ChangeInfoStatusInsync(conn *route53.Route53, changeID string) (*route53.ChangeInfo, error) { diff --git a/aws/resource_aws_route53_traffic_policy.go b/aws/resource_aws_route53_traffic_policy.go new file mode 100644 index 000000000000..f2d268501ecb --- /dev/null +++ b/aws/resource_aws_route53_traffic_policy.go @@ -0,0 +1,232 @@ +package aws + +import ( + "context" + "fmt" + "strconv" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "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/service/route53/waiter" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/route53" +) + +func resourceAwsRoute53TrafficPolicy() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceAwsRoute53TrafficPolicyCreate, + ReadWithoutTimeout: resourceAwsRoute53TrafficPolicyRead, + UpdateWithoutTimeout: resourceAwsRoute53TrafficPolicyUpdate, + DeleteWithoutTimeout: resourceAwsRoute53TrafficPolicyDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(0, 512), + }, + "comment": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 1024), + }, + "document": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(0, 102400), + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "version": { + Type: schema.TypeInt, + Computed: true, + }, + }, + } +} + +func resourceAwsRoute53TrafficPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + input := &route53.CreateTrafficPolicyInput{ + Document: aws.String(d.Get("document").(string)), + Name: aws.String(d.Get("name").(string)), + } + + if v, ok := d.GetOk("comment"); ok { + input.Comment = aws.String(v.(string)) + } + + var err error + var output *route53.CreateTrafficPolicyOutput + err = resource.RetryContext(ctx, waiter.TrafficPolicyTimeout, func() *resource.RetryError { + output, err = conn.CreateTrafficPolicyWithContext(ctx, input) + + if err != nil { + return resource.NonRetryableError(err) + } + + return nil + }) + + if isResourceTimeoutError(err) { + output, err = conn.CreateTrafficPolicyWithContext(ctx, input) + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Route53 traffic policy: %w", err)) + } + + d.SetId(fmt.Sprintf("%s/%d", aws.StringValue(output.TrafficPolicy.Id), aws.Int64Value(output.TrafficPolicy.Version))) + + return resourceAwsRoute53TrafficPolicyRead(ctx, d, meta) +} + +func resourceAwsRoute53TrafficPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + id, version, err := decodeTrafficPolicyID(d.Id()) + if err != nil { + return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) + } + + request := &route53.GetTrafficPolicyInput{ + Id: aws.String(id), + Version: aws.Int64(version), + } + + response, err := conn.GetTrafficPolicy(request) + if err != nil { + return diag.FromErr(fmt.Errorf("error getting Route53 Traffic Policy %s, version %d: %w", d.Get("name").(string), d.Get("latest_version").(int), err)) + } + + d.Set("comment", response.TrafficPolicy.Comment) + d.Set("document", response.TrafficPolicy.Document) + d.Set("name", response.TrafficPolicy.Name) + d.Set("type", response.TrafficPolicy.Type) + + return nil +} + +func resourceAwsRoute53TrafficPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + id, version, err := decodeTrafficPolicyID(d.Id()) + if err != nil { + return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) + } + + input := &route53.UpdateTrafficPolicyCommentInput{ + Id: aws.String(id), + Version: aws.Int64(version), + } + + if d.HasChange("comment") { + input.Comment = aws.String(d.Get("comment").(string)) + } + + _, err = conn.UpdateTrafficPolicyCommentWithContext(ctx, input) + if err != nil { + return diag.FromErr(fmt.Errorf("error updating Route53 Traffic Policy: %s. %w", d.Get("name").(string), err)) + } + + return resourceAwsRoute53TrafficPolicyRead(ctx, d, meta) +} + +func resourceAwsRoute53TrafficPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + var versionMarker *string + + var trafficPolicies []*route53.TrafficPolicy + + for allPoliciesListed := false; !allPoliciesListed; { + listRequest := &route53.ListTrafficPolicyVersionsInput{ + Id: aws.String(d.Id()), + } + if versionMarker != nil { + listRequest.TrafficPolicyVersionMarker = versionMarker + } + + listResponse, err := conn.ListTrafficPolicyVersions(listRequest) + if err != nil { + return diag.FromErr(fmt.Errorf("error listing Route 53 Traffic Policy versions: %v", err)) + } + + trafficPolicies = append(trafficPolicies, listResponse.TrafficPolicies...) + + if *listResponse.IsTruncated { + versionMarker = listResponse.TrafficPolicyVersionMarker + } else { + allPoliciesListed = true + } + } + + for _, trafficPolicy := range trafficPolicies { + deleteRequest := &route53.DeleteTrafficPolicyInput{ + Id: trafficPolicy.Id, + Version: trafficPolicy.Version, + } + + _, err := conn.DeleteTrafficPolicy(deleteRequest) + if err != nil { + return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy %s, version %d: %s", *trafficPolicy.Id, *trafficPolicy.Version, err)) + } + } + + return nil +} + +func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPolicyId string) (*route53.TrafficPolicySummary, error) { + var idMarker *string + + for allPoliciesListed := false; !allPoliciesListed; { + input := &route53.ListTrafficPoliciesInput{} + + if idMarker != nil { + input.TrafficPolicyIdMarker = idMarker + } + + listResponse, err := conn.ListTrafficPoliciesWithContext(ctx, input) + if err != nil { + return nil, fmt.Errorf("error listing Route 53 Traffic Policies: %w", err) + } + + for _, summary := range listResponse.TrafficPolicySummaries { + if aws.StringValue(summary.Id) == trafficPolicyId { + return summary, nil + } + } + + if aws.BoolValue(listResponse.IsTruncated) { + idMarker = listResponse.TrafficPolicyIdMarker + } else { + allPoliciesListed = true + } + } + + return nil, nil +} + +func decodeTrafficPolicyID(id string) (string, int64, error) { + idParts := strings.Split(id, "/") + if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { + return "", int64(0), fmt.Errorf("expected ID in the form of id/version, given: %q", id) + } + version, err := strconv.ParseInt(idParts[1], 10, 64) + if err != nil { + return "", int64(0), err + } + + return idParts[0], version, nil +} diff --git a/aws/resource_aws_route53_traffic_policy_test.go b/aws/resource_aws_route53_traffic_policy_test.go new file mode 100644 index 000000000000..dbb0f3f16ebe --- /dev/null +++ b/aws/resource_aws_route53_traffic_policy_test.go @@ -0,0 +1,83 @@ +package aws + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/route53" + "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/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { + resourceName := "aws_route53_traffic_policy.test" + rName := acctest.RandomWithPrefix("") + comment := `{ + "AWSPolicyFormatVersion":"2015-10-01", + "RecordType":"A", + "Endpoints":{ + "endpoint-start-NkPh":{ + "Type":"value", + "Value":"10.0.0.1" + } + }, + "StartEndpoint":"endpoint-start-NkPh" +}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyConfig(rName, comment), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "comment", comment), + resource.TestCheckResourceAttr(resourceName, "version", "1"), + ), + }, + { + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckRoute53TrafficPolicyDestroy(s *terraform.State) error { + return testAccCheckRoute53TrafficPolicyDestroyWithProvider(s, testAccProvider) +} + +func testAccCheckRoute53TrafficPolicyDestroyWithProvider(s *terraform.State, provider *schema.Provider) error { + conn := provider.Meta().(*AWSClient).r53conn + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_route53_traffic_policy" { + continue + } + tp, err := getTrafficPolicyById(context.Background(), conn, rs.Primary.ID) + if err != nil { + return fmt.Errorf("error during check if traffic policy still exists, %#v", err) + } + if tp != nil { + return fmt.Errorf("traffic Policy still exists") + } + } + return nil +} + +func testAccRoute53TrafficPolicyConfig(name, comment string) string { + return fmt.Sprintf(` +resource "aws_route53_traffic_policy" "test" { + name = %[1]q + comment = "comment" + document = <<-EOT +%[2]s +EOT +} +`, name, comment) +} diff --git a/website/docs/r/route53_traffic_policy.html.markdown b/website/docs/r/route53_traffic_policy.html.markdown new file mode 100644 index 000000000000..1160ea32f017 --- /dev/null +++ b/website/docs/r/route53_traffic_policy.html.markdown @@ -0,0 +1,57 @@ +--- +subcategory: "Route53" +layout: "aws" +page_title: "AWS: aws_route53_traffic_policy" +description: |- +Manages a Route53 Traffic Policy +--- + +# Resource: aws_route53_traffic_policy + +Manages a Route53 Traffic Policy. + +## Example Usage + +```hcl +resource "aws_route53_traffic_policy" "example" { + name = "example" + comment = "example comment" + document = < Date: Tue, 31 Aug 2021 11:18:15 -0600 Subject: [PATCH 2/5] refactor --- aws/provider.go | 1 + aws/resource_aws_route53_traffic_policy.go | 68 +++----- ...esource_aws_route53_traffic_policy_test.go | 165 +++++++++++++++--- .../r/route53_traffic_policy.html.markdown | 21 ++- 4 files changed, 184 insertions(+), 71 deletions(-) diff --git a/aws/provider.go b/aws/provider.go index 4bc34a50c3c3..644721f1fdab 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -1007,6 +1007,7 @@ func Provider() *schema.Provider { "aws_route53_resolver_query_log_config_association": resourceAwsRoute53ResolverQueryLogConfigAssociation(), "aws_route53_resolver_rule_association": resourceAwsRoute53ResolverRuleAssociation(), "aws_route53_resolver_rule": resourceAwsRoute53ResolverRule(), + "aws_route53_traffic_policy": resourceAwsRoute53TrafficPolicy(), "aws_route53recoverycontrolconfig_cluster": resourceAwsRoute53RecoveryControlConfigCluster(), "aws_route53recoverycontrolconfig_control_panel": resourceAwsRoute53RecoveryControlConfigControlPanel(), "aws_route53recoverycontrolconfig_routing_control": resourceAwsRoute53RecoveryControlConfigRoutingControl(), diff --git a/aws/resource_aws_route53_traffic_policy.go b/aws/resource_aws_route53_traffic_policy.go index f2d268501ecb..fe20a8aa2383 100644 --- a/aws/resource_aws_route53_traffic_policy.go +++ b/aws/resource_aws_route53_traffic_policy.go @@ -3,17 +3,18 @@ package aws import ( "context" "fmt" + "log" "strconv" "strings" + "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/diag" "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/service/route53/waiter" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/route53" ) func resourceAwsRoute53TrafficPolicy() *schema.Resource { @@ -71,8 +72,11 @@ func resourceAwsRoute53TrafficPolicyCreate(ctx context.Context, d *schema.Resour var output *route53.CreateTrafficPolicyOutput err = resource.RetryContext(ctx, waiter.TrafficPolicyTimeout, func() *resource.RetryError { output, err = conn.CreateTrafficPolicyWithContext(ctx, input) - if err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + resource.RetryableError(err) + } + return resource.NonRetryableError(err) } @@ -106,6 +110,12 @@ func resourceAwsRoute53TrafficPolicyRead(ctx context.Context, d *schema.Resource } response, err := conn.GetTrafficPolicy(request) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + log.Printf("[WARN] Route53 Traffic Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + } + if err != nil { return diag.FromErr(fmt.Errorf("error getting Route53 Traffic Policy %s, version %d: %w", d.Get("name").(string), d.Get("latest_version").(int), err)) } @@ -146,48 +156,28 @@ func resourceAwsRoute53TrafficPolicyUpdate(ctx context.Context, d *schema.Resour func resourceAwsRoute53TrafficPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).r53conn - var versionMarker *string - - var trafficPolicies []*route53.TrafficPolicy - - for allPoliciesListed := false; !allPoliciesListed; { - listRequest := &route53.ListTrafficPolicyVersionsInput{ - Id: aws.String(d.Id()), - } - if versionMarker != nil { - listRequest.TrafficPolicyVersionMarker = versionMarker - } - - listResponse, err := conn.ListTrafficPolicyVersions(listRequest) - if err != nil { - return diag.FromErr(fmt.Errorf("error listing Route 53 Traffic Policy versions: %v", err)) - } - - trafficPolicies = append(trafficPolicies, listResponse.TrafficPolicies...) - - if *listResponse.IsTruncated { - versionMarker = listResponse.TrafficPolicyVersionMarker - } else { - allPoliciesListed = true - } + idTraffic, version, err := decodeTrafficPolicyID(d.Id()) + if err != nil { + return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) } - for _, trafficPolicy := range trafficPolicies { - deleteRequest := &route53.DeleteTrafficPolicyInput{ - Id: trafficPolicy.Id, - Version: trafficPolicy.Version, - } + input := &route53.DeleteTrafficPolicyInput{ + Id: aws.String(idTraffic), + Version: aws.Int64(version), + } - _, err := conn.DeleteTrafficPolicy(deleteRequest) - if err != nil { - return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy %s, version %d: %s", *trafficPolicy.Id, *trafficPolicy.Version, err)) + _, err = conn.DeleteTrafficPolicyWithContext(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + return nil } + return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy %s, version %d: %s", idTraffic, version, err)) } return nil } -func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPolicyId string) (*route53.TrafficPolicySummary, error) { +func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPolicyId string, version int64) (*route53.TrafficPolicySummary, error) { var idMarker *string for allPoliciesListed := false; !allPoliciesListed; { @@ -199,11 +189,11 @@ func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPol listResponse, err := conn.ListTrafficPoliciesWithContext(ctx, input) if err != nil { - return nil, fmt.Errorf("error listing Route 53 Traffic Policies: %w", err) + return nil, err } for _, summary := range listResponse.TrafficPolicySummaries { - if aws.StringValue(summary.Id) == trafficPolicyId { + if aws.StringValue(summary.Id) == trafficPolicyId && aws.Int64Value(summary.LatestVersion) == version { return summary, nil } } diff --git a/aws/resource_aws_route53_traffic_policy_test.go b/aws/resource_aws_route53_traffic_policy_test.go index dbb0f3f16ebe..93cf07968171 100644 --- a/aws/resource_aws_route53_traffic_policy_test.go +++ b/aws/resource_aws_route53_traffic_policy_test.go @@ -6,26 +6,16 @@ import ( "testing" "github.com/aws/aws-sdk-go/service/route53" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "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/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { + var output route53.TrafficPolicySummary resourceName := "aws_route53_traffic_policy.test" rName := acctest.RandomWithPrefix("") - comment := `{ - "AWSPolicyFormatVersion":"2015-10-01", - "RecordType":"A", - "Endpoints":{ - "endpoint-start-NkPh":{ - "Type":"value", - "Value":"10.0.0.1" - } - }, - "StartEndpoint":"endpoint-start-NkPh" -}` resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -34,14 +24,74 @@ func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), Steps: []resource.TestStep{ { - Config: testAccRoute53TrafficPolicyConfig(rName, comment), + Config: testAccRoute53TrafficPolicyConfig(rName), Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyExists(resourceName, &output), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute53TrafficPolicy_disappears(t *testing.T) { + var output route53.TrafficPolicySummary + resourceName := "aws_route53_traffic_policy.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyExists(resourceName, &output), + testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute53TrafficPolicy(), resourceName), + ), + }, + }, + }) +} + +func TestAccAWSRoute53TrafficPolicy_complete(t *testing.T) { + var output route53.TrafficPolicySummary + resourceName := "aws_route53_traffic_policy.test" + rName := acctest.RandomWithPrefix("") + comment := `comment` + commentUpdated := `comment updated` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyConfigComplete(rName, comment), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyExists(resourceName, &output), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "comment", comment), - resource.TestCheckResourceAttr(resourceName, "version", "1"), ), }, { + Config: testAccRoute53TrafficPolicyConfigComplete(rName, commentUpdated), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyExists(resourceName, &output), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "comment", commentUpdated), + ), + }, + { + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, @@ -49,34 +99,103 @@ func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { }) } -func testAccCheckRoute53TrafficPolicyDestroy(s *terraform.State) error { - return testAccCheckRoute53TrafficPolicyDestroyWithProvider(s, testAccProvider) +func testAccCheckAwsRoute53TrafficPolicyExists(resourceName string, trafficPolicy *route53.TrafficPolicySummary) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).r53conn + + idTraffic, version, err := decodeTrafficPolicyID(rs.Primary.ID) + if err != nil { + return fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", rs.Primary.Attributes["name"], err) + } + + resp, err := getTrafficPolicyById(context.Background(), conn, idTraffic, version) + + if err != nil { + return fmt.Errorf("problem checking for traffic policy existence: %w", err) + } + + if resp == nil { + return fmt.Errorf("traffic policy %q does not exist", idTraffic) + } + + *trafficPolicy = *resp + + return nil + } } -func testAccCheckRoute53TrafficPolicyDestroyWithProvider(s *terraform.State, provider *schema.Provider) error { - conn := provider.Meta().(*AWSClient).r53conn +func testAccCheckRoute53TrafficPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).r53conn + for _, rs := range s.RootModule().Resources { if rs.Type != "aws_route53_traffic_policy" { continue } - tp, err := getTrafficPolicyById(context.Background(), conn, rs.Primary.ID) + + idTraffic, version, err := decodeTrafficPolicyID(rs.Primary.ID) + if err != nil { + return fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", rs.Primary.Attributes["name"], err) + } + + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + continue + } + + resp, err := getTrafficPolicyById(context.Background(), conn, idTraffic, version) + if err != nil { return fmt.Errorf("error during check if traffic policy still exists, %#v", err) } - if tp != nil { + if resp != nil { return fmt.Errorf("traffic Policy still exists") } } return nil } -func testAccRoute53TrafficPolicyConfig(name, comment string) string { +func testAccRoute53TrafficPolicyConfig(name string) string { + return fmt.Sprintf(` +resource "aws_route53_traffic_policy" "test" { + name = %[1]q + document = <<-EOT +{ + "AWSPolicyFormatVersion":"2015-10-01", + "RecordType":"A", + "Endpoints":{ + "endpoint-start-NkPh":{ + "Type":"value", + "Value":"10.0.0.1" + } + }, + "StartEndpoint":"endpoint-start-NkPh" +} +EOT +} +`, name) +} + +func testAccRoute53TrafficPolicyConfigComplete(name, comment string) string { return fmt.Sprintf(` resource "aws_route53_traffic_policy" "test" { name = %[1]q - comment = "comment" + comment = %[2]q document = <<-EOT -%[2]s +{ + "AWSPolicyFormatVersion":"2015-10-01", + "RecordType":"A", + "Endpoints":{ + "endpoint-start-NkPh":{ + "Type":"value", + "Value":"10.0.0.1" + } + }, + "StartEndpoint":"endpoint-start-NkPh" +} EOT } `, name, comment) diff --git a/website/docs/r/route53_traffic_policy.html.markdown b/website/docs/r/route53_traffic_policy.html.markdown index 1160ea32f017..6226174f01d8 100644 --- a/website/docs/r/route53_traffic_policy.html.markdown +++ b/website/docs/r/route53_traffic_policy.html.markdown @@ -3,7 +3,7 @@ subcategory: "Route53" layout: "aws" page_title: "AWS: aws_route53_traffic_policy" description: |- -Manages a Route53 Traffic Policy + Manages a Route53 Traffic Policy --- # Resource: aws_route53_traffic_policy @@ -12,7 +12,7 @@ Manages a Route53 Traffic Policy. ## Example Usage -```hcl +```terraform resource "aws_route53_traffic_policy" "example" { name = "example" comment = "example comment" @@ -34,23 +34,26 @@ EOF ## Argument Reference -The following arguments are supported: +The following arguments are required: -* `name` - (Required) This is the name of the traffic policy. -* `comment` - (Optional) A comment for the traffic policy. -* `document` - (Required) The policy document. This is a JSON formatted string. For more information about building Route53 traffic policy documents, see the [AWS Route53 Traffic Policy document format](https://docs.aws.amazon.com/Route53/latest/APIReference/api-policies-traffic-policy-document-format.html) +* `name` - (Required) Name of the traffic policy. +* `document` - (Required) Policy document. This is a JSON formatted string. For more information about building Route53 traffic policy documents, see the [AWS Route53 Traffic Policy document format](https://docs.aws.amazon.com/Route53/latest/APIReference/api-policies-traffic-policy-document-format.html) + +The following arguments are optional: + +* `comment` - (Optional) Comment for the traffic policy. ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `id` - ID of the traffic policy -* `latest_version` - The latest version number of the traffic policy. This value is automatically incremented by AWS after each update of this resource. - +* `version` - Version number of the traffic policy. This value is automatically incremented by AWS after each update of this resource. + ## Import -Route53 Traffic Policy can be imported using the `id` and `latest_version`, e.g. +Route53 Traffic Policy can be imported using the `id` and `version`, e.g. ``` $ terraform import aws_route53_traffic_policy.example 01a52019-d16f-422a-ae72-c306d2b6df7e/1 From 1164aaffd17ee6174d4561be494aafe7f1b50859 Mon Sep 17 00:00:00 2001 From: Edgar Lopez Date: Tue, 31 Aug 2021 15:07:14 -0600 Subject: [PATCH 3/5] fixes bug --- aws/resource_aws_route53_traffic_policy.go | 113 +++++++++++------- ...esource_aws_route53_traffic_policy_test.go | 37 +++--- 2 files changed, 89 insertions(+), 61 deletions(-) diff --git a/aws/resource_aws_route53_traffic_policy.go b/aws/resource_aws_route53_traffic_policy.go index fe20a8aa2383..525a4262b58a 100644 --- a/aws/resource_aws_route53_traffic_policy.go +++ b/aws/resource_aws_route53_traffic_policy.go @@ -24,7 +24,20 @@ func resourceAwsRoute53TrafficPolicy() *schema.Resource { UpdateWithoutTimeout: resourceAwsRoute53TrafficPolicyUpdate, DeleteWithoutTimeout: resourceAwsRoute53TrafficPolicyDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + idParts := strings.Split(d.Id(), "/") + if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { + return nil, fmt.Errorf("unexpected format of ID (%q), expected traffic-policy-id/traffic-policy-version", d.Id()) + } + version, err := strconv.Atoi(idParts[1]) + if err != nil { + return nil, fmt.Errorf("cannot convert to int: %s", idParts[1]) + } + d.Set("version", version) + d.SetId(idParts[0]) + + return []*schema.ResourceData{d}, nil + }, }, Schema: map[string]*schema.Schema{ "name": { @@ -91,7 +104,7 @@ func resourceAwsRoute53TrafficPolicyCreate(ctx context.Context, d *schema.Resour return diag.FromErr(fmt.Errorf("error creating Route53 traffic policy: %w", err)) } - d.SetId(fmt.Sprintf("%s/%d", aws.StringValue(output.TrafficPolicy.Id), aws.Int64Value(output.TrafficPolicy.Version))) + d.SetId(aws.StringValue(output.TrafficPolicy.Id)) return resourceAwsRoute53TrafficPolicyRead(ctx, d, meta) } @@ -99,14 +112,20 @@ func resourceAwsRoute53TrafficPolicyCreate(ctx context.Context, d *schema.Resour func resourceAwsRoute53TrafficPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).r53conn - id, version, err := decodeTrafficPolicyID(d.Id()) + object, err := getTrafficPolicyById(ctx, conn, d.Id()) if err != nil { - return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) + return diag.FromErr(fmt.Errorf("error getting Route53 Traffic Policy %s from ListTrafficPolicies: %w", d.Get("name").(string), err)) + } + + if object == nil { + log.Printf("[WARN] Route53 Traffic Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil } request := &route53.GetTrafficPolicyInput{ - Id: aws.String(id), - Version: aws.Int64(version), + Id: aws.String(d.Id()), + Version: object.LatestVersion, } response, err := conn.GetTrafficPolicy(request) @@ -114,16 +133,18 @@ func resourceAwsRoute53TrafficPolicyRead(ctx context.Context, d *schema.Resource if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { log.Printf("[WARN] Route53 Traffic Policy (%s) not found, removing from state", d.Id()) d.SetId("") + return nil } if err != nil { - return diag.FromErr(fmt.Errorf("error getting Route53 Traffic Policy %s, version %d: %w", d.Get("name").(string), d.Get("latest_version").(int), err)) + return diag.FromErr(fmt.Errorf("error getting Route53 Traffic Policy %s, version %d: %w", d.Get("name").(string), d.Get("version").(int), err)) } d.Set("comment", response.TrafficPolicy.Comment) d.Set("document", response.TrafficPolicy.Document) d.Set("name", response.TrafficPolicy.Name) d.Set("type", response.TrafficPolicy.Type) + d.Set("version", response.TrafficPolicy.Version) return nil } @@ -131,21 +152,16 @@ func resourceAwsRoute53TrafficPolicyRead(ctx context.Context, d *schema.Resource func resourceAwsRoute53TrafficPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).r53conn - id, version, err := decodeTrafficPolicyID(d.Id()) - if err != nil { - return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) - } - - input := &route53.UpdateTrafficPolicyCommentInput{ - Id: aws.String(id), - Version: aws.Int64(version), + input := &route53.CreateTrafficPolicyVersionInput{ + Id: aws.String(d.Id()), + Document: aws.String(d.Get("document").(string)), } if d.HasChange("comment") { input.Comment = aws.String(d.Get("comment").(string)) } - _, err = conn.UpdateTrafficPolicyCommentWithContext(ctx, input) + _, err := conn.CreateTrafficPolicyVersionWithContext(ctx, input) if err != nil { return diag.FromErr(fmt.Errorf("error updating Route53 Traffic Policy: %s. %w", d.Get("name").(string), err)) } @@ -156,28 +172,50 @@ func resourceAwsRoute53TrafficPolicyUpdate(ctx context.Context, d *schema.Resour func resourceAwsRoute53TrafficPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).r53conn - idTraffic, version, err := decodeTrafficPolicyID(d.Id()) - if err != nil { - return diag.FromErr(fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", d.Get("name").(string), err)) - } + var trafficPolicies []*route53.TrafficPolicy + var versionMarker *string - input := &route53.DeleteTrafficPolicyInput{ - Id: aws.String(idTraffic), - Version: aws.Int64(version), - } + for allPoliciesListed := false; !allPoliciesListed; { + listRequest := &route53.ListTrafficPolicyVersionsInput{ + Id: aws.String(d.Id()), + } + if versionMarker != nil { + listRequest.TrafficPolicyVersionMarker = versionMarker + } - _, err = conn.DeleteTrafficPolicyWithContext(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { - return nil + listResponse, err := conn.ListTrafficPolicyVersionsWithContext(ctx, listRequest) + if err != nil { + return diag.FromErr(fmt.Errorf("error listing Route 53 Traffic Policy versions: %v", err)) + } + + trafficPolicies = append(trafficPolicies, listResponse.TrafficPolicies...) + + if aws.BoolValue(listResponse.IsTruncated) { + versionMarker = listResponse.TrafficPolicyVersionMarker + } else { + allPoliciesListed = true } - return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy %s, version %d: %s", idTraffic, version, err)) } + for _, trafficPolicy := range trafficPolicies { + input := &route53.DeleteTrafficPolicyInput{ + Id: trafficPolicy.Id, + Version: trafficPolicy.Version, + } + + _, err := conn.DeleteTrafficPolicyWithContext(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + return nil + } + + return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy %s, version %d: %s", aws.StringValue(trafficPolicy.Id), aws.Int64Value(trafficPolicy.Version), err)) + } + } return nil } -func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPolicyId string, version int64) (*route53.TrafficPolicySummary, error) { +func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPolicyId string) (*route53.TrafficPolicySummary, error) { var idMarker *string for allPoliciesListed := false; !allPoliciesListed; { @@ -193,7 +231,7 @@ func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPol } for _, summary := range listResponse.TrafficPolicySummaries { - if aws.StringValue(summary.Id) == trafficPolicyId && aws.Int64Value(summary.LatestVersion) == version { + if aws.StringValue(summary.Id) == trafficPolicyId { return summary, nil } } @@ -207,16 +245,3 @@ func getTrafficPolicyById(ctx context.Context, conn *route53.Route53, trafficPol return nil, nil } - -func decodeTrafficPolicyID(id string) (string, int64, error) { - idParts := strings.Split(id, "/") - if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { - return "", int64(0), fmt.Errorf("expected ID in the form of id/version, given: %q", id) - } - version, err := strconv.ParseInt(idParts[1], 10, 64) - if err != nil { - return "", int64(0), err - } - - return idParts[0], version, nil -} diff --git a/aws/resource_aws_route53_traffic_policy_test.go b/aws/resource_aws_route53_traffic_policy_test.go index 93cf07968171..006f89b0a9ba 100644 --- a/aws/resource_aws_route53_traffic_policy_test.go +++ b/aws/resource_aws_route53_traffic_policy_test.go @@ -15,7 +15,7 @@ import ( func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { var output route53.TrafficPolicySummary resourceName := "aws_route53_traffic_policy.test" - rName := acctest.RandomWithPrefix("") + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -32,6 +32,7 @@ func TestAccAWSRoute53TrafficPolicy_basic(t *testing.T) { }, { ResourceName: resourceName, + ImportStateIdFunc: testAccAWSRoute53TrafficPolicyImportStateIdFunc(resourceName), ImportState: true, ImportStateVerify: true, }, @@ -56,6 +57,7 @@ func TestAccAWSRoute53TrafficPolicy_disappears(t *testing.T) { testAccCheckAwsRoute53TrafficPolicyExists(resourceName, &output), testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute53TrafficPolicy(), resourceName), ), + ExpectNonEmptyPlan: true, }, }, }) @@ -64,7 +66,7 @@ func TestAccAWSRoute53TrafficPolicy_disappears(t *testing.T) { func TestAccAWSRoute53TrafficPolicy_complete(t *testing.T) { var output route53.TrafficPolicySummary resourceName := "aws_route53_traffic_policy.test" - rName := acctest.RandomWithPrefix("") + rName := acctest.RandomWithPrefix("tf-acc-test") comment := `comment` commentUpdated := `comment updated` @@ -92,6 +94,7 @@ func TestAccAWSRoute53TrafficPolicy_complete(t *testing.T) { }, { ResourceName: resourceName, + ImportStateIdFunc: testAccAWSRoute53TrafficPolicyImportStateIdFunc(resourceName), ImportState: true, ImportStateVerify: true, }, @@ -108,19 +111,14 @@ func testAccCheckAwsRoute53TrafficPolicyExists(resourceName string, trafficPolic conn := testAccProvider.Meta().(*AWSClient).r53conn - idTraffic, version, err := decodeTrafficPolicyID(rs.Primary.ID) - if err != nil { - return fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", rs.Primary.Attributes["name"], err) - } - - resp, err := getTrafficPolicyById(context.Background(), conn, idTraffic, version) + resp, err := getTrafficPolicyById(context.Background(), conn, rs.Primary.ID) if err != nil { return fmt.Errorf("problem checking for traffic policy existence: %w", err) } if resp == nil { - return fmt.Errorf("traffic policy %q does not exist", idTraffic) + return fmt.Errorf("traffic policy %q does not exist", rs.Primary.ID) } *trafficPolicy = *resp @@ -137,17 +135,11 @@ func testAccCheckRoute53TrafficPolicyDestroy(s *terraform.State) error { continue } - idTraffic, version, err := decodeTrafficPolicyID(rs.Primary.ID) - if err != nil { - return fmt.Errorf("error decoding Route53 Traffic Policy %s : %w", rs.Primary.Attributes["name"], err) - } - - if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) { + resp, err := getTrafficPolicyById(context.Background(), conn, rs.Primary.ID) + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicy) || resp == nil { continue } - resp, err := getTrafficPolicyById(context.Background(), conn, idTraffic, version) - if err != nil { return fmt.Errorf("error during check if traffic policy still exists, %#v", err) } @@ -158,6 +150,17 @@ func testAccCheckRoute53TrafficPolicyDestroy(s *terraform.State) error { return nil } +func testAccAWSRoute53TrafficPolicyImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + + return fmt.Sprintf("%s/%s", rs.Primary.Attributes["id"], rs.Primary.Attributes["version"]), nil + } +} + func testAccRoute53TrafficPolicyConfig(name string) string { return fmt.Sprintf(` resource "aws_route53_traffic_policy" "test" { From 78ac9325f073baae58a0df8420d134ef3cdde869 Mon Sep 17 00:00:00 2001 From: Edgar Lopez Date: Tue, 31 Aug 2021 13:44:17 -0600 Subject: [PATCH 4/5] feat: added resource for route53 traffic policy instance and its tests docs --- aws/internal/service/route53/waiter/waiter.go | 3 +- aws/provider.go | 1 + ...rce_aws_route53_traffic_policy_instance.go | 161 +++++++++++++++ ...ws_route53_traffic_policy_instance_test.go | 191 ++++++++++++++++++ ...te53_traffic_policy_instance.html.markdown | 47 +++++ 5 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 aws/resource_aws_route53_traffic_policy_instance.go create mode 100644 aws/resource_aws_route53_traffic_policy_instance_test.go create mode 100644 website/docs/r/route53_traffic_policy_instance.html.markdown diff --git a/aws/internal/service/route53/waiter/waiter.go b/aws/internal/service/route53/waiter/waiter.go index 6f87140ab2a6..6e416d19a819 100644 --- a/aws/internal/service/route53/waiter/waiter.go +++ b/aws/internal/service/route53/waiter/waiter.go @@ -20,7 +20,8 @@ const ( KeySigningKeyStatusTimeout = 5 * time.Minute - TrafficPolicyTimeout = 5 * time.Minute + TrafficPolicyTimeout = 5 * time.Minute + TrafficPolicyInstanceOperationTimeout = 4 * time.Minute ) func ChangeInfoStatusInsync(conn *route53.Route53, changeID string) (*route53.ChangeInfo, error) { diff --git a/aws/provider.go b/aws/provider.go index 644721f1fdab..a285c91a63bc 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -1008,6 +1008,7 @@ func Provider() *schema.Provider { "aws_route53_resolver_rule_association": resourceAwsRoute53ResolverRuleAssociation(), "aws_route53_resolver_rule": resourceAwsRoute53ResolverRule(), "aws_route53_traffic_policy": resourceAwsRoute53TrafficPolicy(), + "aws_route53_traffic_policy_instance": resourceAwsRoute53TrafficPolicyInstance(), "aws_route53recoverycontrolconfig_cluster": resourceAwsRoute53RecoveryControlConfigCluster(), "aws_route53recoverycontrolconfig_control_panel": resourceAwsRoute53RecoveryControlConfigControlPanel(), "aws_route53recoverycontrolconfig_routing_control": resourceAwsRoute53RecoveryControlConfigRoutingControl(), diff --git a/aws/resource_aws_route53_traffic_policy_instance.go b/aws/resource_aws_route53_traffic_policy_instance.go new file mode 100644 index 000000000000..9f58b6f7fd44 --- /dev/null +++ b/aws/resource_aws_route53_traffic_policy_instance.go @@ -0,0 +1,161 @@ +package aws + +import ( + "context" + "fmt" + "log" + + "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/diag" + "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/service/route53/waiter" +) + +func resourceAwsRoute53TrafficPolicyInstance() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceAwsRoute53TrafficPolicyInstanceCreate, + ReadWithoutTimeout: resourceAwsRoute53TrafficPolicyInstanceRead, + UpdateWithoutTimeout: resourceAwsRoute53TrafficPolicyInstanceUpdate, + DeleteWithoutTimeout: resourceAwsRoute53TrafficPolicyInstanceDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "hosted_zone_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 32), + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + "traffic_policy_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 36), + }, + "traffic_policy_version": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 1000), + }, + "ttl": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtMost(2147483647), + }, + }, + } +} + +func resourceAwsRoute53TrafficPolicyInstanceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + input := &route53.CreateTrafficPolicyInstanceInput{ + HostedZoneId: aws.String(d.Get("hosted_zone_id").(string)), + Name: aws.String(d.Get("name").(string)), + TrafficPolicyId: aws.String(d.Get("traffic_policy_id").(string)), + TrafficPolicyVersion: aws.Int64(int64(d.Get("traffic_policy_version").(int))), + TTL: aws.Int64(int64(d.Get("ttl").(int))), + } + + var err error + var output *route53.CreateTrafficPolicyInstanceOutput + err = resource.RetryContext(ctx, waiter.TrafficPolicyInstanceOperationTimeout, func() *resource.RetryError { + output, err = conn.CreateTrafficPolicyInstanceWithContext(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } + + return nil + }) + + if isResourceTimeoutError(err) { + output, err = conn.CreateTrafficPolicyInstanceWithContext(ctx, input) + } + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) + } + + d.SetId(aws.StringValue(output.TrafficPolicyInstance.Id)) + + return resourceAwsRoute53TrafficPolicyInstanceRead(ctx, d, meta) +} + +func resourceAwsRoute53TrafficPolicyInstanceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + input := &route53.GetTrafficPolicyInstanceInput{ + Id: aws.String(d.Id()), + } + + output, err := conn.GetTrafficPolicyInstanceWithContext(ctx, input) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { + log.Printf("[WARN] Route53 Traffic Policy Instance (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) + } + + d.Set("hosted_zone_id", output.TrafficPolicyInstance.HostedZoneId) + d.Set("name", output.TrafficPolicyInstance.Name) + d.Set("traffic_policy_id", output.TrafficPolicyInstance.TrafficPolicyId) + d.Set("traffic_policy_version", output.TrafficPolicyInstance.TrafficPolicyVersion) + d.Set("ttl", output.TrafficPolicyInstance.TTL) + + return nil +} + +func resourceAwsRoute53TrafficPolicyInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + input := &route53.UpdateTrafficPolicyInstanceInput{ + Id: aws.String(d.Id()), + TrafficPolicyId: aws.String(d.Get("traffic_policy_id").(string)), + TrafficPolicyVersion: aws.Int64(int64(d.Get("traffic_policy_version").(int))), + TTL: aws.Int64(int64(d.Get("ttl").(int))), + } + + _, err := conn.UpdateTrafficPolicyInstanceWithContext(ctx, input) + if err != nil { + return diag.FromErr(fmt.Errorf("error updating Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) + } + + return resourceAwsRoute53TrafficPolicyInstanceRead(ctx, d, meta) +} + +func resourceAwsRoute53TrafficPolicyInstanceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).r53conn + + input := &route53.DeleteTrafficPolicyInstanceInput{ + Id: aws.String(d.Id()), + } + + _, err := conn.DeleteTrafficPolicyInstanceWithContext(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { + return nil + } + + return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) + } + + return nil +} diff --git a/aws/resource_aws_route53_traffic_policy_instance_test.go b/aws/resource_aws_route53_traffic_policy_instance_test.go new file mode 100644 index 000000000000..2e8286c1b7e8 --- /dev/null +++ b/aws/resource_aws_route53_traffic_policy_instance_test.go @@ -0,0 +1,191 @@ +package aws + +import ( + "context" + "fmt" + "testing" + + "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/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSRoute53TrafficPolicyInstance_basic(t *testing.T) { + var output route53.GetTrafficPolicyInstanceOutput + resourceName := "aws_route53_traffic_policy_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyInstanceDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute53TrafficPolicyInstance_disappears(t *testing.T) { + var output route53.GetTrafficPolicyInstanceOutput + resourceName := "aws_route53_traffic_policy_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyInstanceDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), + testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute53TrafficPolicyInstance(), resourceName), + ), + }, + }, + }) +} + +func TestAccAWSRoute53TrafficPolicyInstance_complete(t *testing.T) { + var output route53.GetTrafficPolicyInstanceOutput + resourceName := "aws_route53_traffic_policy_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + rNameUpdated := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckRoute53TrafficPolicyInstanceDestroy, + ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), + Steps: []resource.TestStep{ + { + Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rNameUpdated), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), + resource.TestCheckResourceAttr(resourceName, "name", rNameUpdated), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName string, TrafficPolicyInstance *route53.GetTrafficPolicyInstanceOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).r53conn + + input := &route53.GetTrafficPolicyInstanceInput{ + Id: aws.String(rs.Primary.ID), + } + + resp, err := conn.GetTrafficPolicyInstanceWithContext(context.Background(), input) + + if err != nil { + return fmt.Errorf("problem checking for traffic policy instance existence: %w", err) + } + + if resp == nil { + return fmt.Errorf("traffic policy instance %q does not exist", rs.Primary.ID) + } + + *TrafficPolicyInstance = *resp + + return nil + } +} + +func testAccCheckRoute53TrafficPolicyInstanceDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).r53conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_route53_traffic_policy_instance" { + continue + } + + input := &route53.GetTrafficPolicyInstanceInput{ + Id: aws.String(rs.Primary.ID), + } + + resp, err := conn.GetTrafficPolicyInstanceWithContext(context.Background(), input) + if err != nil { + return fmt.Errorf("error decoding Route53 Traffic Policy Instance %s : %w", rs.Primary.Attributes["name"], err) + } + + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { + continue + } + + if err != nil { + return fmt.Errorf("error during check if traffic policy instance still exists, %#v", err) + } + if resp != nil { + return fmt.Errorf("traffic Policy instance still exists") + } + } + return nil +} + +func testAccRoute53TrafficPolicyInstanceConfig(zoneName, instanceName string) string { + return fmt.Sprintf(` +resource "aws_route53_zone" "test" { + name = %[1]q +} + +resource "aws_route53_traffic_policy" "test" { + name = aws_route53_zone.test.name + document = <<-EOT +{ + "AWSPolicyFormatVersion":"2015-10-01", + "RecordType":"A", + "Endpoints":{ + "endpoint-start-NkPh":{ + "Type":"value", + "Value":"10.0.0.1" + } + }, + "StartEndpoint":"endpoint-start-NkPh" +} +EOT +} + +resource "aws_route53_traffic_policy_instance" "test" { + hosted_zone_id = aws_route53_zone.test.zone_id + name = %[2]q + traffic_policy_id = aws_route53_traffic_policy.test.id + traffic_policy_version = aws_route53_traffic_policy.test.version + ttl = 360 +} +`, zoneName, instanceName) +} diff --git a/website/docs/r/route53_traffic_policy_instance.html.markdown b/website/docs/r/route53_traffic_policy_instance.html.markdown new file mode 100644 index 000000000000..db4b6be14b56 --- /dev/null +++ b/website/docs/r/route53_traffic_policy_instance.html.markdown @@ -0,0 +1,47 @@ +--- +subcategory: "Route53" +layout: "aws" +page_title: "AWS: aws_route53_traffic_policy_instance" +description: |- + Provides a Route53 traffic policy instance resource. +--- + +# Resource: aws_route53_traffic_policy_instance + +Provides a Route53 traffic policy instance resource. + +## Example Usage + +```hcl +resource "aws_route53_traffic_policy_instance" "test" { + name = "test.example.com" + traffic_policy_id = "b3gb108f-ea6f-45a5-baab-9d112d8b4037" + traffic_policy_version = 1 + hosted_zone_id = "Z033120931TAQO548OGJC" + ttl = 360 +} +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) Domain name for which Amazon Route 53 responds to DNS queries by using the resource record sets that Route 53 creates for this traffic policy instance. +* `traffic_policy_id` - (Required) ID of the traffic policy that you want to use to create resource record sets in the specified hosted zone. +* `traffic_policy_version` - (Required) Version of the traffic policy +* `hosted_zone_id` - (Required) ID of the hosted zone that you want Amazon Route 53 to create resource record sets in by using the configuration in a traffic policy. +* `ttl` - (Required) TTL that you want Amazon Route 53 to assign to all the resource record sets that it creates in the specified hosted zone. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of traffic policy instance. + +## Import + +Route53 traffic policy instance can be imported using its id. + +``` +$ terraform import aws_route53_traffic_policy_instance.test df579d9a-6396-410e-ac22-e7ad60cf9e7e +``` From 22d6b09bec7ac54eeaee4c38f77dc3d9ad92be9d Mon Sep 17 00:00:00 2001 From: Edgar Lopez Date: Tue, 31 Aug 2021 17:15:29 -0600 Subject: [PATCH 5/5] fixes bug --- aws/internal/service/route53/finder/finder.go | 14 +++++++ aws/internal/service/route53/waiter/status.go | 19 ++++++++++ aws/internal/service/route53/waiter/waiter.go | 37 +++++++++++++++++++ ...rce_aws_route53_traffic_policy_instance.go | 29 ++++++++++++++- ...ws_route53_traffic_policy_instance_test.go | 35 +++++++++++------- ...te53_traffic_policy_instance.html.markdown | 4 +- 6 files changed, 121 insertions(+), 17 deletions(-) diff --git a/aws/internal/service/route53/finder/finder.go b/aws/internal/service/route53/finder/finder.go index 7273c85ead62..4dde32f51b1a 100644 --- a/aws/internal/service/route53/finder/finder.go +++ b/aws/internal/service/route53/finder/finder.go @@ -1,6 +1,7 @@ package finder import ( + "context" "fmt" "github.com/aws/aws-sdk-go/aws" @@ -62,3 +63,16 @@ func KeySigningKeyByResourceID(conn *route53.Route53, resourceID string) (*route return KeySigningKey(conn, hostedZoneID, name) } + +func TrafficPolicyInstanceID(ctx context.Context, conn *route53.Route53, id string) (*route53.GetTrafficPolicyInstanceOutput, error) { + input := &route53.GetTrafficPolicyInstanceInput{ + Id: aws.String(id), + } + + resp, err := conn.GetTrafficPolicyInstanceWithContext(ctx, input) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/aws/internal/service/route53/waiter/status.go b/aws/internal/service/route53/waiter/status.go index ac56d38bdaa3..f9895a17a8b3 100644 --- a/aws/internal/service/route53/waiter/status.go +++ b/aws/internal/service/route53/waiter/status.go @@ -1,6 +1,8 @@ package waiter import ( + "context" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/route53" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -58,3 +60,20 @@ func KeySigningKeyStatus(conn *route53.Route53, hostedZoneID string, name string return keySigningKey, aws.StringValue(keySigningKey.Status), nil } } + +//TrafficPolicyInstanceState fetches the traffic policy instance and its state +func TrafficPolicyInstanceState(ctx context.Context, conn *route53.Route53, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + object, err := finder.TrafficPolicyInstanceID(ctx, conn, id) + + if err != nil { + return nil, "Unknown", err + } + + if object == nil && object.TrafficPolicyInstance == nil { + return object, "NotFound", nil + } + + return object, aws.StringValue(object.TrafficPolicyInstance.State), nil + } +} diff --git a/aws/internal/service/route53/waiter/waiter.go b/aws/internal/service/route53/waiter/waiter.go index 6e416d19a819..46c3968c6171 100644 --- a/aws/internal/service/route53/waiter/waiter.go +++ b/aws/internal/service/route53/waiter/waiter.go @@ -1,6 +1,7 @@ package waiter import ( + "context" "errors" "fmt" "math/rand" @@ -108,3 +109,39 @@ func KeySigningKeyStatusUpdated(conn *route53.Route53, hostedZoneID string, name return nil, err } + +// TrafficPolicyInstanceStateApplied waits for a traffic policy instance applied +func TrafficPolicyInstanceStateApplied(ctx context.Context, conn *route53.Route53, id string) (*route53.GetTrafficPolicyInstanceOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{"Creating"}, + Target: []string{"Applied", "Failed"}, + Refresh: TrafficPolicyInstanceState(ctx, conn, id), + Timeout: TrafficPolicyInstanceOperationTimeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*route53.GetTrafficPolicyInstanceOutput); ok { + return output, err + } + + return nil, err +} + +// TrafficPolicyInstanceStateDeleted waits for a traffic policy instance deleted +func TrafficPolicyInstanceStateDeleted(ctx context.Context, conn *route53.Route53, id string) (*route53.GetTrafficPolicyInstanceOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{"Deleting"}, + Target: []string{"NotFound", "Failed"}, + Refresh: TrafficPolicyInstanceState(ctx, conn, id), + Timeout: TrafficPolicyInstanceOperationTimeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*route53.GetTrafficPolicyInstanceOutput); ok { + return output, err + } + + return nil, err +} diff --git a/aws/resource_aws_route53_traffic_policy_instance.go b/aws/resource_aws_route53_traffic_policy_instance.go index 9f58b6f7fd44..bc2fe7922cdb 100644 --- a/aws/resource_aws_route53_traffic_policy_instance.go +++ b/aws/resource_aws_route53_traffic_policy_instance.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "strings" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/route53" @@ -32,11 +33,23 @@ func resourceAwsRoute53TrafficPolicyInstance() *schema.Resource { ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 32), }, + "message": { + Type: schema.TypeString, + Computed: true, + }, "name": { Type: schema.TypeString, Required: true, ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 1024), + StateFunc: func(v interface{}) string { + value := strings.TrimSuffix(v.(string), ".") + return strings.ToLower(value) + }, + }, + "state": { + Type: schema.TypeString, + Computed: true, }, "traffic_policy_id": { Type: schema.TypeString, @@ -90,6 +103,10 @@ func resourceAwsRoute53TrafficPolicyInstanceCreate(ctx context.Context, d *schem return diag.FromErr(fmt.Errorf("error creating Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) } + if _, err = waiter.TrafficPolicyInstanceStateApplied(ctx, conn, aws.StringValue(output.TrafficPolicyInstance.Id)); err != nil { + return diag.FromErr(fmt.Errorf("error waiting for Route53 Traffic Policy Instance (%s) to be Applied: %w", d.Id(), err)) + } + d.SetId(aws.StringValue(output.TrafficPolicyInstance.Id)) return resourceAwsRoute53TrafficPolicyInstanceRead(ctx, d, meta) @@ -115,7 +132,9 @@ func resourceAwsRoute53TrafficPolicyInstanceRead(ctx context.Context, d *schema. } d.Set("hosted_zone_id", output.TrafficPolicyInstance.HostedZoneId) - d.Set("name", output.TrafficPolicyInstance.Name) + d.Set("message", output.TrafficPolicyInstance.Message) + d.Set("name", strings.TrimSuffix(aws.StringValue(output.TrafficPolicyInstance.Name), ".")) + d.Set("state", output.TrafficPolicyInstance.State) d.Set("traffic_policy_id", output.TrafficPolicyInstance.TrafficPolicyId) d.Set("traffic_policy_version", output.TrafficPolicyInstance.TrafficPolicyVersion) d.Set("ttl", output.TrafficPolicyInstance.TTL) @@ -153,9 +172,15 @@ func resourceAwsRoute53TrafficPolicyInstanceDelete(ctx context.Context, d *schem if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { return nil } - return diag.FromErr(fmt.Errorf("error deleting Route53 Traffic Policy Instance %s: %w", d.Get("name").(string), err)) } + if _, err = waiter.TrafficPolicyInstanceStateDeleted(ctx, conn, d.Id()); err != nil { + if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { + return nil + } + return diag.FromErr(fmt.Errorf("error waiting for Route53 Traffic Policy Instance (%s) to be Deleted: %w", d.Id(), err)) + } + return nil } diff --git a/aws/resource_aws_route53_traffic_policy_instance_test.go b/aws/resource_aws_route53_traffic_policy_instance_test.go index 2e8286c1b7e8..d1ae2a26b846 100644 --- a/aws/resource_aws_route53_traffic_policy_instance_test.go +++ b/aws/resource_aws_route53_traffic_policy_instance_test.go @@ -16,7 +16,9 @@ import ( func TestAccAWSRoute53TrafficPolicyInstance_basic(t *testing.T) { var output route53.GetTrafficPolicyInstanceOutput resourceName := "aws_route53_traffic_policy_instance.test" - rName := acctest.RandomWithPrefix("tf-acc-test") + + zoneName := testAccRandomDomainName() + rName := fmt.Sprintf("%s_%s", acctest.RandomWithPrefix("tf-acc-test"), zoneName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -25,7 +27,7 @@ func TestAccAWSRoute53TrafficPolicyInstance_basic(t *testing.T) { ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), Steps: []resource.TestStep{ { - Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Config: testAccRoute53TrafficPolicyInstanceConfig(zoneName, rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), resource.TestCheckResourceAttr(resourceName, "name", rName), @@ -43,7 +45,9 @@ func TestAccAWSRoute53TrafficPolicyInstance_basic(t *testing.T) { func TestAccAWSRoute53TrafficPolicyInstance_disappears(t *testing.T) { var output route53.GetTrafficPolicyInstanceOutput resourceName := "aws_route53_traffic_policy_instance.test" - rName := acctest.RandomWithPrefix("tf-acc-test") + + zoneName := testAccRandomDomainName() + rName := fmt.Sprintf("%s_%s", acctest.RandomWithPrefix("tf-acc-test"), zoneName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -52,11 +56,12 @@ func TestAccAWSRoute53TrafficPolicyInstance_disappears(t *testing.T) { ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), Steps: []resource.TestStep{ { - Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Config: testAccRoute53TrafficPolicyInstanceConfig(zoneName, rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute53TrafficPolicyInstance(), resourceName), ), + ExpectNonEmptyPlan: true, }, }, }) @@ -65,8 +70,10 @@ func TestAccAWSRoute53TrafficPolicyInstance_disappears(t *testing.T) { func TestAccAWSRoute53TrafficPolicyInstance_complete(t *testing.T) { var output route53.GetTrafficPolicyInstanceOutput resourceName := "aws_route53_traffic_policy_instance.test" - rName := acctest.RandomWithPrefix("tf-acc-test") - rNameUpdated := acctest.RandomWithPrefix("tf-acc-test") + + zoneName := testAccRandomDomainName() + rName := fmt.Sprintf("%s_%s", acctest.RandomWithPrefix("tf-acc-test"), zoneName) + rNameUpdated := fmt.Sprintf("%s_%s", acctest.RandomWithPrefix("tf-acc-test"), zoneName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -75,14 +82,14 @@ func TestAccAWSRoute53TrafficPolicyInstance_complete(t *testing.T) { ErrorCheck: testAccErrorCheck(t, route53.EndpointsID), Steps: []resource.TestStep{ { - Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rName), + Config: testAccRoute53TrafficPolicyInstanceConfig(zoneName, rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, { - Config: testAccRoute53TrafficPolicyInstanceConfig(rName, rNameUpdated), + Config: testAccRoute53TrafficPolicyInstanceConfig(zoneName, rNameUpdated), Check: resource.ComposeTestCheckFunc( testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName, &output), resource.TestCheckResourceAttr(resourceName, "name", rNameUpdated), @@ -97,7 +104,7 @@ func TestAccAWSRoute53TrafficPolicyInstance_complete(t *testing.T) { }) } -func testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName string, TrafficPolicyInstance *route53.GetTrafficPolicyInstanceOutput) resource.TestCheckFunc { +func testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName string, output *route53.GetTrafficPolicyInstanceOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] if !ok { @@ -120,7 +127,7 @@ func testAccCheckAwsRoute53TrafficPolicyInstanceExists(resourceName string, Traf return fmt.Errorf("traffic policy instance %q does not exist", rs.Primary.ID) } - *TrafficPolicyInstance = *resp + output = resp return nil } @@ -139,14 +146,14 @@ func testAccCheckRoute53TrafficPolicyInstanceDestroy(s *terraform.State) error { } resp, err := conn.GetTrafficPolicyInstanceWithContext(context.Background(), input) - if err != nil { - return fmt.Errorf("error decoding Route53 Traffic Policy Instance %s : %w", rs.Primary.Attributes["name"], err) - } - if tfawserr.ErrCodeEquals(err, route53.ErrCodeNoSuchTrafficPolicyInstance) { continue } + if err != nil { + return fmt.Errorf("error getting Route53 Traffic Policy Instance %s : %w", rs.Primary.Attributes["name"], err) + } + if err != nil { return fmt.Errorf("error during check if traffic policy instance still exists, %#v", err) } diff --git a/website/docs/r/route53_traffic_policy_instance.html.markdown b/website/docs/r/route53_traffic_policy_instance.html.markdown index db4b6be14b56..b200b7557cde 100644 --- a/website/docs/r/route53_traffic_policy_instance.html.markdown +++ b/website/docs/r/route53_traffic_policy_instance.html.markdown @@ -12,7 +12,7 @@ Provides a Route53 traffic policy instance resource. ## Example Usage -```hcl +```terraform resource "aws_route53_traffic_policy_instance" "test" { name = "test.example.com" traffic_policy_id = "b3gb108f-ea6f-45a5-baab-9d112d8b4037" @@ -37,6 +37,8 @@ The following arguments are required: In addition to all arguments above, the following attributes are exported: * `id` - ID of traffic policy instance. +* `message` - If `state` is `Failed`, an explanation of the reason for the failure. If `state` is another value, `message` is empty. . +* `state` - State of a policy traffic instance. ## Import