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:
ParamDBInstanceIdentifier:
It contains the name of the Database instance.ParamDBInstanceClass:
It contains the Instance type associated with the database instance.ParamAllocatedStorage:
Contains the amount of storage allocated for the database instance.ParamStorageType:
Allocates the desired storage type for the RDS instance.ParamMasterUsername:
Defines the username for the master user account.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