-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests/provider: Migrate environment variable functionality into share…
…d package with constants and testing (#17197) Reference: #17083 Other environment variable handling in the code and testing can be migrated in the future for consistency. Please note that if attempting to use the returned value in a test configuration function, it must be done outside the test PreCheck function due to execution during compilation versus run. Without GITHUB_TOKEN set: ``` === RUN TestAccAWSCodePipeline_WithGitHubv1SourceAction resource_aws_codepipeline_test.go:470: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline source configuration --- SKIP: TestAccAWSCodePipeline_WithGitHubv1SourceAction (0.00s) === RUN TestAccAWSCodePipelineWebhook_basic resource_aws_codepipeline_webhook_test.go:18: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline webhook creation --- SKIP: TestAccAWSCodePipelineWebhook_basic (0.00s) === RUN TestAccAWSCodePipelineWebhook_ipAuth resource_aws_codepipeline_webhook_test.go:52: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline webhook creation --- SKIP: TestAccAWSCodePipelineWebhook_ipAuth (0.00s) === RUN TestAccAWSCodePipelineWebhook_unauthenticated resource_aws_codepipeline_webhook_test.go:86: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline webhook creation --- SKIP: TestAccAWSCodePipelineWebhook_unauthenticated (0.00s) === RUN TestAccAWSCodePipelineWebhook_tags resource_aws_codepipeline_webhook_test.go:118: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline webhook creation --- SKIP: TestAccAWSCodePipelineWebhook_tags (0.00s) === RUN TestAccAWSCodePipelineWebhook_UpdateAuthenticationConfiguration_SecretToken resource_aws_codepipeline_webhook_test.go:181: skipping test; environment variable GITHUB_TOKEN must be set. Usage: token with GitHub permissions to repository for CodePipeline webhook creation --- SKIP: TestAccAWSCodePipelineWebhook_UpdateAuthenticationConfiguration_SecretToken (0.00s) ``` Output from acceptance testing: ``` # Verify GITHUB_TOKEN working --- PASS: TestAccAWSCodePipeline_WithGitHubv1SourceAction (55.64s) --- PASS: TestAccAWSCodePipelineWebhook_basic (32.74s) --- PASS: TestAccAWSCodePipelineWebhook_ipAuth (33.24s) --- PASS: TestAccAWSCodePipelineWebhook_tags (71.80s) --- PASS: TestAccAWSCodePipelineWebhook_unauthenticated (32.65s) --- PASS: TestAccAWSCodePipelineWebhook_UpdateAuthenticationConfiguration_SecretToken (54.08s) # Verify cross-region and cross-account --- PASS: TestAccAWSDynamoDbTable_Replica_Multiple (1646.42s) --- PASS: TestAccAWSRoute53ZoneAssociation_CrossAccount (160.38s) --- PASS: TestAccAWSProvider_AssumeRole_Empty (15.68s) --- PASS: TestAccAWSProvider_Endpoints (13.10s) --- PASS: TestAccAWSProvider_IgnoreTags_EmptyConfigurationBlock (12.44s) --- PASS: TestAccAWSProvider_IgnoreTags_KeyPrefixes_Multiple (12.87s) --- PASS: TestAccAWSProvider_IgnoreTags_KeyPrefixes_None (12.49s) --- PASS: TestAccAWSProvider_IgnoreTags_KeyPrefixes_One (12.71s) --- PASS: TestAccAWSProvider_IgnoreTags_Keys_Multiple (12.57s) --- PASS: TestAccAWSProvider_IgnoreTags_Keys_None (12.23s) --- PASS: TestAccAWSProvider_IgnoreTags_Keys_One (12.71s) --- PASS: TestAccAWSProvider_Region_AwsChina (9.82s) --- PASS: TestAccAWSProvider_Region_AwsCommercial (10.42s) --- PASS: TestAccAWSProvider_Region_AwsGovCloudUs (11.37s) ```
- Loading branch information
Showing
10 changed files
with
378 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package envvar | ||
|
||
// Standard AWS environment variables used in the Terraform AWS Provider testing. | ||
// These are not provided as constants in the AWS Go SDK currently. | ||
const ( | ||
// Default static credential identifier for tests (AWS Go SDK does not provide this as constant) | ||
// See also AWS_SECRET_ACCESS_KEY and AWS_PROFILE | ||
AwsAccessKeyId = "AWS_ACCESS_KEY_ID" | ||
|
||
// Container credentials endpoint | ||
// See also AWS_ACCESS_KEY_ID and AWS_PROFILE | ||
AwsContainerCredentialsFullUri = "AWS_CONTAINER_CREDENTIALS_FULL_URI" | ||
|
||
// Default AWS region for tests (AWS Go SDK does not provide this as constant) | ||
AwsDefaultRegion = "AWS_DEFAULT_REGION" | ||
|
||
// Default AWS shared configuration profile for tests (AWS Go SDK does not provide this as constant) | ||
AwsProfile = "AWS_PROFILE" | ||
|
||
// Default static credential value for tests (AWS Go SDK does not provide this as constant) | ||
// See also AWS_ACCESS_KEY_ID and AWS_PROFILE | ||
AwsSecretAccessKey = "AWS_SECRET_ACCESS_KEY" | ||
) | ||
|
||
// Custom environment variables used in the Terraform AWS Provider testing. | ||
// Additions should also be documented in the Environment Variable Dictionary | ||
// of the Maintainers Guide: docs/MAINTAINING.md | ||
const ( | ||
// For tests using an alternate AWS account, the equivalent of AWS_ACCESS_KEY_ID for that account | ||
AwsAlternateAccessKeyId = "AWS_ALTERNATE_ACCESS_KEY_ID" | ||
|
||
// For tests using an alternate AWS account, the equivalent of AWS_PROFILE for that account | ||
AwsAlternateProfile = "AWS_PROFILE" | ||
|
||
// For tests using an alternate AWS region, the equivalent of AWS_DEFAULT_REGION for that account | ||
AwsAlternateRegion = "AWS_ALTERNATE_REGION" | ||
|
||
// For tests using an alternate AWS account, the equivalent of AWS_SECRET_ACCESS_KEY for that account | ||
AwsAlternateSecretAccessKey = "AWS_ALTERNATE_SECRET_ACCESS_KEY" | ||
|
||
// For tests using a third AWS region, the equivalent of AWS_DEFAULT_REGION for that region | ||
AwsThirdRegion = "AWS_THIRD_REGION" | ||
|
||
// For tests requiring GitHub permissions | ||
GithubToken = "GITHUB_TOKEN" | ||
|
||
// For tests requiring restricted IAM permissions, an existing IAM Role to assume | ||
// An inline assume role policy is then used to deny actions for the test | ||
TfAccAssumeRoleArn = "TF_ACC_ASSUME_ROLE_ARN" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// envvar contains constants and helpers for environment variable usage in testing. | ||
package envvar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package envvar | ||
|
||
import ( | ||
"os" | ||
) | ||
|
||
// GetWithDefault gets an environment variable value if non-empty or returns the default. | ||
func GetWithDefault(variable string, defaultValue string) string { | ||
value := os.Getenv(variable) | ||
|
||
if value == "" { | ||
return defaultValue | ||
} | ||
|
||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package envvar_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/terraform-providers/terraform-provider-aws/aws/internal/envvar" | ||
) | ||
|
||
func TestGetWithDefault(t *testing.T) { | ||
envVar := "TESTENVVAR_GETWITHDEFAULT" | ||
|
||
t.Run("missing", func(t *testing.T) { | ||
want := "default" | ||
|
||
os.Unsetenv(envVar) | ||
|
||
got := envvar.GetWithDefault(envVar, want) | ||
|
||
if got != want { | ||
t.Fatalf("expected %s, got %s", want, got) | ||
} | ||
}) | ||
|
||
t.Run("empty", func(t *testing.T) { | ||
want := "default" | ||
|
||
os.Setenv(envVar, "") | ||
defer os.Unsetenv(envVar) | ||
|
||
got := envvar.GetWithDefault(envVar, want) | ||
|
||
if got != want { | ||
t.Fatalf("expected %s, got %s", want, got) | ||
} | ||
}) | ||
|
||
t.Run("not empty", func(t *testing.T) { | ||
want := "notempty" | ||
|
||
os.Setenv(envVar, want) | ||
defer os.Unsetenv(envVar) | ||
|
||
got := envvar.GetWithDefault(envVar, "default") | ||
|
||
if got != want { | ||
t.Fatalf("expected %s, got %s", want, got) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package envvar | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/mitchellh/go-testing-interface" | ||
) | ||
|
||
// TestFailIfAllEmpty verifies that at least one environment variable is non-empty or fails the test. | ||
// | ||
// If at lease one environment variable is non-empty, returns the first name and value. | ||
func TestFailIfAllEmpty(t testing.T, names []string, usageMessage string) (string, string) { | ||
t.Helper() | ||
|
||
for _, variable := range names { | ||
value := os.Getenv(variable) | ||
|
||
if value != "" { | ||
return variable, value | ||
} | ||
} | ||
|
||
t.Fatalf("at least one environment variable of %v must be set. Usage: %s", names, usageMessage) | ||
|
||
return "", "" | ||
} | ||
|
||
// TestFailIfEmpty verifies that an environment variable is non-empty or fails the test. | ||
// | ||
// For acceptance tests, this function must be used outside PreCheck functions to set values for configurations. | ||
func TestFailIfEmpty(t testing.T, name string, usageMessage string) string { | ||
t.Helper() | ||
|
||
value := os.Getenv(name) | ||
|
||
if value == "" { | ||
t.Fatalf("environment variable %s must be set. Usage: %s", name, usageMessage) | ||
} | ||
|
||
return value | ||
} | ||
|
||
// TestSkipIfEmpty verifies that an environment variable is non-empty or skips the test. | ||
// | ||
// For acceptance tests, this function must be used outside PreCheck functions to set values for configurations. | ||
func TestSkipIfEmpty(t testing.T, name string, usageMessage string) string { | ||
t.Helper() | ||
|
||
value := os.Getenv(name) | ||
|
||
if value == "" { | ||
t.Skipf("skipping test; environment variable %s must be set. Usage: %s", name, usageMessage) | ||
} | ||
|
||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package envvar_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
testingiface "github.com/mitchellh/go-testing-interface" | ||
"github.com/terraform-providers/terraform-provider-aws/aws/internal/envvar" | ||
) | ||
|
||
func TestTestFailIfAllEmpty(t *testing.T) { | ||
envVar1 := "TESTENVVAR_FAILIFALLEMPTY1" | ||
envVar2 := "TESTENVVAR_FAILIFALLEMPTY2" | ||
envVars := []string{envVar1, envVar2} | ||
|
||
t.Run("missing", func(t *testing.T) { | ||
defer testingifaceRecover() | ||
|
||
for _, envVar := range envVars { | ||
os.Unsetenv(envVar) | ||
} | ||
|
||
envvar.TestFailIfAllEmpty(&testingiface.RuntimeT{}, envVars, "usage") | ||
|
||
t.Fatal("expected to fail previously") | ||
}) | ||
|
||
t.Run("all empty", func(t *testing.T) { | ||
defer testingifaceRecover() | ||
|
||
os.Setenv(envVar1, "") | ||
os.Setenv(envVar2, "") | ||
defer unsetEnvVars(envVars) | ||
|
||
envvar.TestFailIfAllEmpty(&testingiface.RuntimeT{}, envVars, "usage") | ||
|
||
t.Fatal("expected to fail previously") | ||
}) | ||
|
||
t.Run("some empty", func(t *testing.T) { | ||
wantValue := "pickme" | ||
|
||
os.Setenv(envVar1, "") | ||
os.Setenv(envVar2, wantValue) | ||
defer unsetEnvVars(envVars) | ||
|
||
gotName, gotValue := envvar.TestFailIfAllEmpty(&testingiface.RuntimeT{}, envVars, "usage") | ||
|
||
if gotName != envVar2 { | ||
t.Fatalf("expected name: %s, got: %s", envVar2, gotName) | ||
} | ||
|
||
if gotValue != wantValue { | ||
t.Fatalf("expected value: %s, got: %s", wantValue, gotValue) | ||
} | ||
}) | ||
|
||
t.Run("all not empty", func(t *testing.T) { | ||
wantValue := "pickme" | ||
|
||
os.Setenv(envVar1, wantValue) | ||
os.Setenv(envVar2, "other") | ||
defer unsetEnvVars(envVars) | ||
|
||
gotName, gotValue := envvar.TestFailIfAllEmpty(&testingiface.RuntimeT{}, envVars, "usage") | ||
|
||
if gotName != envVar1 { | ||
t.Fatalf("expected name: %s, got: %s", envVar1, gotName) | ||
} | ||
|
||
if gotValue != wantValue { | ||
t.Fatalf("expected value: %s, got: %s", wantValue, gotValue) | ||
} | ||
}) | ||
} | ||
|
||
func TestTestFailIfEmpty(t *testing.T) { | ||
envVar := "TESTENVVAR_FAILIFEMPTY" | ||
|
||
t.Run("missing", func(t *testing.T) { | ||
defer testingifaceRecover() | ||
|
||
os.Unsetenv(envVar) | ||
|
||
envvar.TestFailIfEmpty(&testingiface.RuntimeT{}, envVar, "usage") | ||
|
||
t.Fatal("expected to fail previously") | ||
}) | ||
|
||
t.Run("empty", func(t *testing.T) { | ||
defer testingifaceRecover() | ||
|
||
os.Setenv(envVar, "") | ||
defer os.Unsetenv(envVar) | ||
|
||
envvar.TestFailIfEmpty(&testingiface.RuntimeT{}, envVar, "usage") | ||
|
||
t.Fatal("expected to fail previously") | ||
}) | ||
|
||
t.Run("not empty", func(t *testing.T) { | ||
want := "notempty" | ||
|
||
os.Setenv(envVar, want) | ||
defer os.Unsetenv(envVar) | ||
|
||
got := envvar.TestFailIfEmpty(&testingiface.RuntimeT{}, envVar, "usage") | ||
|
||
if got != want { | ||
t.Fatalf("expected value: %s, got: %s", want, got) | ||
} | ||
}) | ||
} | ||
|
||
func TestTestSkipIfEmpty(t *testing.T) { | ||
envVar := "TESTENVVAR_SKIPIFEMPTY" | ||
|
||
t.Run("missing", func(t *testing.T) { | ||
mockT := &testingiface.RuntimeT{} | ||
|
||
os.Unsetenv(envVar) | ||
|
||
envvar.TestSkipIfEmpty(mockT, envVar, "usage") | ||
|
||
if !mockT.Skipped() { | ||
t.Fatal("expected to skip previously") | ||
} | ||
}) | ||
|
||
t.Run("empty", func(t *testing.T) { | ||
mockT := &testingiface.RuntimeT{} | ||
|
||
os.Setenv(envVar, "") | ||
defer os.Unsetenv(envVar) | ||
|
||
envvar.TestSkipIfEmpty(mockT, envVar, "usage") | ||
|
||
if !mockT.Skipped() { | ||
t.Fatal("expected to skip previously") | ||
} | ||
}) | ||
|
||
t.Run("not empty", func(t *testing.T) { | ||
want := "notempty" | ||
|
||
os.Setenv(envVar, want) | ||
defer os.Unsetenv(envVar) | ||
|
||
got := envvar.TestSkipIfEmpty(&testingiface.RuntimeT{}, envVar, "usage") | ||
|
||
if got != want { | ||
t.Fatalf("expected value: %s, got: %s", want, got) | ||
} | ||
}) | ||
} | ||
|
||
func testingifaceRecover() { | ||
r := recover() | ||
|
||
// this string is hardcoded in github.com/mitchellh/go-testing-interface | ||
if s, ok := r.(string); !ok || s != "testing.T failed, see logs for output (if any)" { | ||
panic(r) | ||
} | ||
} | ||
|
||
func unsetEnvVars(envVars []string) { | ||
for _, envVar := range envVars { | ||
os.Unsetenv(envVar) | ||
} | ||
} |
Oops, something went wrong.