Boto EC2: Create an instance with tags

This method has worked for me:

rsvn = image.run(
  ... standard options ...
)

sleep(1)

for instance in rsvn.instances:
   instance.add_tag('<tag name>', <tag value>)

Using boto 2.9.6, I'm able to add tags to an instance immediately after getting my response back from run_instances. Something like this works without sleep:

reservation = my_connection.run_instances(...)
for instance in reservation.instances:
    instance.add_tag('Name', <whatever>)

I verified that the instance was still in pending state after successfully adding the tag. It would be easy to wrap this logic in a function similar to that requested by the original post.


You can tag instance or volume on creation

From run_instances docs:

You can tag instances and EBS volumes during launch, after launch, or both. For more information, see CreateTags and Tagging Your Amazon EC2 Resources.

Using Tags AWS doc includes a table with resources supporting tagging and supporting tagging on creation (Instance and EBS Volume support both as of 01-MAY-2017)

Here is a code snippet to tag instance at creation time in Python (other SDK references are listed on this page):

from pkg_resources import parse_version
import boto3
assert parse_version(boto3.__version__) >= parse_version('1.4.4'), \
    "Older version of boto3 installed {} which doesn't support instance tagging on creation. Update with command 'pip install -U boto3>=1.4.4'".format(boto3.__version__)
import botocore
assert parse_version(botocore.__version__) >= parse_version('1.5.63'), \
   "Older version of botocore installed {} which doesn't support instance tagging on creation. Update with command 'pip install -U botocore>=1.5.63'".format(botocore.__version__)
ec2 = boto3.resource('ec2')
tag_purpose_test = {"Key": "Purpose", "Value": "Test"}
instance = ec2.create_instances(
    ImageId=EC2_IMAGE_ID,
    MinCount=1,
    MaxCount=1,
    InstanceType=EC2_INSTANCE_TYPE,
    KeyName=EC2_KEY_NAME,
    SecurityGroupIds=[EC2_DEFAULT_SEC_GROUP],
    SubnetId=EC2_SUBNET_ID,
    TagSpecifications=[{'ResourceType': 'instance',
                        'Tags': [tag_purpose_test]}])[0]

I used

Python 2.7.13
boto3 (1.4.4)
botocore (1.5.63)

This answer was accurate at the time it was written but is now out of date. The AWS API's and Libraries (such as boto3) can now take a "TagSpecification" parameter that allows you to specify tags when running the "create_instances" call.


Tags cannot be made until the instance has been created. Even though the function is called create_instance, what it's really doing is reserving and instance. Then that instance may or may not be launched. (Usually it is, but sometimes...)

So, you cannot add a tag until it's been launched. And there's no way to tell if it's been launched without polling for it. Like so:

reservation = conn.run_instances( ... )

# NOTE: this isn't ideal, and assumes you're reserving one instance. Use a for loop, ideally.
instance = reservation.instances[0]

# Check up on its status every so often
status = instance.update()
while status == 'pending':
    time.sleep(10)
    status = instance.update()

if status == 'running':
    instance.add_tag("Name","{{INSERT NAME}}")
else:
    print('Instance status: ' + status)
    return None

# Now that the status is running, it's not yet launched. The only way to tell if it's fully up is to try to SSH in.
if status == "running":
    retry = True
    while retry:
        try:
            # SSH into the box here. I personally use fabric
            retry = False
        except:
            time.sleep(10)

# If we've reached this point, the instance is up and running, and we can SSH and do as we will with it. Or, there never was an instance to begin with.