Add missing Fn::GetAtt attributes to S3 bucket mock (#3396)

* Add missing `Fn::GetAtt` attributes to S3 bucket mock

Addresses an issue reported here https://github.com/localstack/aws-cdk-local/issues/1

* Reformat touched files with `black`

* Reformat touched files with `black` on Python 3.7
This commit is contained in:
Neal Granger 2020-10-27 09:04:32 -07:00 committed by GitHub
parent 53cc3dd67a
commit a5fc14b5bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 8 deletions

View File

@ -66,7 +66,7 @@ OWNER = "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
def get_moto_s3_account_id():
"""This makes it easy for mocking AWS Account IDs when using AWS Config
-- Simply mock.patch the ACCOUNT_ID here, and Config gets it for free.
-- Simply mock.patch the ACCOUNT_ID here, and Config gets it for free.
"""
return ACCOUNT_ID
@ -1061,12 +1061,16 @@ class FakeBucket(CloudFormationModel):
def get_cfn_attribute(self, attribute_name):
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
if attribute_name == "DomainName":
raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "DomainName" ]"')
elif attribute_name == "WebsiteURL":
raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "WebsiteURL" ]"')
elif attribute_name == "Arn":
if attribute_name == "Arn":
return self.arn
elif attribute_name == "DomainName":
return self.domain_name
elif attribute_name == "DualStackDomainName":
return self.dual_stack_domain_name
elif attribute_name == "RegionalDomainName":
return self.regional_domain_name
elif attribute_name == "WebsiteURL":
return self.website_url
raise UnformattedGetAttTemplateException()
def set_acl(self, acl):
@ -1076,6 +1080,24 @@ class FakeBucket(CloudFormationModel):
def arn(self):
return "arn:aws:s3:::{}".format(self.name)
@property
def domain_name(self):
return "{}.s3.amazonaws.com".format(self.name)
@property
def dual_stack_domain_name(self):
return "{}.s3.dualstack.{}.amazonaws.com".format(self.name, self.region_name)
@property
def regional_domain_name(self):
return "{}.s3.{}.amazonaws.com".format(self.name, self.region_name)
@property
def website_url(self):
return "http://{}.s3-website.{}.amazonaws.com".format(
self.name, self.region_name
)
@property
def physical_resource_id(self):
return self.name

View File

@ -148,8 +148,9 @@ def test_s3_bucket_cloudformation_update_replacement():
@mock_s3
@mock_cloudformation
def test_s3_bucket_cloudformation_outputs():
s3 = boto3.client("s3", region_name="us-east-1")
cf = boto3.resource("cloudformation", region_name="us-east-1")
region_name = "us-east-1"
s3 = boto3.client("s3", region_name=region_name)
cf = boto3.resource("cloudformation", region_name=region_name)
stack_name = "test-stack"
bucket_name = "test-bucket"
template = {
@ -165,6 +166,26 @@ def test_s3_bucket_cloudformation_outputs():
"Value": {"Fn::GetAtt": ["TestBucket", "Arn"]},
"Export": {"Name": {"Fn::Sub": "${AWS::StackName}:BucketARN"}},
},
"BucketDomainName": {
"Value": {"Fn::GetAtt": ["TestBucket", "DomainName"]},
"Export": {"Name": {"Fn::Sub": "${AWS::StackName}:BucketDomainName"}},
},
"BucketDualStackDomainName": {
"Value": {"Fn::GetAtt": ["TestBucket", "DualStackDomainName"]},
"Export": {
"Name": {"Fn::Sub": "${AWS::StackName}:BucketDualStackDomainName"}
},
},
"BucketRegionalDomainName": {
"Value": {"Fn::GetAtt": ["TestBucket", "RegionalDomainName"]},
"Export": {
"Name": {"Fn::Sub": "${AWS::StackName}:BucketRegionalDomainName"}
},
},
"BucketWebsiteURL": {
"Value": {"Fn::GetAtt": ["TestBucket", "WebsiteURL"]},
"Export": {"Name": {"Fn::Sub": "${AWS::StackName}:BucketWebsiteURL"}},
},
"BucketName": {
"Value": {"Ref": "TestBucket"},
"Export": {"Name": {"Fn::Sub": "${AWS::StackName}:BucketName"}},
@ -176,4 +197,22 @@ def test_s3_bucket_cloudformation_outputs():
output = {item["OutputKey"]: item["OutputValue"] for item in outputs_list}
s3.head_bucket(Bucket=output["BucketName"])
output["BucketARN"].should.match("arn:aws:s3.+{bucket}".format(bucket=bucket_name))
output["BucketDomainName"].should.equal(
"{bucket}.s3.amazonaws.com".format(bucket=bucket_name)
)
output["BucketDualStackDomainName"].should.equal(
"{bucket}.s3.dualstack.{region}.amazonaws.com".format(
bucket=bucket_name, region=region_name
)
)
output["BucketRegionalDomainName"].should.equal(
"{bucket}.s3.{region}.amazonaws.com".format(
bucket=bucket_name, region=region_name
)
)
output["BucketWebsiteURL"].should.equal(
"http://{bucket}.s3-website.{region}.amazonaws.com".format(
bucket=bucket_name, region=region_name
)
)
output["BucketName"].should.equal(bucket_name)