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.
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?
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.
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)
Go to the forums and create a post there with the code and error. I’ll try it out and see what I get.
I just ran it and it worked. Now the EC2s must have a Name tag for this to work. EC2s don’t have this by default.
Yeah, it’s broken.
In [47]: get_instance_name(‘i-12345678’)
Out[47]: ”
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 ”.
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
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.
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?
When you define the boto3 resource, include region_name=’us-east-1′ (or whichever region).
ec2 = boto3.resource(‘ec2′,region_name=’us-east-1’)
thanks!
now it writes me different error when i go to the ec2instance.tags:
botocore.exceptions.NoCredentialsError: Unable to locate credentials
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′
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)
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
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.
Hi,
Almost 4 years and still works like a Charm. Thanks.
Is it possible to get all the Tags in one go and then assign them to variables.
Using the ec2 client describe_tags() function or a ec2 instance resource’s tags method, You would get all tags returned for a resource in a python list. Pretty much any function describing tags returns a list of dicts. It’s up to you to iterate over the list and do what you want with it.
Nope doesn’t work, get syntax error
def list_instances_by_tag_value(CostCenter,333-000-000-333-333-3333-3333) even putting the number in quotes or change the name and value to something simple does not return anything. Empty response. Python is such a horrible language.
import boto3
#s3 = boto3.resource(‘s3’)
# for bucket in s3.buckets.all():
# print(bucket.name)
ec2 =boto3.resource(‘ec2’).instances.all()
ec2_client = boto3.client(‘ec2’)
response = ec2_client.describe_instances()
for i in ec2:
print(i.tags[0][‘Value’])
#tag = boto3.resource(‘ec2’)
#for e in ec2:
# print(e.id)
# individual = boto3.resource(‘ec2’).Instance(e.id)
# print(individual)