Skip to content

Commit e5f1b8b

Browse files
committed
tests/resource/aws_api_gateway_domain_name: Remove hardcoded environment variable handling, create public ACM certificate, improve state value checks
Reference: #8316 Reference: #14664 Reference: #15737 Output from acceptance testing in AWS Commercial: ``` --- PASS: TestAccAWSAPIGatewayDomainName_disappears (20.54s) --- PASS: TestAccAWSAPIGatewayDomainName_RegionalCertificateArn (81.84s) --- PASS: TestAccAWSAPIGatewayDomainName_SecurityPolicy (139.42s) --- PASS: TestAccAWSAPIGatewayDomainName_Tags (203.73s) --- SKIP: TestAccAWSAPIGatewayDomainName_CertificateName (0.00s) --- SKIP: TestAccAWSAPIGatewayDomainName_RegionalCertificateName (0.00s) ``` Output from acceptance testing in AWS GovCloud (US) (other tests failing with ACM quota limits): ``` --- SKIP: TestAccAWSAPIGatewayDomainName_CertificateArn (1.58s) ```
1 parent ae8365c commit e5f1b8b

3 files changed

+190
-33
lines changed

aws/api_gateway_domain_name_test.go

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync"
7+
"testing"
8+
9+
"github.com/aws/aws-sdk-go/aws/arn"
10+
"github.com/aws/aws-sdk-go/aws/endpoints"
11+
"github.com/aws/aws-sdk-go/service/apigateway"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
14+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
16+
)
17+
18+
// API Gateway Edge-Optimized Domain Name can only be created with ACM Certificates in specific regions.
19+
20+
// testAccApigatewayEdgeDomainNameRegion is the chosen API Gateway Domain Name testing region
21+
//
22+
// Cached to prevent issues should multiple regions become available.
23+
var testAccApigatewayEdgeDomainNameRegion string
24+
25+
// testAccProviderApigatewayEdgeDomainName is the API Gateway Domain Name provider instance
26+
//
27+
// This Provider can be used in testing code for API calls without requiring
28+
// the use of saving and referencing specific ProviderFactories instances.
29+
//
30+
// testAccPreCheckApigatewayEdgeDomainName(t) must be called before using this provider instance.
31+
var testAccProviderApigatewayEdgeDomainName *schema.Provider
32+
33+
// testAccProviderApigatewayEdgeDomainNameConfigure ensures the provider is only configured once
34+
var testAccProviderApigatewayEdgeDomainNameConfigure sync.Once
35+
36+
// testAccPreCheckApigatewayEdgeDomainName verifies AWS credentials and that API Gateway Domain Name is supported
37+
func testAccPreCheckApigatewayEdgeDomainName(t *testing.T) {
38+
testAccPartitionHasServicePreCheck(apigateway.EndpointsID, t)
39+
40+
// Since we are outside the scope of the Terraform configuration we must
41+
// call Configure() to properly initialize the provider configuration.
42+
testAccProviderApigatewayEdgeDomainNameConfigure.Do(func() {
43+
testAccProviderApigatewayEdgeDomainName = Provider()
44+
45+
region := testAccGetApigatewayEdgeDomainNameRegion()
46+
47+
if region == "" {
48+
t.Skip("API Gateway Domain Name not available in this AWS Partition")
49+
}
50+
51+
config := map[string]interface{}{
52+
"region": region,
53+
}
54+
55+
diags := testAccProviderApigatewayEdgeDomainName.Configure(context.Background(), terraform.NewResourceConfigRaw(config))
56+
57+
if diags != nil && diags.HasError() {
58+
for _, d := range diags {
59+
if d.Severity == diag.Error {
60+
t.Fatalf("error configuring API Gateway Domain Name provider: %s", d.Summary)
61+
}
62+
}
63+
}
64+
})
65+
}
66+
67+
// testAccApigatewayEdgeDomainNameRegionProviderConfig is the Terraform provider configuration for API Gateway Domain Name region testing
68+
//
69+
// Testing API Gateway Domain Name assumes no other provider configurations
70+
// are necessary and overwrites the "aws" provider configuration.
71+
func testAccApigatewayEdgeDomainNameRegionProviderConfig() string {
72+
return testAccRegionalProviderConfig(testAccGetApigatewayEdgeDomainNameRegion())
73+
}
74+
75+
// testAccGetApigatewayEdgeDomainNameRegion returns the API Gateway Domain Name region for testing
76+
func testAccGetApigatewayEdgeDomainNameRegion() string {
77+
if testAccApigatewayEdgeDomainNameRegion != "" {
78+
return testAccApigatewayEdgeDomainNameRegion
79+
}
80+
81+
// AWS Commercial: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html
82+
// AWS GovCloud (US) - edge custom domain names not supported: https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-abp.html
83+
// AWS China - edge custom domain names not supported: https://docs.amazonaws.cn/en_us/aws/latest/userguide/api-gateway.html
84+
switch testAccGetPartition() {
85+
case endpoints.AwsPartitionID:
86+
testAccApigatewayEdgeDomainNameRegion = endpoints.UsEast1RegionID
87+
}
88+
89+
return testAccApigatewayEdgeDomainNameRegion
90+
}
91+
92+
// testAccCheckResourceAttrRegionalARNApigatewayEdgeDomainName ensures the Terraform state exactly matches the expected API Gateway Edge Domain Name format
93+
func testAccCheckResourceAttrRegionalARNApigatewayEdgeDomainName(resourceName, attributeName, arnService string, domain string) resource.TestCheckFunc {
94+
return func(s *terraform.State) error {
95+
attributeValue := arn.ARN{
96+
Partition: testAccGetPartition(),
97+
Region: testAccGetApigatewayEdgeDomainNameRegion(),
98+
Resource: fmt.Sprintf("/domainnames/%s", domain),
99+
Service: arnService,
100+
}.String()
101+
102+
return resource.TestCheckResourceAttr(resourceName, attributeName, attributeValue)(s)
103+
}
104+
}
105+
106+
// testAccCheckResourceAttrRegionalARNApigatewayRegionalDomainName ensures the Terraform state exactly matches the expected API Gateway Regional Domain Name format
107+
func testAccCheckResourceAttrRegionalARNApigatewayRegionalDomainName(resourceName, attributeName, arnService string, domain string) resource.TestCheckFunc {
108+
return func(s *terraform.State) error {
109+
attributeValue := arn.ARN{
110+
Partition: testAccGetPartition(),
111+
Region: testAccGetRegion(),
112+
Resource: fmt.Sprintf("/domainnames/%s", domain),
113+
Service: arnService,
114+
}.String()
115+
116+
return resource.TestCheckResourceAttr(resourceName, attributeName, attributeValue)(s)
117+
}
118+
}

aws/resource_aws_api_gateway_domain_name_test.go

+72-32
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,34 @@ import (
1414
)
1515

1616
func TestAccAWSAPIGatewayDomainName_CertificateArn(t *testing.T) {
17-
certificateArn := os.Getenv("AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_ARN")
18-
if certificateArn == "" {
19-
t.Skip(
20-
"Environment variable AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_ARN is not set. " +
21-
"This environment variable must be set to the ARN of " +
22-
"an ISSUED ACM certificate in us-east-1 to enable this test.")
23-
}
24-
25-
// This test must always run in us-east-1
26-
// BadRequestException: Invalid certificate ARN: arn:aws:acm:us-west-2:123456789012:certificate/xxxxx. Certificate must be in 'us-east-1'.
27-
oldvar := os.Getenv("AWS_DEFAULT_REGION")
28-
os.Setenv("AWS_DEFAULT_REGION", "us-east-1")
29-
defer os.Setenv("AWS_DEFAULT_REGION", oldvar)
17+
rootDomain := testAccAwsAcmCertificateDomainFromEnv(t)
18+
domain := testAccAwsAcmCertificateRandomSubDomain(rootDomain)
3019

3120
var domainName apigateway.DomainName
21+
acmCertificateResourceName := "aws_acm_certificate.test"
3222
resourceName := "aws_api_gateway_domain_name.test"
33-
rName := fmt.Sprintf("tf-acc-%s.terraformtest.com", acctest.RandString(8))
3423

3524
resource.ParallelTest(t, resource.TestCase{
36-
PreCheck: func() { testAccPreCheck(t) },
37-
Providers: testAccProviders,
38-
CheckDestroy: testAccCheckAWSAPIGatewayDomainNameDestroy,
25+
PreCheck: func() { testAccPreCheck(t); testAccPreCheckApigatewayEdgeDomainName(t) },
26+
ProviderFactories: testAccProviderFactories,
27+
CheckDestroy: testAccCheckAWSAPIGatewayDomainNameDestroy,
3928
Steps: []resource.TestStep{
4029
{
41-
Config: testAccAWSAPIGatewayDomainNameConfig_CertificateArn(rName, certificateArn),
30+
Config: testAccAWSAPIGatewayDomainNameConfig_CertificateArn(rootDomain, domain),
4231
Check: resource.ComposeTestCheckFunc(
4332
testAccCheckAWSAPIGatewayDomainNameExists(resourceName, &domainName),
44-
testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/domainnames/+.`)),
45-
resource.TestCheckResourceAttrSet(resourceName, "cloudfront_domain_name"),
33+
testAccCheckResourceAttrRegionalARNApigatewayEdgeDomainName(resourceName, "arn", "apigateway", domain),
34+
resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", acmCertificateResourceName, "arn"),
35+
resource.TestMatchResourceAttr(resourceName, "cloudfront_domain_name", regexp.MustCompile(`[a-z0-9]+.cloudfront.net`)),
4636
resource.TestCheckResourceAttr(resourceName, "cloudfront_zone_id", "Z2FDTNDATAQYW2"),
47-
resource.TestCheckResourceAttr(resourceName, "domain_name", rName),
37+
resource.TestCheckResourceAttrPair(resourceName, "domain_name", acmCertificateResourceName, "domain_name"),
4838
),
4939
},
40+
{
41+
ResourceName: resourceName,
42+
ImportState: true,
43+
ImportStateVerify: true,
44+
},
5045
},
5146
})
5247
}
@@ -131,9 +126,9 @@ func TestAccAWSAPIGatewayDomainName_RegionalCertificateArn(t *testing.T) {
131126
Config: testAccAWSAPIGatewayDomainNameConfig_RegionalCertificateArn(rName, key, certificate),
132127
Check: resource.ComposeTestCheckFunc(
133128
testAccCheckAWSAPIGatewayDomainNameExists(resourceName, &domainName),
134-
testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/domainnames/+.`)),
129+
testAccCheckResourceAttrRegionalARNApigatewayRegionalDomainName(resourceName, "arn", "apigateway", rName),
135130
resource.TestCheckResourceAttr(resourceName, "domain_name", rName),
136-
resource.TestMatchResourceAttr(resourceName, "regional_domain_name", regexp.MustCompile(`.*\.execute-api\..*`)),
131+
testAccMatchResourceAttrRegionalHostname(resourceName, "regional_domain_name", "execute-api", regexp.MustCompile(`d-[a-z0-9]+`)),
137132
resource.TestMatchResourceAttr(resourceName, "regional_zone_id", regexp.MustCompile(`^Z`)),
138133
),
139134
},
@@ -174,14 +169,14 @@ func TestAccAWSAPIGatewayDomainName_RegionalCertificateName(t *testing.T) {
174169
Config: testAccAWSAPIGatewayDomainNameConfig_RegionalCertificateName(rName, key, certificate, caCertificate),
175170
Check: resource.ComposeTestCheckFunc(
176171
testAccCheckAWSAPIGatewayDomainNameExists(resourceName, &domainName),
177-
testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/domainnames/+.`)),
172+
testAccCheckResourceAttrRegionalARNApigatewayRegionalDomainName(resourceName, "arn", "apigateway", rName),
178173
resource.TestCheckResourceAttr(resourceName, "certificate_body", certificate),
179174
resource.TestCheckResourceAttr(resourceName, "certificate_chain", caCertificate),
180175
resource.TestCheckResourceAttr(resourceName, "certificate_name", "tf-acc-apigateway-domain-name"),
181176
resource.TestCheckResourceAttr(resourceName, "certificate_private_key", key),
182177
resource.TestCheckResourceAttrSet(resourceName, "certificate_upload_date"),
183178
resource.TestCheckResourceAttr(resourceName, "domain_name", rName),
184-
resource.TestMatchResourceAttr(resourceName, "regional_domain_name", regexp.MustCompile(`.*\.execute-api\..*`)),
179+
testAccMatchResourceAttrRegionalHostname(resourceName, "regional_domain_name", "execute-api", regexp.MustCompile(`d-[a-z0-9]+`)),
185180
resource.TestMatchResourceAttr(resourceName, "regional_zone_id", regexp.MustCompile(`^Z`)),
186181
),
187182
},
@@ -206,7 +201,6 @@ func TestAccAWSAPIGatewayDomainName_SecurityPolicy(t *testing.T) {
206201
Config: testAccAWSAPIGatewayDomainNameConfig_SecurityPolicy(rName, key, certificate, apigateway.SecurityPolicyTls12),
207202
Check: resource.ComposeTestCheckFunc(
208203
testAccCheckAWSAPIGatewayDomainNameExists(resourceName, &domainName),
209-
testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/domainnames/+.`)),
210204
resource.TestCheckResourceAttr(resourceName, "security_policy", apigateway.SecurityPolicyTls12),
211205
),
212206
},
@@ -236,7 +230,6 @@ func TestAccAWSAPIGatewayDomainName_Tags(t *testing.T) {
236230
Config: testAccAWSAPIGatewayDomainNameConfigTags1(rName, key, certificate, "key1", "value1"),
237231
Check: resource.ComposeTestCheckFunc(
238232
testAccCheckAWSAPIGatewayDomainNameExists(resourceName, &domainName),
239-
testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/domainnames/+.`)),
240233
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
241234
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
242235
),
@@ -348,17 +341,64 @@ func testAccCheckAWSAPIGatewayDomainNameDestroy(s *terraform.State) error {
348341
return nil
349342
}
350343

351-
func testAccAWSAPIGatewayDomainNameConfig_CertificateArn(domainName, certificateArn string) string {
352-
return fmt.Sprintf(`
344+
func testAccAWSAPIGatewayDomainNameConfig_CertificateArn(rootDomain string, domain string) string {
345+
return composeConfig(
346+
testAccApigatewayEdgeDomainNameRegionProviderConfig(),
347+
fmt.Sprintf(`
348+
data "aws_route53_zone" "test" {
349+
name = %[1]q
350+
private_zone = false
351+
}
352+
353+
resource "aws_acm_certificate" "test" {
354+
domain_name = %[2]q
355+
validation_method = "DNS"
356+
}
357+
358+
#
359+
# for_each acceptance testing requires:
360+
# https://github.com/hashicorp/terraform-plugin-sdk/issues/536
361+
#
362+
# resource "aws_route53_record" "test" {
363+
# for_each = {
364+
# for dvo in aws_acm_certificate.test.domain_validation_options: dvo.domain_name => {
365+
# name = dvo.resource_record_name
366+
# record = dvo.resource_record_value
367+
# type = dvo.resource_record_type
368+
# }
369+
# }
370+
371+
# allow_overwrite = true
372+
# name = each.value.name
373+
# records = [each.value.record]
374+
# ttl = 60
375+
# type = each.value.type
376+
# zone_id = data.aws_route53_zone.test.zone_id
377+
# }
378+
379+
resource "aws_route53_record" "test" {
380+
allow_overwrite = true
381+
name = tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_name
382+
records = [tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_value]
383+
ttl = 60
384+
type = tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_type
385+
zone_id = data.aws_route53_zone.test.zone_id
386+
}
387+
388+
resource "aws_acm_certificate_validation" "test" {
389+
certificate_arn = aws_acm_certificate.test.arn
390+
validation_record_fqdns = [aws_route53_record.test.fqdn]
391+
}
392+
353393
resource "aws_api_gateway_domain_name" "test" {
354-
domain_name = "%s"
355-
certificate_arn = "%s"
394+
domain_name = aws_acm_certificate.test.domain_name
395+
certificate_arn = aws_acm_certificate_validation.test.certificate_arn
356396
357397
endpoint_configuration {
358398
types = ["EDGE"]
359399
}
360400
}
361-
`, domainName, certificateArn)
401+
`, rootDomain, domain))
362402
}
363403

364404
func testAccAWSAPIGatewayDomainNameConfig_CertificateName(domainName, key, certificate, chainCertificate string) string {

docs/MAINTAINING.md

-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,6 @@ Environment variables (beyond standard AWS Go SDK ones) used by acceptance testi
393393
| `AWS_ALTERNATE_SECRET_ACCESS_KEY` | AWS secret access key with access to a secondary AWS account for tests requiring multiple accounts. Requires `AWS_ALTERNATE_ACCESS_KEY_ID`. Conflicts with `AWS_ALTERNATE_PROFILE`. |
394394
| `AWS_ALTERNATE_PROFILE` | AWS profile with access to a secondary AWS account for tests requiring multiple accounts. Conflicts with `AWS_ALTERNATE_ACCESS_KEY_ID` and `AWS_ALTERNATE_SECRET_ACCESS_KEY`. |
395395
| `AWS_ALTERNATE_REGION` | Secondary AWS region for tests requiring multiple regions. Defaults to `us-east-1`. |
396-
| `AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_ARN` | Amazon Resource Name of ACM Certificate in `us-east-1` for API Gateway Domain Name testing. |
397396
| `AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_BODY` | Certificate body of publicly trusted certificate for API Gateway Domain Name testing. |
398397
| `AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_CHAIN` | Certificate chain of publicly trusted certificate for API Gateway Domain Name testing. |
399398
| `AWS_API_GATEWAY_DOMAIN_NAME_CERTIFICATE_PRIVATE_KEY` | Private key of publicly trusted certificate for API Gateway Domain Name testing. |

0 commit comments

Comments
 (0)