AWS::S3::Bucket - BucketName accesible via Fn::GetAtt
Make the BucketName accessible using Fn::GetAtt on an AWS::S3::Bucket resource.
Get back the bucket's name created for the AWS::S3::Bucket resource, e.g. mycompany-mybucket.
N/A
N/A
Storage
We're using a 3rd party Python Lambda - maybe provided by AWS itself, I don't know - which expects an S3 bucket name - not an ARN, not an URL, not a DomainName. Currently we're generating the bucket's name using the environmental information like this:
"Fn::Sub": "mycompany-${AWS::StackName}-${AParameter}-${AWS::Region}"
It would be easier if we can fetch the bucket name from the S3 resource itself and we don't have to copy/paste that "rule" everywhere where we want to use the bucket's name.
"Fn::GetAtt": [ "MyBucket", "BucketName" ]
It's shorter and if the bucket name generation changes we don't have to search and replace every occurences. I know I can solve this with Fn::GetAtt.Arn, Fn::Split and Fn::Select but thats even complicated and silently assumes that the number of double colons (:) doesn't change in the ARN.
The bucket name available; it's returned by Fn::Ref, rather than by Fn::GetAtt: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket-return-values
Hmmm... That's not the resource name? If it's really the BucketName, then it's okay, just the documentation tricked me.
In CloudFormation, for every resource, you have a logical resource id and a physical resource id. The logical resource id is the name for that resource within a stack. The physical resource id is a type-specific unique identifier. It's usually either the name or the ARN of the resource, it (sadly) varies by resource type. In the case of AWS::S3::Bucket, it's the name (i.e., the bucket name). Similarly, for AWS::DynamoDB::Table, it's the table name. But for AWS::ECS::Service, Fn::Ref returns the ARN, and Name is an attribute. This can be frustratingly inconsistent, but here's a cheatsheet for it.
So if you had this resource:
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
...
the logical id of the resource is MyBucket. Creating the stack creates a bucket resource with a name something like mystack-mybucket-kdwwxmddtr2g. The physical resource id of the MyBucket resource is then mystack-mybucket-kdwwxmddtr2g. Fn::Ref returns the physical resource id, so mystack-mybucket-kdwwxmddtr2g. And Fn::GetAtt MyBucket.Arn returns aws:s3:::mystack-mybucket-kdwwxmddtr2g
I submitted feedback on that docs page that they should make it explicit that the value of !Ref is the bucket name.
Also note that when you are viewing a stack in the console, the "Resources" tab shows you a table with both logical id and physical id. With the CLI, this is aws cloudformation describe-stack-resources
Thanks. When I use !Ref then I usually get back the Logical Id for other kind of resources - or the ARN as you wrote - so that's what confused me in this case. I think too that it's worth to emphasize this behaviour in the docs more clearly.
Fn::Ref always returns the physical resource id, for all resources. The logical id only exists inside the template, and you already know the value of it inside the template: it's the _input_ to Fn::Ref and Fn::GetAtt. When you say Fn::Ref MyBucket or Fn::GetAtt MyBucket.Arn, you're using the logical id, which is MyBucket. So for most CloudFormation resource types, when you want the resource name (which is the bucket name for AWS::S3::Bucket, the table name for AWS::DynamoDB::Table, the function name for AWS::Lambda::Function, ...), you're going to use Fn::Ref.
Most helpful comment
In CloudFormation, for every resource, you have a logical resource id and a physical resource id. The logical resource id is the name for that resource within a stack. The physical resource id is a type-specific unique identifier. It's usually either the name or the ARN of the resource, it (sadly) varies by resource type. In the case of
AWS::S3::Bucket, it's the name (i.e., the bucket name). Similarly, forAWS::DynamoDB::Table, it's the table name. But forAWS::ECS::Service,Fn::Refreturns the ARN, andNameis an attribute. This can be frustratingly inconsistent, but here's a cheatsheet for it.So if you had this resource:
the logical id of the resource is
MyBucket. Creating the stack creates a bucket resource with a name something likemystack-mybucket-kdwwxmddtr2g. The physical resource id of theMyBucketresource is thenmystack-mybucket-kdwwxmddtr2g.Fn::Refreturns the physical resource id, somystack-mybucket-kdwwxmddtr2g. AndFn::GetAtt MyBucket.Arnreturnsaws:s3:::mystack-mybucket-kdwwxmddtr2g