Mappings

Mappings

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.