diff --git a/aws/resource_aws_service_discovery_private_dns_namespace_test.go b/aws/resource_aws_service_discovery_private_dns_namespace_test.go index bac661832216..d79d6d309a11 100644 --- a/aws/resource_aws_service_discovery_private_dns_namespace_test.go +++ b/aws/resource_aws_service_discovery_private_dns_namespace_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -51,6 +52,26 @@ func TestAccAWSServiceDiscoveryPrivateDnsNamespace_longname(t *testing.T) { }) } +// This acceptance test ensures we properly send back error messaging. References: +// * https://github.com/terraform-providers/terraform-provider-aws/issues/2830 +// * https://github.com/terraform-providers/terraform-provider-aws/issues/5532 +func TestAccAWSServiceDiscoveryPrivateDnsNamespace_error_Overlap(t *testing.T) { + rName := acctest.RandString(5) + ".example.com" + subDomain := acctest.RandString(5) + "." + rName + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsServiceDiscoveryPrivateDnsNamespaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccServiceDiscoveryPrivateDnsNamespaceConfigOverlapping(rName, subDomain), + ExpectError: regexp.MustCompile(`overlapping name space`), + }, + }, + }) +} + func testAccCheckAwsServiceDiscoveryPrivateDnsNamespaceDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).sdconn @@ -101,3 +122,25 @@ resource "aws_service_discovery_private_dns_namespace" "test" { } `, rName) } + +func testAccServiceDiscoveryPrivateDnsNamespaceConfigOverlapping(topDomain, subDomain string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + tags = { + Name = "terraform-testacc-service-discovery-private-dns-ns" + } +} + +resource "aws_service_discovery_private_dns_namespace" "top" { + name = %q + vpc = "${aws_vpc.test.id}" +} + +# Ensure ordering after first namespace +resource "aws_service_discovery_private_dns_namespace" "subdomain" { + name = %q + vpc = "${aws_service_discovery_private_dns_namespace.top.vpc}" +} +`, topDomain, subDomain) +} diff --git a/aws/resource_aws_service_discovery_public_dns_namespace.go b/aws/resource_aws_service_discovery_public_dns_namespace.go index 65a6bdce6fea..6020b071afc3 100644 --- a/aws/resource_aws_service_discovery_public_dns_namespace.go +++ b/aws/resource_aws_service_discovery_public_dns_namespace.go @@ -1,6 +1,7 @@ package aws import ( + "fmt" "time" "github.com/aws/aws-sdk-go/aws" @@ -138,9 +139,20 @@ func servicediscoveryOperationRefreshStatusFunc(conn *servicediscovery.ServiceDi OperationId: aws.String(oid), } resp, err := conn.GetOperation(input) + if err != nil { - return nil, "failed", err + return nil, servicediscovery.OperationStatusFail, err } - return resp, *resp.Operation.Status, nil + + // Error messages can also be contained in the response with FAIL status + // "ErrorCode":"CANNOT_CREATE_HOSTED_ZONE", + // "ErrorMessage":"The VPC that you chose, vpc-xxx in region xxx, is already associated with another private hosted zone that has an overlapping name space, xxx.. (Service: AmazonRoute53; Status Code: 400; Error Code: ConflictingDomainExists; Request ID: xxx)" + // "Status":"FAIL", + + if aws.StringValue(resp.Operation.Status) == servicediscovery.OperationStatusFail { + return resp, servicediscovery.OperationStatusFail, fmt.Errorf("%s: %s", aws.StringValue(resp.Operation.ErrorCode), aws.StringValue(resp.Operation.ErrorMessage)) + } + + return resp, aws.StringValue(resp.Operation.Status), nil } }