0

I'm building a list of EC2 instances in Amazon. And I am testing for the existence of keys called PrivateIpAddress and PublicIpAddress in a dictionary. In some cases neither key exists and I get an exception:

-------------------------------------
Instance ID: i-86533615
Type: m4.xlarge
State: stopped
Private IP: 10.1.233.18
Traceback (most recent call last):
  File ".\aws_ec2_list_instances.py", line 43, in <module>
    print(Fore.CYAN + "{0}: {1}".format(key, instance[key]))
KeyError: 'Public IP'

My code says:

for instance in reservation["Instances"]:
if 'PrivateIpAddress' in instance and 'PublicIpAddress' in instance:
    ... do stuff...
elif 'PrivateIpAddress' in instance:
else:
    ...do stuff..

But the last else doesn't catch the problem of an instance not having either a public ip address or a private ip address.

Here is the full code in python: list ec2 instances

bluethundr
  • 1,005
  • 17
  • 68
  • 141
  • 3
    you can use reservation.get("Instances",default value here). for example `reservation.get("Instances",[])` – painor Mar 07 '19 at 17:29
  • so, just in case this was where you were stumped: you can add another elif, which checks for 'PublicIpAddress', you arent limited to just 1 elif. Having said that, this can probably be done cleaner with a `get` or `setdefault` method, as you see fit. – Paritosh Singh Mar 07 '19 at 17:34
  • Couple of ways you could handle this. You could proactively check the keys that are in the dictionary before you call them by doing something like `if 'Public IP' in instance.keys()` , or use `.get` and supply a default value, or, if you wanted to go overboard, use a `DefaultDict`: https://docs.python.org/2/library/collections.html#defaultdict-examples – n1c9 Mar 07 '19 at 17:35
  • Possible duplicate of [How to make a python dictionary that returns key for keys missing from the dictionary instead of raising KeyError?](https://stackoverflow.com/questions/6229073/how-to-make-a-python-dictionary-that-returns-key-for-keys-missing-from-the-dicti) – r.ook Mar 07 '19 at 17:36
  • Your traceback says the error is in ` print(Fore.CYAN + "{0}: {1}".format(key, instance[key]))`, but that's not included in the code that you present. – Acccumulation Mar 07 '19 at 17:43

2 Answers2

1
for instance in reservation.get("Instances", []):
    private_ip_address = instance.get("PrivateIpAddress" , None)
    public_ip_address = instance.get("PublicIpAddress" , None)
    if  private_ip_address and public_ip_address:
    ... do stuff...
    elif private_ip_address:
       ...do stuff.. 
    else:
       ...do stuff..

Try this one

paras chauhan
  • 777
  • 4
  • 13
1

I see a fundamental problem in your logic. You're looping through all the instances and building up maps for each of them in ec2info. But each time through the loop, when processing a particular instance, you're looping over all the data in ec2info, including the data added by previous iterations of the loop. I bet you don't really want to do this. I bet you really want to display the attributes for just the instance you're working on.

Here's the key to your problem:

attributes = ['Instance ID', 'Type',
    'State', 'Private IP', 'Launch Time' ]
for instance_id, instance in ec2info.items():

So here, you're iterating over all the maps in ec2info, and yet you're applying a set of 'attributes' that are specific to the one instance you're currently processing. Since in general, per your own code, not all of the maps in ec2info will have all of the same keys, you're getting the error you're getting.

CryptoFool
  • 21,719
  • 5
  • 26
  • 44