Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #4540 Add new attribute bucket_regional_domain_name in aws_s3_bucket #4556

Merged
merged 6 commits into from
May 30, 2018

Conversation

saravanan30erd
Copy link
Contributor

Added new attribute bucket_regional_domain_name in aws_s3_bucket.

@ghost ghost added the size/M Managed by automation to categorize the size of a PR. label May 16, 2018
@bflad bflad added enhancement Requests to existing resources that expand the functionality or scope. service/s3 Issues and PRs that pertain to the s3 service. labels May 16, 2018
Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this @saravanan30erd -- please see the below and let us know if you have any questions.

@@ -1441,6 +1449,18 @@ func bucketDomainName(bucket string) string {
return fmt.Sprintf("%s.s3.amazonaws.com", bucket)
}

func bucketRegionalDomainName(bucket string, region string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS Go SDK contains an endpoints package which can automatically retrieve this information.

Here's the endpoints data set: https://github.com/aws/aws-sdk-go/blob/master/aws/endpoints/defaults.go

Theoretically we should be able to fetch the endpoint from the SDK package based on service (s3) and region. This should prevent future maintainability issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used endpoints package to retrieve region-specific endpoint.

Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
resource.TestCheckResourceAttr("aws_s3_bucket.bucket", "region", "ap-south-1"),
resource.TestCheckResourceAttr(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the other PR with a Computed: true attribute that is always available, this can be moved as a single check under the _basic test.

We also explicitly need the S3 testing to be able to run from AWS Commercial, AWS GovCloud (US), and AWS China which means that we cannot hard code a specific partition region. I believe there is a testAccProviderRegion() helper function which can aid us here.

If we want to ensure that specific regions are returning their expected domain names (e.g. cn-north-1 actually returning BUCKET.s3.cn-north-1.amazonaws.com.cn) I would highly recommend setting up unit testing for bucketRegionalDomainName as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I need to create separate test config, I used separate acceptance test TestAccAWSS3Bucket_bucketRegionalDomainName. I couldn't find testAccProviderRegion(), so I used the same endpoints package to choose region.

@@ -450,6 +450,7 @@ The following attributes are exported:
* `id` - The name of the bucket.
* `arn` - The ARN of the bucket. Will be of format `arn:aws:s3:::bucketname`.
* `bucket_domain_name` - The bucket domain name. Will be of format `bucketname.s3.amazonaws.com`.
* `bucket_regional_domain_name` - The bucket region-specific domain name. Will be of format `bucketname.s3-eu-west-1.amazonaws.com`. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent [redirect issues](https://forums.aws.amazon.com/thread.jspa?threadID=216814) from CloudFront to S3 Origin URL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than specifying bucketname.s3-eu-west-1.amazonaws.com here we should probably instead point to the AWS regions and endpoints documentation mentioning the domain name including the region name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@bflad bflad added the waiting-response Maintainers are waiting on response from community or contributor. label May 24, 2018
@ghost ghost added the size/M Managed by automation to categorize the size of a PR. label May 24, 2018
@saravanan30erd
Copy link
Contributor Author

$ make testacc TEST=./aws TESTARGS='-run=TestAccAWSS3Bucket_bucketRegionalDomainName'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSS3Bucket_bucketRegionalDomainName -timeout 120m
=== RUN TestAccAWSS3Bucket_bucketRegionalDomainName
--- PASS: TestAccAWSS3Bucket_bucketRegionalDomainName (67.64s)
PASS
ok github.com/terraform-providers/terraform-provider-aws/aws 67.687s

Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I need to create separate test config

Can you explain why this is necessary? A new single check in the existing _basic test should work just fine as it applies to all bucket resource configurations. testAccGetRegion() has the region information you need and on master is already available in the _basic test function. I would rebase the test file (as it currently shows a merge conflict) and simply just add something like the below rather than creating a new test and configuration:

resource.TestCheckResourceAttr("aws_s3_bucket.bucket", "bucket_regional_domain_name", testAccBucketRegionalDomainName(rInt, region)),

@@ -1331,6 +1356,26 @@ func testAccBucketDomainName(randInt int) string {
return fmt.Sprintf("tf-test-bucket-%d.s3.amazonaws.com", randInt)
}

func testAccFindRandomRegion() string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally in our acceptance testing we do not want to insert randomness as it leads to inconsistent testing behavior that makes troubleshooting harder than it needs to be.

Aside from that, as written this currently will enumerate a list of regions across all AWS partitions (Commercial, GovCloud (US), and China) while the testing credentials are only valid for one partition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@saravanan30erd
Copy link
Contributor Author

@bflad since I couldn't find testAccProviderRegion(), I thought it's better to provide region as input in separate test config and test the same. Now testAccGetRegion() fixed all the issues.

$ make testacc TEST=./aws TESTARGS='-run=TestAccAWSS3Bucket_basic'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSS3Bucket_basic -timeout 120m
=== RUN TestAccAWSS3Bucket_basic
--- PASS: TestAccAWSS3Bucket_basic (104.41s)
PASS
ok github.com/terraform-providers/terraform-provider-aws/aws 104.451s

reverting changes due to conflict
@ghost ghost added the size/M Managed by automation to categorize the size of a PR. label May 25, 2018
@saravanan30erd
Copy link
Contributor Author

@bflad is there anything I can do to push this?

@bflad bflad removed the waiting-response Maintainers are waiting on response from community or contributor. label May 30, 2018
@bflad
Copy link
Contributor

bflad commented May 30, 2018

@saravanan30erd there is currently a merge conflict in aws/resource_aws_s3_bucket_test.go and I'd like to add some quick unit testing for BucketRegionalDomainName. Fixing these on merge.

Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after fixing up the merge conflict! I went ahead and refactored the function to use endpoints.DefaultResolver().EndpointFor() to simplify it a bit:

// https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
func BucketRegionalDomainName(bucket string, region string) (string, error) {
	// Return a default AWS Commercial domain name if no region is provided
	// Otherwise EndpointFor() will return BUCKET.s3..amazonaws.com
	if region == "" {
		return fmt.Sprintf("%s.s3.amazonaws.com", bucket), nil
	}
	endpoint, err := endpoints.DefaultResolver().EndpointFor(endpoints.S3ServiceID, region)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s.%s", bucket, strings.TrimPrefix(endpoint.URL, "https://")), nil
}

Added unit testing:

func TestBucketRegionalDomainName(t *testing.T) {
	const bucket = "bucket-name"

	var testCases = []struct {
		ExpectedErrCount int
		ExpectedOutput   string
		Region           string
	}{
		{
			Region:           "",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.amazonaws.com",
		},
		{
			Region:           "custom",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.custom.amazonaws.com",
		},
		{
			Region:           "us-east-1",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.amazonaws.com",
		},
		{
			Region:           "us-west-2",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.us-west-2.amazonaws.com",
		},
		{
			Region:           "us-gov-west-1",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.us-gov-west-1.amazonaws.com",
		},
		{
			Region:           "cn-north-1",
			ExpectedErrCount: 0,
			ExpectedOutput:   bucket + ".s3.cn-north-1.amazonaws.com.cn",
		},
	}

	for _, tc := range testCases {
		output, err := BucketRegionalDomainName(bucket, tc.Region)
		if tc.ExpectedErrCount == 0 && err != nil {
			t.Fatalf("expected %q not to trigger an error, received: %s", tc.Region, err)
		}
		if tc.ExpectedErrCount > 0 && err == nil {
			t.Fatalf("expected %q to trigger an error", tc.Region)
		}
		if output != tc.ExpectedOutput {
			t.Fatalf("expected %q, received %q", tc.ExpectedOutput, output)
		}
	}
}

Everything looks good!

make test TEST=./aws
==> Checking that code complies with gofmt requirements...
go test ./aws -timeout=30s -parallel=4
ok  	github.com/terraform-providers/terraform-provider-aws/aws	1.830s
47 tests passed (all tests)
=== RUN   TestAccAWSS3BucketObject_content
--- PASS: TestAccAWSS3BucketObject_content (10.81s)
=== RUN   TestAccAWSS3BucketObject_contentBase64
--- PASS: TestAccAWSS3BucketObject_contentBase64 (10.96s)
=== RUN   TestAccAWSS3Bucket_importBasic
--- PASS: TestAccAWSS3Bucket_importBasic (11.22s)
=== RUN   TestAccAWSS3BucketObject_withContentCharacteristics
--- PASS: TestAccAWSS3BucketObject_withContentCharacteristics (11.60s)
=== RUN   TestAccAWSS3BucketObject_source
--- PASS: TestAccAWSS3BucketObject_source (18.25s)
=== RUN   TestAccAWSS3BucketNotification_withoutFilter
--- PASS: TestAccAWSS3BucketNotification_withoutFilter (18.53s)
=== RUN   TestAccAWSS3BucketObject_sse
--- PASS: TestAccAWSS3BucketObject_sse (25.37s)
=== RUN   TestAccAWSS3BucketObject_updatesWithVersioning
--- PASS: TestAccAWSS3BucketObject_updatesWithVersioning (26.34s)
=== RUN   TestAccAWSS3BucketMetric_basic
--- PASS: TestAccAWSS3BucketMetric_basic (31.70s)
=== RUN   TestAccAWSS3BucketMetric_WithFilterPrefixAndMultipleTags
--- PASS: TestAccAWSS3BucketMetric_WithFilterPrefixAndMultipleTags (31.75s)
=== RUN   TestAccAWSS3Bucket_importWithPolicy
--- PASS: TestAccAWSS3Bucket_importWithPolicy (33.41s)
=== RUN   TestAccAWSS3BucketObject_kms
--- PASS: TestAccAWSS3BucketObject_kms (36.69s)
=== RUN   TestAccAWSS3BucketObject_storageClass
--- PASS: TestAccAWSS3BucketObject_storageClass (25.96s)
=== RUN   TestAccAWSS3BucketObject_updates
--- PASS: TestAccAWSS3BucketObject_updates (42.09s)
=== RUN   TestAccAWSS3BucketObject_tags
--- PASS: TestAccAWSS3BucketObject_tags (32.45s)
=== RUN   TestAccAWSS3BucketMetric_WithFilterMultipleTags
--- PASS: TestAccAWSS3BucketMetric_WithFilterMultipleTags (46.79s)
=== RUN   TestAccAWSS3Bucket_namePrefix
--- PASS: TestAccAWSS3Bucket_namePrefix (28.52s)
=== RUN   TestAccAWSS3Bucket_basic
--- PASS: TestAccAWSS3Bucket_basic (32.95s)
=== RUN   TestAccAWSS3BucketPolicy_basic
--- PASS: TestAccAWSS3BucketPolicy_basic (41.27s)
=== RUN   TestAccAWSS3BucketMetric_WithFilterPrefix
--- PASS: TestAccAWSS3BucketMetric_WithFilterPrefix (56.61s)
=== RUN   TestAccAWSS3Bucket_region
--- PASS: TestAccAWSS3Bucket_region (35.26s)
=== RUN   TestAccAWSS3Bucket_enableDefaultEncryption_whenAES256IsUsed
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenAES256IsUsed (15.82s)
=== RUN   TestAccAWSS3BucketObject_acl
--- PASS: TestAccAWSS3BucketObject_acl (64.20s)
=== RUN   TestAccAWSS3BucketMetric_WithFilterSingleTag
--- PASS: TestAccAWSS3BucketMetric_WithFilterSingleTag (71.44s)
=== RUN   TestAccAWSS3Bucket_shouldFailNotFound
--- PASS: TestAccAWSS3Bucket_shouldFailNotFound (32.14s)
=== RUN   TestAccAWSS3Bucket_WebsiteRoutingRules
--- PASS: TestAccAWSS3Bucket_WebsiteRoutingRules (42.44s)
=== RUN   TestAccAWSS3BucketMetric_WithFilterPrefixAndSingleTag
--- PASS: TestAccAWSS3BucketMetric_WithFilterPrefixAndSingleTag (87.95s)
=== RUN   TestAccAWSS3Bucket_disableDefaultEncryption_whenDefaultEncryptionIsEnabled
--- PASS: TestAccAWSS3Bucket_disableDefaultEncryption_whenDefaultEncryptionIsEnabled (40.57s)
=== RUN   TestAccAWSS3Bucket_WebsiteRedirect
--- PASS: TestAccAWSS3Bucket_WebsiteRedirect (53.76s)
=== RUN   TestAccAWSS3BucketNotification_basic
--- PASS: TestAccAWSS3BucketNotification_basic (102.26s)
=== RUN   TestAccAWSS3Bucket_Logging
--- PASS: TestAccAWSS3Bucket_Logging (49.05s)
=== RUN   TestAccAWSS3Bucket_UpdateAcl
--- PASS: TestAccAWSS3Bucket_UpdateAcl (75.75s)
=== RUN   TestAccAWSS3Bucket_Website_Simple
--- PASS: TestAccAWSS3Bucket_Website_Simple (75.79s)
=== RUN   TestAccAWSS3Bucket_RequestPayer
--- PASS: TestAccAWSS3Bucket_RequestPayer (84.60s)
=== RUN   TestAccAWSS3Bucket_Cors
--- PASS: TestAccAWSS3Bucket_Cors (57.91s)
=== RUN   TestAccAWSS3Bucket_ReplicationExpectVersioningValidationError
--- PASS: TestAccAWSS3Bucket_ReplicationExpectVersioningValidationError (34.39s)
=== RUN   TestAccAWSS3BucketNotification_importBasic
--- PASS: TestAccAWSS3BucketNotification_importBasic (122.50s)
=== RUN   TestAccAWSS3Bucket_ReplicationWithoutStorageClass
--- PASS: TestAccAWSS3Bucket_ReplicationWithoutStorageClass (51.77s)
=== RUN   TestAccAWSS3BucketPolicy_policyUpdate
--- PASS: TestAccAWSS3BucketPolicy_policyUpdate (129.19s)
=== RUN   TestAccAWSS3Bucket_Versioning
--- PASS: TestAccAWSS3Bucket_Versioning (97.72s)
=== RUN   TestAccAWSS3Bucket_Lifecycle
--- PASS: TestAccAWSS3Bucket_Lifecycle (94.98s)
=== RUN   TestAccAWSS3Bucket_Policy
--- PASS: TestAccAWSS3Bucket_Policy (135.04s)
=== RUN   TestAccAWSS3Bucket_acceleration
--- PASS: TestAccAWSS3Bucket_acceleration (142.10s)
=== RUN   TestAccAWSS3Bucket_enableDefaultEncryption_whenTypical
--- PASS: TestAccAWSS3Bucket_enableDefaultEncryption_whenTypical (128.29s)
=== RUN   TestAccAWSS3Bucket_generatedName
--- PASS: TestAccAWSS3Bucket_generatedName (161.80s)
=== RUN   TestAccAWSS3Bucket_LifecycleExpireMarkerOnly
--- PASS: TestAccAWSS3Bucket_LifecycleExpireMarkerOnly (122.43s)
=== RUN   TestAccAWSS3Bucket_Replication
--- PASS: TestAccAWSS3Bucket_Replication (135.17s)

@bflad bflad added this to the v1.21.0 milestone May 30, 2018
@bflad bflad merged commit 97f375e into hashicorp:master May 30, 2018
bflad added a commit that referenced this pull request May 30, 2018
@saravanan30erd
Copy link
Contributor Author

Cool. The endpoints.DefaultResolver().EndpointFor is really simplifying the logic, I should have checked that.

@saravanan30erd saravanan30erd deleted the issue-4540 branch May 31, 2018 03:25
@bflad
Copy link
Contributor

bflad commented May 31, 2018

This has been released in version 1.21.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

@ghost
Copy link

ghost commented Apr 5, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope. service/s3 Issues and PRs that pertain to the s3 service. size/M Managed by automation to categorize the size of a PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants