Monday, April 1, 2019

Step by Step Troubleshooting and Validation of AWS CloudFormation Yaml template

CloudFormation (CFN) is infrastructure as a code service of AWS. You just tell CFN your desired state of resources and it creates them in order while resolving dependencies. You mention these resources in a file called as template which can be written in YAML or JSON. YAML being bit more user readable, is widely used now. YAML is great but you have to be aware of its indentation.


Following is a step by step troubleshooting and validation of a simple CFN template by using aws cli from windows 10 command prompt.

Step 1: Create your template file. I am using ec2.yaml which just creates an EC2 instance and a security group with some parameters and outputs.


#####################################################################################################
#  Template : Use to deploy simple T2.MICRO EC2 Instance with a security group
#
#  Author   : Fahd Mirza
#
#  Created on :  23rd March, 2019
#
#####################################################################################################
---
AWSTemplateFormatVersion: "2010-09-09"
Description: Deploy EC2 Instance with a security group
######################################################################################################
Parameters:
######################################################################################################
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.2xlarge
  MyRSAKey:
    Type: String
    Description: Supply your RSA Key Name
Mappings:
  RegionMap:
    us-east-1:
      AMI: ami-1853ac65
    us-west-1:
      AMI: ami-bf5540df
    eu-west-1:
      AMI: ami-3bfab942
    ap-southeast-1:
      AMI: ami-e2adf99e
    ap-southeast-2:
      AMI: ami-43874721   
######################################################################################################
Resources:
######################################################################################################
  MySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow SSH to EC2 Bastion Host
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: Name
        Value: MyBastionSG112
  MyEc2Instance:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        config:
          files:
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                    [main]
                    stack=${AWS::StackId}
                    region=${AWS::Region}
                    interval=1
              mode: '000744'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                     [cfn-auto-reloader-hook]
                     triggers=post.update
                     path=Resources.MyEc2Instance.Metadata.AWS::CloudFormation::Init
                     action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --region ${AWS::Region} --resource MyEc2Instance
                     runas=root
            ~/hello1.txt:
               content: !Sub |
                     hello world, I am from files section of CFN Init metadata.         
          commands:
            RunA:
              command: cat "hello world, I am from command section of CFN Init metadata." > ~/hello.txt
              ignoreErrors: "true"
          services:
              sysvinit:
                  cfn-hup:
                    enabled: true
                    ensureRunning: true
                    files: [/etc/cfn/cfn-hup.conf, /etc/cfn/hooks.d/cfn-auto-reloader.conf]
    Properties:
      Tags:
      - Key: Name
        Value: !Ref "AWS::StackName"
      ImageId:
        Fn::FindInMap:
        - RegionMap
        - !Ref AWS::Region
        - AMI       
      InstanceType:
        Ref: InstanceType
      KeyName:
        Ref: MyRSAKey
      UserData:
        Fn::Base64: !Sub |
              #!/bin/bash -xe
              yum install -y aws-cfn-bootstrap
              chkconfig --add cfn-hup
              /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource MyEc2Instance --region ${AWS::Region}
              /opt/aws/bin/cfn-signal -e 0 --stack ${AWS::StackName} --resource MyEc2Instance --region ${AWS::Region}
    CreationPolicy:
      ResourceSignal:
        Timeout: "PT15M"
######################################################################################################
Outputs:
######################################################################################################
  MyEC2InstancePublicIP:
    Description: My EC2 Instance Public IP
    Value: !GetAtt MyEc2Instance.PublicIp
  MyEC2InstanceID:
    Description: My EC2 Instance ID
    Value: !Ref MyEc2Instance
  MyEC2SecGroup:
    Description: My EC2 Security Group
    Value: !Ref MySecurityGroup

Step 2: When I first ran the validation on this template, it gave me error about its indentation like following. I fixed the indentation  by using simple editor. You can also use any online editor or Visual code studio.

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>dir
 Volume in drive C is Windows
 Volume Serial Number is 5285-4635

 Directory of C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates

23/03/2019  12:54 PM              .
23/03/2019  12:54 PM              ..
23/03/2019  12:49 PM             4,360 ec2.yaml
23/03/2019  12:54 PM             2,461 my.yaml
               2 File(s)          6,821 bytes
               2 Dir(s)  807,032,090,624 bytes free

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>aws cloudformation validate-template --template-body file://my.yaml

An error occurred (ValidationError) when calling the ValidateTemplate operation: [/Parameters/Mappings] 'null' values are not allowed in templates

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>
C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>
C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>aws cloudformation validate-template --template-body file://ec2.yaml

An error occurred (ValidationError) when calling the ValidateTemplate operation: Invalid template parameter property 'RegionMap'

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>aws cloudformation validate-template --template-body file://ec2.yaml

Step 3: Then I had declared a resource in resources section but it wasn't present in the Parameters section. So I removed it from parameters.

An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: Unresolved resource dependencies [MyVPCId] in the Resources block of the template

Step 4: Now it works like a charm.

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>
C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>
C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>
C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>aws cloudformation validate-template --template-body file://ec2.yaml
Deploy EC2 Instance with a security group
PARAMETERS              Supply your RSA Key Name        False   MyRSAKey
PARAMETERS      t2.micro                False   InstanceType

C:\Users\mirza\Desktop\Cloud\AWS\Cloud\CloudFormation\templates>

No comments: