Is there a way to tag a root volume when initializing from the cloudformation template?

amazon-ec2, amazon-web-services, aws-cloudformation

Solution

Was able to make it work through an AWS CLI interface, IAM role, and UserData initialization.

Added this to `AWS::EC2::Instance:Properties:UserData`

{ "Fn::Base64" : { "Fn::Join" : [ "\n", [
  "#!/bin/bash",
  "set -eux",
  "exec > >(tee /tmp/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1",
  { "Fn::Join" : [ "", [
    "AWS_STACK_NAME='", { "Ref" : "AWS::StackName" }, "'"
  ]]},
  { "Fn::Join" : [ "", [
    "AWS_ROOT_VOLUME_SNAPSHOT_ID='",
      { "Fn::FindInMap" :
         [ "RegionMap", { "Ref" : "AWS::Region" }, "RootVolumeSnapshotId" ]},
      "'"
  ]]},
  "AWS_INSTANCE_ID=$( curl http://169.254.169.254/latest/meta-data/instance-id )",
  "",
  "AWS_HOME=/opt/aws",
  "AWS_BIN_DIR=\"${AWS_HOME}/bin\"",
  "export EC2_HOME=\"${AWS_HOME}/apitools/ec2\"",
  "export JAVA_HOME=/etc/alternatives/jre_1.7.0",
  "",
  "ROOT_DISK_ID=$(",
  "    \"${AWS_BIN_DIR}/ec2-describe-volumes\" \\",
  "        --filter \"attachment.instance-id=${AWS_INSTANCE_ID}\" \\",
  "        --show-empty-fields \\",
  "      | grep '^VOLUME' \\",
  "      | awk '{printf \"%s,%s\\n\", $4, $2}' \\",
  "      | grep '^${AWS_ROOT_VOLUME_SNAPSHOT_ID}' \\",
  "      | cut --delimiter=, --fields=2",
  "    exit ${PIPESTATUS[0]}",
  "  )",
  "\"${AWS_BIN_DIR}/ec2-create-tags \\",
  "  \"${ROOT_DISK_ID}\" \\",
  "  --tag \"Name=${AWS_STACK_NAME}-root\"",
  ""
]]}}

Also have to add a reference to an IAM role that can describe volumes and create tags.

Added this to "Resources" section:

"InstanceProfile" :
{
  "Type" : "AWS::IAM::InstanceProfile",
  "Properties" :
  {
    "Path" : "/",
    "Roles" : [ "ec2-tag-instance" ]
  }
}

Referenced this profile in the `Instance` resource:

"Ec2Instance" :
{
  "Type" : "AWS::EC2::Instance",
  "Properties" :
  {
    ...
    "IamInstanceProfile" : {"Ref" : "InstanceProfile"},
    ...
  }
}

And in `IAM` UI create a new Role called `ec2-tag-instance`, and assign this policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ec2:CreateTags"
      ],
      "Resource": "*"
    }
  ]
}

This said, would be much nicer if `BlockDeviceMappings:Ebs` had supported `Tags` element.

Problem

I am creating an instance through the cloud formation script. The only way I found to attach an OS partition was through "BlockDeviceMappings" property. (I've tried to use "Volumes" property before, but the instance could not be mounted, the system told me that /dev/sda was already mapped and rolled back the instance creation) Here is the relevant portion of my template: ``` "Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "BlockDeviceMappings" : [{ "DeviceName" : "/dev/sda", "Ebs" : { "VolumeSize" : { "Ref" : "RootVolumeSize" }, "SnapshotId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "RootVolumeSnapshotId" ] } } }], ... } } ``` My question is, how can I tag the Ebs volume, that I am creating here with "BlockDeviceMappings" property? I did not find the obvious solution. Thanks.

Original source