0
votes

I am trying to learn and practise AWS Cloudformation template.

While validating the template i am getting below error.

$ aws cloudformation validate-template --template-body file:///home/bhemanth/Downloads/ec2-templates/singe-instance-v2.yaml

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

CloudFormation Template Code Error:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'CentOS EC2 Instance template'
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    Default: hemanth
    AllowedValues:
    - hemanth
    - client
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  InstanceType:
    Description: CentOS
    Type: String
    Default: t2.small
    AllowedValues:
    - t2.micro
    - t2.small
    - t2.medium
    ConstraintDescription: must be a valid EC2 instance type.
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType:
        Ref: InstanceType
      SecurityGroups:
      - Ref: InstanceSecurityGroup
      KeyName:
        Ref: KeyName
      ImageId: ami-01ed306a12b7d1c96
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: EnableAll
      GroupDescription: Enable SSH access for all ports
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '0'
        ToPort: '65535'
        CidrIp:
          Ref: SSHLocation
    BlockDeviceMappings:
    - DeviceName: /dev/sda1
      Ebs:
        DeleteOnTermination: true
        Status: attached
    Hypervisor: xen
    RootDeviceName: /dev/sda1
    RootDeviceType: ebs
    Tags:
    - Key: Name
      Value: Docker
    VirtualizationType: hvm
    UserData:
      Fn::Base64: !Sub |
        #!/usr/bin/env bash
        yum install -y wget
        wget -O- https://get.docker.com/ | sh
        systemctl status docker
        systemctl start docker
        systemctl enable docker
        systemctl status docker
        systemctl status -l docker
    Volumes:
    - Attachments:
        Device: /dev/sda1
        State: attached
        DeleteOnTermination: true
      AvailabilityZone: us-west-2a
      Encrypted: false
      Size: 30
      State: in-use
      Iops: 100
      VolumeType: gp2
Outputs:
  InstanceId:
    Description: InstanceId of the newly created EC2 instance
    Value:
      Ref: EC2Instance
  AZ:
    Description: Availability Zone of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - AvailabilityZone
  PublicDNS:
    Description: Public DNSName of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - PublicDnsName
  PublicIP:
    Description: Public IP address of the newly created EC2 instance
    Value:
      Fn::GetAtt:
      - EC2Instance
      - PublicIp

I am trying to prepare aws cloudformation template which will install docker from userdata and delete the volume when instance is terminated.

Can you please advice what is wrong in my template.

If possible can you please good tips and cheats for creating aws cloudformation for beginners.

Thanks, Hemanth.

1

1 Answers

1
votes

The CloudFormation Linter catches this and more with:

E3001 Invalid resource attribute BlockDeviceMappings for resource InstanceSecurityGroup
singe-instance-v2.yaml:51:5

E3001 Invalid resource attribute Hypervisor for resource InstanceSecurityGroup
singe-instance-v2.yaml:56:5

E3001 Invalid resource attribute RootDeviceName for resource InstanceSecurityGroup
singe-instance-v2.yaml:57:5

E3001 Invalid resource attribute RootDeviceType for resource InstanceSecurityGroup
singe-instance-v2.yaml:58:5

E3001 Invalid resource attribute Tags for resource InstanceSecurityGroup
singe-instance-v2.yaml:59:5

E3001 Invalid resource attribute VirtualizationType for resource InstanceSecurityGroup
singe-instance-v2.yaml:62:5

E3001 Invalid resource attribute UserData for resource InstanceSecurityGroup
singe-instance-v2.yaml:63:5

E3001 Invalid resource attribute Volumes for resource InstanceSecurityGroup
singe-instance-v2.yaml:73:5

Property types like BlockDeviceMappings, Tags, UserData, Volumes, and AvailabilityZone should be indented a level further than Properties:

I also believe those properties should be underneath Properties: in the AWS::EC2::Instance resource, because most of them are not valid property types of AWS::EC2::SecurityGroup

I don't think Hypervisor is a valid property type of any resource type, so I'm not sure where that property type came from

I'd recommend referencing the documentation for the AWS::EC2::SecurityGroup and AWS::EC2::Instance resource types