Metadata

Metadata

Everything you need to know about CloudFormation Metadata. The next top-level section of AWS CloudFormation

Introduction

The Metadata section acts as a powerful tool that boosts the functionality and manageability of your template. In this blog post, we will look at the advantages of using Metadata in CloudFormation templates, its relation to Parameters, and other relevant information to help you make the most of this feature.

But first, why do we need the Metadata section?

It's responsible for grouping and labelling related Parameters together to enforce order, structure and readability.

Recap

Do you recall the template below from our previous blog post?

AWSTemplateFormatVersion: 2010-09-09
Description: Creating an ec2 instance
Parameters:
  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
  ParamInstanceType:
    Description: Select the Instance Type from the list
    Type: AWS::SSM::Parameter::Value<String>
  ParamDBInstanceIdentifier:
    Description: RDS Database Instance Name
    Type: String
    MinLength: '1'
    MaxLength: '64'
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only
    ConstraintDescription: Allows alphanumerics
  ParamDBInstanceClass:
    Description: DB Instance Class for the RDS Instance
    Type: String
    Default: db.t3.micro
  ParamAllocatedStorage: 
    Default: '30'
    Description: Storage for RDS Instance
    Type: Number
    MinValue: '20'
    MaxValue: '6144'
  ParamStorageType:
    Description: DB Storage type for the RDS Instance
    Type: String
    Default: gp2
  ParamMasterUsername:
    Description: DB Username for the RDS Instance
    Type: String
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only
  ParamMasterUserPassword:
    NoEcho: true
    Description: The database master user account password
    Type: String
    MinLength: '1'
    MaxLength: '41'
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only. Min 8 characters
    ConstraintDescription: Please use a secure password that only consists of alphanumerics
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
  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow RDS traffic 
      GroupName: DemoRDSSecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '3306'
          ToPort: '3306'
          CidrIp: 0.0.0.0/0
  MyEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-0571c1aedb4b8c5fc
      KeyName: !Ref ParamKeyName
      AvailabilityZone: !Ref ParamAZName
      InstanceType: !Ref ParamInstanceType
      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 Web Server!</h1></html>' > /var/www/html/index.html
      SecurityGroups: 
        - default
        - !Ref HTTpSShSecurityGroup
  MyRDSInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: !Ref ParamAllocatedStorage
      DBInstanceIdentifier: !Ref ParamDBInstanceIdentifier
      DBInstanceClass: !Ref ParamDBInstanceClass
      StorageType: !Ref ParamStorageType
      MasterUsername: !Ref ParamMasterUsername
      MasterUserPassword: !Ref ParamMasterUserPassword
      VPCSecurityGroups: 
        - !GetAtt RDSSecurityGroup.GroupId
      Engine: mysql
      PubliclyAccessible: true
      Tags:
        - Key: Name
          Value: Demo

This is what is displayed in the console once you upload the template above.

Take note of how the Parameters are disorganized. You would expect the Database Parameters to be listed together in a specific order followed by EC2 Instance Parameters i.e. ParamStorageType, ParamInstanceType, ParamAZName but instead, they are randomly ordered.

It provides descriptive information about each parameter, explaining its meaning, purpose, and expected format. This makes it easier to understand what each parameter does and how to use it effectively.

With Metadata, you get to group and categorize related Parameters. This reduces errors and confusion among multiple users when dealing with complex configurations. In essence, Metadata stands between raw parameters and human understanding.

Sample Template

Below is a template of the Metadata section and how it brings order and structure to situations with many parameters.

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Default RDS DB Instance Configuration
        Parameters:
          - ParamDBInstanceIdentifier
          - ParamDBInstanceClass
          - ParamAllocatedStorage
          - ParamStorageType
          - ParamMasterUsername
          - ParamMasterUserPassword
      - Label:
          default: EC2 Instance Configuration
        Parameters:
          - ParamInstanceType
          - ParamAZName 
          - ParamKeyName

    ParameterLabels:
      ParamDBInstanceIdentifier:
        default: DB Instance Identifier
      ParamDBInstanceClass:
        default: DB Instance Class
      ParamAllocatedStorage:
        default: Allocated Storage
      ParamStorageType:
        default: Storage Type
      ParamMasterUsername:
        default: Master Username
      ParamMasterUserPassword:
        default: Master Password
      ParamAZName:
        default: Availability Zone Name

The Parameters you see above are categorized into 2: Default RDS DB Instance Configuration and EC2 Instance Configuration.

Every parameter belongs to a label that explains its purpose and thus makes the configuration easier to understand.

Let us break down the code for easier understanding.

Parameter Groups

This section comprises of two groups of Parameters. One being the Default RDS DB Instance Configuration and EC2 Instance Configuration

Default RDS DB Instance Configuration

This Parameter Group will contain all configurations that relate to the RDS Instance.

It contains the following Parameters:

  1. ParamDBInstanceIdentifier: It contains the name of the Database instance.

  2. ParamDBInstanceClass: It contains the Instance type associated with the database instance.

  3. ParamAllocatedStorage: Contains the amount of storage allocated for the database instance.

  4. ParamStorageType: Allocates the desired storage type for the RDS instance.

  5. ParamMasterUsername: Defines the username for the master user account.

  6. ParamMasterUserPassword: Defines the password that belongs to the master user account.

EC2 Instance Configuration

This Parameter group will contain all configurations that relate to the EC2 Instance.

It contains the following Parameters:

  • ParamInstanceType: This section contains the instance type of the EC2 instance (e.g., compute optimized, storage optimized).

  • ParamAZName: This section contains the the Availability Zone for the EC2 instance.

  • ParamKeyName: This section contains the name of the existing key pair you'll use to ssh to the EC2 instance.

Parameter Labels

This section comprises of labels you wish to include for your parameters. They are responsible for defining the purpose of every parameter. This helps any user understand the configurations easier.

ParameterLabels:
      ParamDBInstanceIdentifier:
        default: DB Instance Identifier

This is one of the Parameter Labels that allows us to describe the role of that Parameter or what the Parameter is used for.

Sample Template with the Metadata Section

Check out the template below and notice how Parameter Labels and Parameter Groups are used to group and label related Parameters together for the sake of maintaining order, structure and readability of your Parameters.

AWSTemplateFormatVersion: 2010-09-09
Description: Creating an ec2 instance

Parameters:

  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

  ParamInstanceType:
    Description: Select the Instance Type from the list
    Type: AWS::SSM::Parameter::Value<String>


  ParamDBInstanceIdentifier:
    Description: RDS Database Instance Name
    Type: String
    MinLength: '1'
    MaxLength: '64'
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only
    ConstraintDescription: Allows alphanumerics


  ParamDBInstanceClass:
    Description: DB Instance Class for the RDS Instance
    Type: String
    Default: db.t3.micro

  ParamAllocatedStorage: 
    Default: '30'
    Description: Storage for RDS Instance
    Type: Number
    MinValue: '20'
    MaxValue: '6144'

  ParamStorageType:
    Description: DB Storage type for the RDS Instance
    Type: String
    Default: gp2

  ParamMasterUsername:
    Description: DB Username for the RDS Instance
    Type: String
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only

  ParamMasterUserPassword:
    NoEcho: true
    Description: The database master user account password
    Type: String
    MinLength: '1'
    MaxLength: '41'
    AllowedPattern: '^[A-Za-z0-9]*$'  # Allows alphanumerics only. 
    ConstraintDescription: Please use a secure password that only consists of alphanumerics

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Default RDS DB Instance Configuration
        Parameters:
          - ParamDBInstanceIdentifier
          - ParamDBInstanceClass
          - ParamAllocatedStorage
          - ParamStorageType
          - ParamMasterUsername
          - ParamMasterUserPassword
      - Label:
          default: EC2 Instance Configuration
        Parameters:
          - ParamInstanceType
          - ParamAZName 
          - ParamKeyName

    ParameterLabels:
      ParamDBInstanceIdentifier:
        default: DB Instance Identifier
      ParamDBInstanceClass:
        default: DB Instance Class
      ParamAllocatedStorage:
        default: Allocated Storage
      ParamStorageType:
        default: Storage Type
      ParamMasterUsername:
        default: Master Username
      ParamMasterUserPassword:
        default: Master Password
      ParamAZName:
        default: Availability Zone Name

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

  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow RDS traffic 
      GroupName: DemoRDSSecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '3306'
          ToPort: '3306'
          CidrIp: 0.0.0.0/0

  MyEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-0571c1aedb4b8c5fc
      KeyName: !Ref ParamKeyName
      AvailabilityZone: !Ref ParamAZName
      InstanceType: !Ref ParamInstanceType
      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: 
        - default
        - !Ref HTTpSShSecurityGroup

  MyRDSInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: !Ref ParamAllocatedStorage
      DBInstanceIdentifier: !Ref ParamDBInstanceIdentifier
      DBInstanceClass: !Ref ParamDBInstanceClass
      StorageType: !Ref ParamStorageType
      MasterUsername: !Ref ParamMasterUsername
      MasterUserPassword: !Ref ParamMasterUserPassword
      VPCSecurityGroups: 
        - !GetAtt RDSSecurityGroup.GroupId
      Engine: mysql
      PubliclyAccessible: true
      Tags:
        - Key: Name
          Value: Demo