Everything you need to know about CloudFormation Metadata. The next top-level section of AWS CloudFormation
Introduction
Imagine of a situation where you want your CloudFormation template to deploy your infrastructure in different environments, such as development (dev), testing (test), and production (prod). I mean, uploading one template to deploy a dev environment, using the same template to also deploy a test environment and finally using the same template to deploy a prod environment. That sounds cool, right?
With Mappings, you reduce redundancy by avoiding the need to create and maintain separate templates for each environment.
So, What are Mappings?
Mappings allow you to create a fixed set of values that can be referenced within your template.
They are key pairs that you use to dynamically configure your resources based on specific conditions. You basically store fixed information in Mappings and then reference it in your template. This prevents you from repeatedly hardcoding values such AMI IDs, instance types, or any other configuration settings multiple times.
This will come in handy when you have different settings for your environments or regions but still want to use the same template.
How Do Mappings Work?
You create maps that contain keys and values that you would want to reference in different sections of the template.
It is important to note that Mappings work with Parameters, Conditions and Resources.
Mappings: # Allows cloudformation to use only these AMIs in the following regions.
MapEc2Region:
us-east-2:
AMI_ID: ami-0eb9d67c52f5c80e5 # Replace the AMI ID with the ones you see on EC2 Console
us-west-2:
AMI_ID: ami-0eb9d67c52f5c80e5
From the code snippet above, we have a region-based mapping.
MapEc2Region:
- Represents the name of the map. You decide on the map name.us-east-2:
- Represents the top-level key.- For this case, the region top-level key has to be the specific regions you want to be referenced in your resources.
AMI_ID:
- Represents the second-level key.- Represents the ami-id that will be used by the resources you specify in the region you indicated as the top-level key.
Assuming we create an ec2-instance, we will have to reference this map on the instance's
ImageId
property.Resources: DemoEC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !FindInMap - MapEc2Region - !Ref AWS::Region - AMI_ID
In the EC2 Instance resource, you use the !FindInMap
intrinsic function to dynamically select the appropriate AMI ID based on the region where the stack is deployed.
Once you have identified the intrinsic function used to retrieve the image id, you will need to add three arguments as a list for the FindInMap
function. Here is a detailed breakdown:
MapEc2Region
- You will need to indicate the specific map name that will be used to retrieve the ami-id.
!Ref AWS::Region
- We use Ref
intrinsic function to reference the top level key MapEc2Region
AMI_ID
- The specific second-level key within the top-level key that retrieves the corresponding ami-id.
Template Example
Below is a template with Mappings, Parameters and Resources. Take note of how the mappings are being referenced within the template.
AWSTemplateFormatVersion: 2010-09-09
Description: Creating an ec2 instance
Parameters:
ParamEnvironmentType:
Description: Select the Environment Type from the list
Type: String
Default: Dev
AllowedValues:
- Prod
- Dev
ParamKeyName:
Description: Select the key name from the list
Type: AWS::EC2::KeyPair::KeyName
ParamAZName:
Description: Select the Avaiability Zone name from the list
Type: AWS::EC2::AvailabilityZone::Name
Mappings: # Allows cloudformation to use only these AMIs in the following regions.
MapEc2Region:
us-east-2:
AMI: ami-01572eda7c4411960 # Replace the AMI ID with the ones you see on EC2 Console
us-west-2:
AMI: ami-01572eda7c4411960
MapEnvironmentType: # Allows cloudformation to only use these instances depending on the Env type
Prod:
InstanceType: t3.micro
Dev:
InstanceType: t3.small
Resources:
HTTpSShSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP and SSH traffic
GroupName: DemoHTTPSShSecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
MyEC2Instance1:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap
- MapEc2Region # Mapping Name
- !Ref AWS::Region # Top-Level Key
- AMI # Second-Level Key
KeyName: !Ref ParamKeyName
AvailabilityZone: !Ref ParamAZName
InstanceType: !FindInMap
- MapEnvironmentType
- !Ref ParamEnvironmentType
- InstanceType
Tags:
- Key: Name
Value: DevInstance
UserData:
Fn::Base64: |
#!/bin/bash -xe
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo '<html><h1>Hello From Your Restart Web Server!</h1></html>' > /var/www/html/index.html
SecurityGroups:
- !Ref HTTpSShSecurityGroup
Key Takeaways
Flexibility and Reusability
Mappings let you dynamically adjust your template to fit different scenarios without making any changes to the template. e.g. Having different environments (dev, test, prod), with different instance types supported for your instances that can be deployed in different regions.
Maintainability
Mappings make it easy to centrally manage and update your configurations. Any changes needed promptly can be easily implemented without searching through the entire template.