Skip to content

Commit

Permalink
tests/provider: Prepare EC2-Classic handling to remove reseting defau…
Browse files Browse the repository at this point in the history
…lt region environment variable and better document existing provider initialization

Reference: #8316
Reference: #15737
Reference: #15791

Output from acceptance testing in AWS Commercial (DynamoDB to verify existing testAccProviderFactories handling):

```
--- PASS: TestAccAWSDynamoDbTable_Replica_Single (274.15s)

--- PASS: TestAccAWSRedshiftSecurityGroup_basic (10.87s)
--- PASS: TestAccAWSRedshiftSecurityGroup_ingressCidr (10.88s)
--- PASS: TestAccAWSRedshiftSecurityGroup_ingressSecurityGroup (12.45s)
--- PASS: TestAccAWSRedshiftSecurityGroup_updateIngressCidr (24.07s)
--- PASS: TestAccAWSRedshiftSecurityGroup_updateIngressSecurityGroup (27.14s)
```

Output from acceptance testing in AWS GovCloud (US):

```
--- SKIP: TestAccAWSRedshiftSecurityGroup_updateIngressCidr (2.50s)
--- SKIP: TestAccAWSRedshiftSecurityGroup_basic (2.50s)
--- SKIP: TestAccAWSRedshiftSecurityGroup_ingressCidr (2.50s)
--- SKIP: TestAccAWSRedshiftSecurityGroup_ingressSecurityGroup (2.50s)
--- SKIP: TestAccAWSRedshiftSecurityGroup_updateIngressSecurityGroup (2.50s)
```
  • Loading branch information
bflad committed Oct 23, 2020
1 parent 79af2c2 commit fd841b4
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 113 deletions.
84 changes: 84 additions & 0 deletions aws/ec2_classic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package aws

import (
"context"
"os"
"sync"
"testing"

"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

const (
// EC2-Classic region testing environment variable name
Ec2ClassicRegionEnvVar = "AWS_EC2_CLASSIC_REGION"
)

// testAccProviderEc2Classic is the EC2-Classic provider instance
//
// This Provider can be used in testing code for API calls without requiring
// the use of saving and referencing specific ProviderFactories instances.
//
// testAccEC2ClassicPreCheck(t) must be called before using this provider instance.
var testAccProviderEc2Classic *schema.Provider

// testAccProviderEc2ClassicConfigure ensures the provider is only configured once
var testAccProviderEc2ClassicConfigure sync.Once

// testAccEC2ClassicPreCheck verifies AWS credentials and that EC2-Classic is supported
func testAccEC2ClassicPreCheck(t *testing.T) {
// Since we are outside the scope of the Terraform configuration we must
// call Configure() to properly initialize the provider configuration.
testAccProviderEc2ClassicConfigure.Do(func() {
testAccProviderEc2Classic = Provider()

config := map[string]interface{}{
"region": testAccGetEc2ClassicRegion(),
}

err := testAccProviderEc2Classic.Configure(context.Background(), terraform.NewResourceConfigRaw(config))

if err != nil {
t.Fatal(err)
}
})

client := testAccProviderEc2Classic.Meta().(*AWSClient)
platforms := client.supportedplatforms
region := client.region
if !hasEc2Classic(platforms) {
t.Skipf("this test can only run in EC2-Classic, platforms available in %s: %q", region, platforms)
}
}

// testAccEc2ClassicRegionProviderConfig is the Terraform provider configuration for EC2-Classic region testing
//
// Testing EC2-Classic assumes no other provider configurations are necessary
// and overwrites the "aws" provider configuration.
func testAccEc2ClassicRegionProviderConfig() string {
return testAccRegionalProviderConfig(testAccGetEc2ClassicRegion())
}

// testAccGetEc2ClassicRegion returns the EC2-Classic region for testing
func testAccGetEc2ClassicRegion() string {
v := os.Getenv(Ec2ClassicRegionEnvVar)

if v != "" {
return v
}

if testAccGetPartition() == endpoints.AwsPartitionID {
return endpoints.UsEast1RegionID
}

return testAccGetRegion()
}

// testAccProviderFactoriesEc2Classic initializes providers for EC2-Classic testing.
//
// Deprecated: This will be replaced with testAccProviderFactories when it only returns the "aws" provider
func testAccProviderFactoriesEc2Classic() map[string]func() (*schema.Provider, error) {
return testAccProviderFactoriesInit(nil, []string{ProviderNameAws})
}
156 changes: 110 additions & 46 deletions aws/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

const (
// Provider name for single configuration testing
ProviderNameAws = "aws"

// Provider name for alternate configuration testing
ProviderNameAwsAlternate = "awsalternate"

// Provider name for alternate account and alternate region configuration testing
ProviderNameAwsAlternateAccountAlternateRegion = "awsalternateaccountalternateregion"

// Provider name for alternate account and same region configuration testing
ProviderNameAwsAlternateAccountSameRegion = "awsalternateaccountsameregion"

// Provider name for same account and alternate region configuration testing
ProviderNameAwsSameAccountAlternateRegion = "awssameaccountalternateregion"

// Provider name for third configuration testing
ProviderNameAwsThird = "awsthird"

// Provider name for hardcoded us-east-1 configuration testing
//
// Deprecated: This will be replaced with service specific providers
ProviderNameAwsUsEast1 = "awsus-east-1"
)

const rfc3339RegexPattern = `^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?([Zz]|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$`
const uuidRegexPattern = `[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[ab89][a-f0-9]{3}-[a-f0-9]{12}`

Expand All @@ -34,31 +59,73 @@ var TestAccSkip = func(t *testing.T, message string) {
t.Skip(message)
}

// testAccProviders is a static map of provider types and their associated provider instance.
//
// Deprecated: Terraform Plugin SDK version 2 uses TestCase.ProviderFactories
// but supports this value in TestCase.Providers for backwards compatibility.
// In the future Providers: testAccProviders will be changed to
// ProviderFactories: testAccProviderFactories
var testAccProviders map[string]*schema.Provider

// testAccProviderFactories initializes and returns Provider slice elements of a provider type and function that returns the provider instance
//
// Using this function will initialize all listed provider types as gRPC
// plugins for every test, which is inefficient and can cause ulimit issues.
//
// Deprecated: Use specific ProviderFactories functions such as testAccProviderFactoriesEc2Classic instead.
// In the future this will be changed to return only the aws provider and not accept a parameter.
var testAccProviderFactories func(providers *[]*schema.Provider) map[string]func() (*schema.Provider, error)

// testAccProvider is the "main" provider instance
//
// This Provider can be used in testing code for API calls without requiring
// the use of saving and referencing specific ProviderFactories instances.
//
// testAccPreCheck(t) must be called before using this provider instance.
var testAccProvider *schema.Provider

// testAccProviderFunc is a function that returns the "main" provider instance
//
// Deprecated: Use testAccAwsRegionProviderFunc instead.
// In the future this will be changed to be compatible with ProviderFactories.
var testAccProviderFunc func() *schema.Provider

func init() {
testAccProvider = Provider()
testAccProviders = map[string]*schema.Provider{
"aws": testAccProvider,
ProviderNameAws: testAccProvider,
}
testAccProviderFactories = func(providers *[]*schema.Provider) map[string]func() (*schema.Provider, error) {
// this is an SDKV2 compatible hack, the "factory" functions are
// effectively singletons for the lifecycle of a resource.Test
var providerNames = []string{"aws", "awseast", "awswest", "awsalternate", "awsus-east-1", "awsalternateaccountalternateregion", "awsalternateaccountsameregion", "awssameaccountalternateregion", "awsthird"}
var factories = make(map[string]func() (*schema.Provider, error), len(providerNames))
for _, name := range providerNames {
p := Provider()
factories[name] = func() (*schema.Provider, error) { //nolint:unparam
return p, nil
}
return testAccProviderFactoriesInit(providers, []string{
ProviderNameAws,
ProviderNameAwsAlternate,
ProviderNameAwsAlternateAccountAlternateRegion,
ProviderNameAwsAlternateAccountSameRegion,
ProviderNameAwsSameAccountAlternateRegion,
ProviderNameAwsThird,
ProviderNameAwsUsEast1,
})
}
testAccProviderFunc = func() *schema.Provider { return testAccProvider }
}

// testAccProviderFactoriesInit creates ProviderFactories for the provider under testing.
func testAccProviderFactoriesInit(providers *[]*schema.Provider, providerNames []string) map[string]func() (*schema.Provider, error) {
var factories = make(map[string]func() (*schema.Provider, error), len(providerNames))

for _, name := range providerNames {
p := Provider()

factories[name] = func() (*schema.Provider, error) { //nolint:unparam
return p, nil
}

if providers != nil {
*providers = append(*providers, p)
}
return factories
}
testAccProviderFunc = func() *schema.Provider { return testAccProvider }

return factories
}

func TestProvider(t *testing.T) {
Expand Down Expand Up @@ -519,16 +586,6 @@ func testAccAlternateRegionPreCheck(t *testing.T) {
}
}

func testAccEC2ClassicPreCheck(t *testing.T) {
client := testAccProvider.Meta().(*AWSClient)
platforms := client.supportedplatforms
region := client.region
if !hasEc2Classic(platforms) {
t.Skipf("This test can only run in EC2 Classic, platforms available in %s: %q",
region, platforms)
}
}

func testAccEC2VPCOnlyPreCheck(t *testing.T) {
client := testAccProvider.Meta().(*AWSClient)
platforms := client.supportedplatforms
Expand Down Expand Up @@ -697,31 +754,16 @@ provider "awssameaccountalternateregion" {

// Deprecated: Use testAccMultipleRegionProviderConfig instead
func testAccAlternateRegionProviderConfig() string {
//lintignore:AT004
return fmt.Sprintf(`
provider "awsalternate" {
region = %[1]q
}
`, testAccGetAlternateRegion())
return testAccNamedRegionalProviderConfig(ProviderNameAwsAlternate, testAccGetAlternateRegion())
}

func testAccMultipleRegionProviderConfig(regions int) string {
var config strings.Builder

//lintignore:AT004
fmt.Fprintf(&config, `
provider "awsalternate" {
region = %[1]q
}
`, testAccGetAlternateRegion())
config.WriteString(testAccNamedRegionalProviderConfig(ProviderNameAwsAlternate, testAccGetAlternateRegion()))

if regions >= 3 {
//lintignore:AT004
fmt.Fprintf(&config, `
provider "awsthird" {
region = %[1]q
}
`, testAccGetThirdRegion())
config.WriteString(testAccNamedRegionalProviderConfig(ProviderNameAwsThird, testAccGetThirdRegion()))
}

return config.String()
Expand Down Expand Up @@ -749,19 +791,41 @@ provider "aws" {
`, key1)
}

// testAccNamedRegionalProviderConfig creates a new provider named configuration with a region.
//
// This can be used to build multiple provider configuration testing.
func testAccNamedRegionalProviderConfig(providerName string, region string) string {
//lintignore:AT004
return fmt.Sprintf(`
provider %[1]q {
region = %[2]q
}
`, providerName, region)
}

// testAccRegionalProviderConfig creates a new provider configuration with a region.
//
// This can only be used for single provider configuration testing as it
// overwrites the "aws" provider configuration.
func testAccRegionalProviderConfig(region string) string {
//lintignore:AT004
return fmt.Sprintf(`
provider "aws" {
region = %[1]q
}
`, region)
}

// Provider configuration hardcoded for us-east-1.
// This should only be necessary for testing ACM Certificates with CloudFront
// related infrastucture such as API Gateway Domain Names for EDGE endpoints,
// CloudFront Distribution Viewer Certificates, and Cognito User Pool Domains.
// Other valid usage is for services only available in us-east-1 such as the
// Cost and Usage Reporting and Pricing services.
//
// Deprecated: This will be replaced with service specific provider configurations.
func testAccUsEast1RegionProviderConfig() string {
//lintignore:AT004
return `
provider "awsus-east-1" {
region = "us-east-1"
}
`
return testAccNamedRegionalProviderConfig(ProviderNameAwsUsEast1, endpoints.UsEast1RegionID)
}

func testAccAwsRegionProviderFunc(region string, providers *[]*schema.Provider) func() *schema.Provider {
Expand Down
Loading

0 comments on commit fd841b4

Please sign in to comment.