Reputation: 1874
Here I'm writing a python program to list all the ec2 instances without the tag "Owner". Where I'm stuck right now is if the program encounters any Instance already having the "Owner" tag then it exits without checking further Instances. What I want is to skip those instances and continue to check other instances. Here is my Code:
import boto3
client = boto3.client('ec2',region_name='ap-south-1')
a = client.describe_instances()
count=0
y="Owner"
for i in a['Reservations']:
for j in i['Instances']:
for k in range(len(j['Tags'])):
if y == j['Tags'][k]['Key']:
count +=1
else:
continue
if count==0:
print "The following Instance does not have Owner Tag: "+j['InstanceId']
Here is how the json dict object would look like:
{
'Reservations': [{
'Instances': [{
.
.
.
.
'Tags':[
{
'Value': 'sample1',
'Key': 'Name'
},
{
'Value': 'user',
'Key': 'Owner'
}
]
}
}
}
Upvotes: 0
Views: 2281
Reputation: 31
having just written almost exactly this there are few areas that were over looked here. In no particular order:
Below answers the question, and covers the points above.
#Open an initial client to get a list of existing regions
client = boto3.client('ec2', region_name='us-east-1')
# Get a list of all existing regions
zones = client.describe_regions()
# Loop through all regions as anyone can launch in any region though we all
# tend to work in us-east-1
for region in zones["Regions"]:
#reset a dict used for tracking to make sure we don't carry data forward
bt_missing = {}
region_called = region["RegionName"]
# open a new client as we move through each region
ec2 = boto3.client('ec2', region_name=region_called)
# Get a list of running instances in the region
response = ec2.describe_instances()
# Loop though all instances looking for instances with No tags, Missing Billing Owner tags,
# or empty Billing Owner tags... adding the instance-id to a list
for resv in response["Reservations"]:
for inst in resv["Instances"]:
if "Tags" not in [x for x in inst]:
print(f"The instance: {inst['InstanceId']} has no tags at all, if your's please update: {region_called}")
continue
if "Billing_Owner" not in [t['Key'] for t in inst["Tags"]]:
bt_missing.update({inst["InstanceId"]: region_called})
for resv in response["Reservations"]:
for inst in resv["Instances"]:
if "Tags" not in [x for x in inst]:
continue
for tag in inst["Tags"]:
if tag['Key'] == "Billing_Owner" and not tag['Value']:
bt_missing.update({inst["InstanceId"]: region_called})
# Take the list of all instance-ids in all regions that have blank, or missing
# billing owner tags or no tags at all, and retrieve the Name tag for that instance
# and put that into a dict -- instanceid: name-region format
# reset inst to not carry data foward
inst = ""
for inst in bt_missing:
report_on = ec2.describe_tags(
Filters=[
{
'Name': 'resource-id',
'Values': [inst],
},
],
)
for tag in report_on["Tags"]:
if tag["Key"] == "Name":
instname = tag["Value"]
message = f"The instance: {inst} has no Billing Owner tag, if yours, please update: Name: {instname}, region: {bt_missing[inst]}"
print(message)
Upvotes: 0
Reputation: 52375
You are exiting the loop after finding the first tag that does not match. Get all the tag and then check. Try this:
for i in a['Reservations']:
for j in i['Instances']: # For each instance
keys = [tag['Key'].upper() for tag in j['Tags']] # Collect all tags
if 'OWNER' not in keys: # Case insensitive check of Owner tag
print "The following Instance does not have Owner Tag: "+j['InstanceId']
Upvotes: 1
Reputation: 269101
Your continue
is causing a few problems.
Here's an alternate version:
import boto3
key_to_find = 'Owner'
client = boto3.client('ec2')
response = client.describe_instances()
for reservation in response['Reservations']:
for instance in reservation['Instances']:
if key_to_find not in [tag['Key'] for tag in instance['Tags']]:
print (key_to_find + ' tag not found for Instance ' + instance['InstanceId'])
Upvotes: 1
Reputation: 2639
I noticed a couple of things in your code that if you did them slightly different maybe it would be easier to control the program's flow. For starters, use more descriptive variable names, if you have a list of instances for example, a good name would simply be instances
. Here is an example of how you could do this:
import boto3
client = boto3.client('ec2',region_name='ap-south-1')
data = client.describe_instances()
count=0
reservations = data["Reservations"]
for reservation in reservations:
instances = reservation["Instances"]
for instance in instances:
tags = instance["Tags"]
instanceId = instance['InstanceId']
hasOwner = len([tag for tag in tags if tag["Key"] == "Owner"]) > 0
print "The following Instance does not have Owner Tag: " + instanceId
Notice how I also added some spacing to increase readability.
Lastly, if you have a string, namely "Owner"
, it would be silly to put thin into a variable called owner
, since that would only be confusing if it were ever changed.
Upvotes: 1