Using Python and Boto3 to get Instance Tag information

Here are 2 sample functions to illustrate how you can get information about Tags on instances using Boto3 in AWS.

import boto3

def get_instance_name(fid):
    # When given an instance ID as str e.g. 'i-1234567', return the instance 'Name' from the name tag.
    ec2 = boto3.resource('ec2')
    ec2instance = ec2.Instance(fid)
    instancename = ''
    for tags in ec2instance.tags:
        if tags["Key"] == 'Name':
            instancename = tags["Value"]
    return instancename

In this function, I create the ec2 resource object using the instance ID passed to the function. I iterate through the Tags of the instance until I find the ‘Name’ Tag and return its value. This is a very simple function that can pull any tag value, really.

Next up, this function will list all instances with a certain Tag name and certain Value on that tag.

import boto3

def list_instances_by_tag_value(tagkey, tagvalue):
    # When passed a tag key, tag value this will return a list of InstanceIds that were found.

    ec2client = boto3.client('ec2')

    response = ec2client.describe_instances(
        Filters=[
            {
                'Name': 'tag:'+tagkey,
                'Values': [tagvalue]
            }
        ]
    )
    instancelist = []
    for reservation in (response["Reservations"]):
        for instance in reservation["Instances"]:
            instancelist.append(instance["InstanceId"])
    return instancelist

Here I use ‘response’ to collect the instances which fall into the Filter used. Take note that I used the tag: + tagkey. tag-value would return any instance that this value on any tag. Tag-key returns any instance with the tag name field that matches here, regardless of the value. I want a specific tag and specific value.

Tagged , , , . Bookmark the permalink.

16 Responses to Using Python and Boto3 to get Instance Tag information

  1. Ryan says:

    I have tried the first solution above while passing the instance id from a cloudevent . It does not return anything. Any ideas, have things changed since you posted this?

    • mike says:

      By “not return anything” are you getting a timeout, python/boto error, does it just sit there and you have to ctrl+c it to break the process? Are you handling the ‘cloudevent’ through lambda?

      If you want some direction, I’d need more specifics on the error and how you are running the function.

      • ryan says:

        I get a successful response but no information.
        Running it like this
        def get_instance_name(thisInstanceID):
        ec2 = boto3.resource(‘ec2’)
        ec2instance = ec2.Instance(thisInstanceID)
        instancename = ”
        for tags in ec2instance.tags:
        if tags[“Key”] == ‘Name’:
        instancename = tags[“Value”]
        print(instancename)

  2. Deon Fleek says:

    Yeah, it’s broken.

    In [47]: get_instance_name(‘i-12345678’)
    Out[47]: ”

    • mike says:

      I just ran it to check, and the code works. Now, the instance has to have a Name, by default, they do not. If you query an instance ID that does not have a ‘Name’ tag set, it will return ”.

  3. Chris Gerber says:

    You should be using paginators. Your solution works until you have more resources than are returned in a single response.

    def list_instances_by_tag_value(tagkey, tagvalue):
    # When passed a tag key, tag value this will return a list of InstanceIds that were found.

    ec2client = boto3.client(‘ec2’)

    instances = ec2client.get_paginator(‘describe_instances’)

    response = instances.paginate(
    Filters=[
    {
    ‘Name’: ‘tag:’+tagkey,
    ‘Values’: [tagvalue]
    }
    ]
    )
    instancelist = []
    for reservation in response.get(“Reservations”):
    for instance in reservation.get(“Instances”):
    instancelist.append(instance.get(“InstanceId”))
    return instancelist

    • mike says:

      Yes, this would be correct if there are more then 1000 possible items returned, IIRC. I frequently use paginators for s3 stuff where thousands of objects can be returned as a response. And paginators should be used if you expect more then 1000 instances to be returned in your response.

  4. Noa says:

    I tried to write this solution of getting the instance name, and it writes to me “you must specify a region”.
    what should I do?

    • mike says:

      When you define the boto3 resource, include region_name=’us-east-1′ (or whichever region).
      ec2 = boto3.resource(‘ec2′,region_name=’us-east-1’)

  5. Noa says:

    thanks!
    now it writes me different error when i go to the ec2instance.tags:
    botocore.exceptions.NoCredentialsError: Unable to locate credentials

    • mike says:

      Right, you need to do one of these. Run the script on a host inside AWS with a host role with perms, you need to run the AWS cli config for user on the host and give it the key/secret key, or you can provide the id and key in the script.

      Like this:
      boto3.setup_default_session(aws_access_key_id=’xxxxxxxxxxxxx’,
      aws_secret_access_key=’xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’,
      region_name=’us-east-1′

  6. david says:

    just need to add this lines after the function (to call it and to print the result)

    instancename = get_instance_name(‘i-xxxxxxxxxxxxxxxx’)
    print(instancename)

  7. arup says:

    Hi Mike, I am looking for a code where while creating an AMI from an Instance, that AMI & its associated snapshots should receive all the tags which are there with the Instance from where we are creating the AMI

    • mike says:

      The boto3 create_image() from the client does not have an option for copying tags. So your best best is to describe the ec2 instance first, copy the tag list off the response. Then once the AMI is created, add tags to the ami using an ami-resource.create_tags() action. That’s what I would do.

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve : *
25 + 7 =