Posts: 33
Threads: 17
Joined: Feb 2019
I am trying to get a list of AWS instances using Boto3.
The user enters the instance IDs, then the script should print out info about the instance. Then it should terminate the instance.
But I am getting this error: Error: python3 .\aws_ec2_terminate_instances.py
Enter an instance ID separated by commas: i-07c21656a79b8eb45
Deleting Instance IDs:
i-07c21656a79b8eb45
Traceback (most recent call last):
File ".\aws_ec2_terminate_instances.py", line 15, in <module>
instance['Tags'][{'Key': 'Name', 'Value': instance_id}]
TypeError: list indices must be integers or slices, not dict
Here is the current state of my code:
import sys
import boto3
import collections
from collections import defaultdict
ec2 = boto3.client('ec2')
instance_id_list = input("Enter an instance ID separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
print(instance_id)
instance = ec2.describe_instances(
InstanceIds=[instance_id]
) ['Reservations'][0]['Instances'][0]
instance['Tags'][{'Key': 'Name', 'Value': instance_id}]
ec2info = defaultdict()
for tag in instance.tags:
if 'Name'in tag['Key']:
print(tag['Key'])
name = tag['Value']
# Add instance info to a dictionary
print(instance.get('Instances'))
ec2info[instance.id] = {
'Instance ID': instance.id,
'Type': instance.instance_type,
'State': instance.state['Name'],
'Private IP': instance.private_ip_address,
'Public IP': instance.public_ip_address,
'Launch Time': instance.launch_time
}
attributes = ['Instance ID', 'Type',
'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
for key in attributes:
print("{0}: {1}".format(key, instance[key]))
print(instance.terminate())
print("------")
ec2.instances.filter(InstanceIds=instance).stop()
ec2.instances.filter(InstanceIds=instance).terminate() How can I solve this error?
Posts: 3,458
Threads: 101
Joined: Sep 2016
instance['Tags'] is a list. Index a list using index values (integers). You're getting an error because, instead of an index, you're trying to use a dict: {'Key': 'Name', 'Value': instance_id} .
I'd suggest looking at the return value, because it appears that it isn't what you think it is.
Posts: 33
Threads: 17
Joined: Feb 2019
(Feb-27-2019, 10:26 PM)nilamo Wrote: instance['Tags'] is a list. Index a list using index values (integers). You're getting an error because, instead of an index, you're trying to use a dict: {'Key': 'Name', 'Value': instance_id} .
I'd suggest looking at the return value, because it appears that it isn't what you think it is.
I tried printing out the value of instance in the code, and I got back info about the instance in json format. How do I traverse the json to get at the Name tag?
Quote:{'AmiLaunchIndex': 0, 'ImageId': 'ami-035be7bafff33b6b6', 'InstanceId': 'i-0e3dfaeaa89c7e401', 'InstanceType': 't2.micro', 'KeyName': 'agility-company-nonprod', 'LaunchTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'Monitoring': {'State': 'disabled'}, 'Placement': {'AvailabilityZone': 'us-east-1c', 'GroupName': '', 'Tenancy': 'default'}, 'PrivateDnsName': 'ip-10-48-129-108.us.kworld.kpmg.com', 'PrivateIpAddress': '10.48.129.108', 'ProductCodes': [], 'PublicDnsName': '', 'State': {'Code': 16, 'Name': 'running'}, 'StateTransitionReason': '', 'SubnetId': 'subnet-9fca57e9', 'VpcId': 'vpc-d4ad21b0', 'Architecture': 'x86_64', 'BlockDeviceMappings': [{'DeviceName': '/dev/xvda', 'Ebs': {'AttachTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'DeleteOnTermination': True, 'Status': 'attached', 'VolumeId': 'vol-0943014108b20137a'}}], 'ClientToken': '', 'EbsOptimized': False, 'EnaSupport': True, 'Hypervisor': 'xen', 'NetworkInterfaces': [{'Attachment': {'AttachTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'AttachmentId': 'eni-attach-054a1daee0609f80e', 'DeleteOnTermination': True, 'DeviceIndex': 0, 'Status': 'attached'}, 'Description': 'Primary network interface', 'Groups': [{'GroupName': 'launch-wizard-29', 'GroupId': 'sg-0ec43fd09c1a4b5fa'}], 'Ipv6Addresses': [], 'MacAddress': '0a:dd:5b:27:5f:70', 'NetworkInterfaceId': 'eni-00904468cbeb24c28', 'OwnerId': '832839043616', 'PrivateIpAddress': '10.48.129.108', 'PrivateIpAddresses': [{'Primary': True, 'PrivateIpAddress': '10.48.129.108'}], 'SourceDestCheck': True, 'Status': 'in-use', 'SubnetId': 'subnet-9fca57e9', 'VpcId': 'vpc-d4ad21b0'}], 'RootDeviceName': '/dev/xvda', 'RootDeviceType': 'ebs', 'SecurityGroups': [{'GroupName': 'launch-wizard-29', 'GroupId': 'sg-0ec43fd09c1a4b5fa'}], 'SourceDestCheck': True, 'Tags': [{'Key': 'Creator', 'Value': 'tdunphy'}, {'Key': 'Name', 'Value': 'test'}, {'Key': 'PrincipalId', 'Value': 'AIDAIZC35XEFCDGBM47UK'}], 'VirtualizationType': 'hvm', 'CpuOptions': {'CoreCount': 1, 'ThreadsPerCore': 1}, 'CapacityReservationSpecification': {'CapacityReservationPreference': 'open'}, 'HibernationOptions': {'Configured': False}}
In the above json the Name tag is almost at the end: {'Key': 'Name', 'Value': 'test'}
Posts: 3,458
Threads: 101
Joined: Sep 2016
Feb-27-2019, 10:52 PM
(This post was last modified: Feb-27-2019, 10:52 PM by nilamo.)
It looks like you already do, two lines later.
But since you don't know what index you need, you'd iterate over the list. Something like: tags = instance['Tags']
name = ""
for tag in tags:
if tag["Key"] == "Name":
name = tag["Value"]
print(name) But since you aren't using it's name for anything, you can probably just delete the line instead of fixing it.
Posts: 33
Threads: 17
Joined: Feb 2019
Feb-28-2019, 06:36 PM
(This post was last modified: Feb-28-2019, 06:40 PM by bluethundr.)
(Feb-27-2019, 10:52 PM)nilamo Wrote: It looks like you already do, two lines later.
But since you don't know what index you need, you'd iterate over the list. Something like:tags = instance['Tags']
name = ""
for tag in tags:
if tag["Key"] == "Name":
name = tag["Value"]
print(name) But since you aren't using it's name for anything, you can probably just delete the line instead of fixing it.
Ok thanks! That works and I am now able to access the 'Name' tag from the code, and print it out.
I'm getting a new error now when I try to access info about the instance ID from a dictionary. This is how my script outputs now:
Error: Enter instance IDs separated by commas: i-076361b30ee404bb4
Deleting Instance IDs:
i-076361b30ee404bb4
Name: test1
Traceback (most recent call last):
File ".\aws_ec2_terminate_instances.py", line 24, in <module>
'Instance ID': instance.id,
AttributeError: 'dict' object has no attribute 'id'
This is my current script:
import boto3
import collections
from collections import defaultdict
ec2 = boto3.client('ec2')
instance_id_list = input("Enter instance IDs separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
print(instance_id)
instance = ec2.describe_instances(
InstanceIds=[instance_id]
)['Reservations'][0]['Instances'][0]
tags = instance['Tags']
name = ""
for tag in tags:
if tag["Key"] == "Name":
name = tag["Value"]
print("Name: ", name)
# Add instance info to a dictionary
ec2info = defaultdict()
ec2info[instance.id] = {
'Name': name,
'Instance ID': instance.id,
'Type': instance.instance_type,
'State': instance.state['Name'],
'Private IP': instance.private_ip_address,
'Public IP': instance.public_ip_address,
'Launch Time': instance.launch_time
}
attributes = ['Name', 'Instance ID', 'Type',
'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
for key in attributes:
print("{0}: {1}".format(key, instance[key]))
print("------")
print("Terminating the instance:")
ec2.instances.filter(InstanceIds=instance).stop()
ec2.instances.filter(InstanceIds=instance).terminate() I'd appreciate some help on that error!
Posts: 33
Threads: 17
Joined: Feb 2019
Hi all,
I have a script that I wrote that asks a user to enter a list of instance IDs from AWS. The script then prints out info on that server, and terminates it.
When I run the script I get this error:
Error: Traceback (most recent call last):
File ".\aws_ec2_terminate_instances.py", line 23, in <module>
'Instance ID': instance.id,
AttributeError: 'dict' object has no attribute 'id'
This is my code:
import boto3
import collections
from collections import defaultdict
ec2 = boto3.client('ec2')
instance_id_list = input("Enter instance IDs separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
print(instance_id)
instance = ec2.describe_instances(
InstanceIds=[instance_id]
)['Reservations'][0]['Instances'][0]
tags = instance['Tags']
name = ""
for tag in tags:
if tag["Key"] == "Name":
name = tag["Value"]
# Add instance info to a dictionary
ec2info = defaultdict()
ec2info[instance.id] = {
'Name': name,
'Instance ID': instance.id,
'Type': instance.instance_type,
'State': instance.state['Name'],
'Private IP': instance.private_ip_address,
'Public IP': instance.public_ip_address,
'Launch Time': instance.launch_time
}
attributes = ['Name', 'Instance ID', 'Type',
'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
for key in attributes:
print("{0}: {1}".format(key, instance[key]))
print("------")
print("Terminating the instance:")
ec2.instances.filter(InstanceIds=instance).stop()
ec2.instances.filter(InstanceIds=instance).terminate() I seem to be getting a dictionary error when I print out the instance.id.
This script is based on another script that pulls a list of all AWS instances in an account, and prints out their info. That one works!
from collections import defaultdict
import boto3
"""
A tool for retrieving basic information from the running EC2 instances.
"""
# Connect to EC2
ec2 = boto3.resource('ec2')
# Get information for all running instances
running_instances = ec2.instances.filter(Filters=[{
'Name': 'instance-state-name',
'Values': ['running']}])
ec2info = defaultdict()
for instance in running_instances:
for tag in instance.tags:
if 'Name'in tag['Key']:
print(tag['Key'])
name = tag['Value']
# Add instance info to a dictionary
ec2info[instance.id] = {
'Name': name,
'Instance ID': instance.id,
'Type': instance.instance_type,
'State': instance.state['Name'],
'Private IP': instance.private_ip_address,
'Public IP': instance.public_ip_address,
'Launch Time': instance.launch_time
}
attributes = ['Name', 'Instance ID', 'Type', 'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
for key in attributes:
print("{0}: {1}".format(key, instance[key]))
print("------") Here is a sample of the output from the working script above:
Name: test1
Instance ID: i-076361b30ee404bb4
Type: t2.micro
State: running
Private IP: 10.48.129.89
Public IP: None
Launch Time: 2019-02-27 22:45:56+00:00
------
Name: USAWSCDLX00061
Instance ID: i-0463897140af217f8
Type: m4.large
State: running
Private IP: 10.48.136.41
Public IP: None
Launch Time: 2017-12-20 14:26:30+00:00 What I'm unclear on is why I can print the instance.id from the dictionary in the second program, and it gives the error: 'dict' object has no attribute 'id' on the first script I show.
How can I solve this error?
Posts: 3,458
Threads: 101
Joined: Sep 2016
Feb-28-2019, 08:14 PM
(This post was last modified: Feb-28-2019, 08:14 PM by nilamo.)
When in doubt, print() it out!
What's an instance ?
Also, there's no reason to double post. This place isn't that big lol.
Posts: 33
Threads: 17
Joined: Feb 2019
(Feb-28-2019, 08:14 PM)nilamo Wrote: When in doubt, print() it out! What's an instance ? Also, there's no reason to double post. This place isn't that big lol.
Haha! Ok man. Sorry about that. I've actually made some progress since I posted this.
This is the value of the instance variable: AWS EC2 JSON
It's your typical aws json output that you might be familiar with.
If I format the dictionary like this:
ec2info = defaultdict()
ec2info[instance['InstanceId']] = {
'Name': name,
'Instance ID': instance['InstanceId'],
'Type': instance['InstanceType'],
'State': instance['State'],
'Private IP': instance['PrivateIpAddress'],
'Launch Time': instance['LaunchTime']
} I can run my print statements:
attributes = ['Name', 'Instance ID', 'Type',
'State', 'Private IP', 'Launch Time']
print("------")
for instance_id, instance in ec2info.items():
for key in attributes:
print("{0}: {1}".format(key, instance[key]))
print("------") And it works!
------
Name: USAWSCDLX00061
Instance ID: i-0463897140af217f8
Type: m4.large
State: {'Code': 16, 'Name': 'running'}
Private IP: 10.48.136.41
Launch Time: 2017-12-20 14:26:30+00:00
------ I have a couple of questions tho, I was hoping you could help me with.
For the list instance script that I created: aws_ec2_list_instance_info.py
why am I able to format the dictionary like this, and have it print out the information:
ec2info[instance.id] = {
'Name': name,
'Instance ID': instance.id,
'Type': instance.instance_type,
'State': instance.state['Name'],
'Private IP': instance.private_ip_address,
'Public IP': instance.public_ip_address,
'Launch Time': instance.launch_time
} But in my terminate script ( aws_ec2_terminate_instances.py, I have to access the dictionary info like this:
ec2info = defaultdict()
ec2info[instance['InstanceId']] = {
'Name': name,
'Instance ID': instance['InstanceId'],
'Type': instance['InstanceType'],
'State': instance['State'],
'Private IP': instance['PrivateIpAddress'],
'Launch Time': instance['LaunchTime']
} I'd appreciate it if you could explain the difference!
Also all my attempts to access the state information failed.
If I access it as 'State': instance['State'], I get 'State': {'Code': 16, 'Name': 'running'}
But if I try to access it as: 'State': instance['State.Name'],
I get this error: KeyError: 'State.Name'
I just want to get at the running state. If you could help with that too, I would appreciate it!
Posts: 3,458
Threads: 101
Joined: Sep 2016
Those scripts have different values for what's called instance . In one, it's whatever's returned by describe_instances() instance = ec2.describe_instances(
InstanceIds=[instance_id]
)['Reservations'][0]['Instances'][0] ...but the other one looks like some sort of custom object: running_instances = ec2.instances.filter(Filters=[{
'Name': 'instance-state-name',
'Values': ['running']}]) The describe_instances() probably returns a dict of key-value strings, while the other one probably has extra functionality. You have to get info about them differently, because they're different things (only one is a dict).
|