AWS Lambda to list EC2 instance id using python boto3

Question:

I m trying to list out EC2 instance id using python boto3. I m new to python.

Below Code is working fine

import boto3
region = 'ap-south-1'
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    print('Into DescribeEc2Instance')
    instances = ec2.describe_instances(Filters=[{'Name': 'instance-type', 'Values': ["t2.micro", "t3.micro"]}])
    print(instances)

Output is

START RequestId: bb4e9b27-db8e-49fe-85ef-e26ae53f1308 Version: $LATEST
Into DescribeEc2Instance
{'Reservations': [{'Groups': [], 'Instances': [{'AmiLaunchIndex': 0, 'ImageId': 'ami-052c08d70def62', 'InstanceId': 'i-0a22a6209740df', 'InstanceType': 't2.micro', 'KeyName': 'testserver', 'LaunchTime': datetime.datetime(2020, 11, 12, 8, 11, 43, tzinfo=tzlocal()), 'Monitoring': {'State': 'disabled'}

Now to strip instance id from above output, I have added below code(last 2 lines) and for some reason its not working.

import boto3
region = 'ap-south-1'
instance = []
ec2 = boto3.client('ec2', region_name=region)

    def lambda_handler(event, context):
        print('Into DescribeEc2Instance')
        instances = ec2.describe_instances(Filters=[{'Name': 'instance-type', 'Values': ["t2.micro", "t3.micro"]}])
        print(instances)
        for ins_id in instances['Instances']:
                print(ins_id['InstanceId'])

Error is

{
  "errorMessage": "'Instances'",
  "errorType": "KeyError",
  "stackTrace": [
    "  File "/var/task/lambda_function.py", line 10, in lambda_handlern    for ins_id in instances['Instances']:n"
  ]
}
Asked By: 31031981

||

Answers:

The loop iteration should be

for ins_id in instances['Reservations'][0]['Instances']:

since you have a Reservation key at the top level, then an array and objects in the array with the Instances key which itself is yet another array that you then actually iterate.

Answered By: luk2302

Actually the accepted answer instances['Reservations'][0]['Instances'] may not have all instances. Instances are grouped together by security groups.Different security groups means many list elements will be there. To get every instance in that region, you need to use the code below.

Note: ['Reservations'][0]['Instances'] doesn’t list all the instances, It only gives you the instances which are grouped by the first security group. If there are many groups you won’t get all instances.

import boto3
region = 'ap-south-1'

ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    instance_ids = []
    response = ec2.describe_instances(Filters=[{'Name': 'instance-type', 'Values': ["t2.micro", "t3.micro"]}])
    instances_full_details = response['Reservations']
    for instance_detail in instances_full_details:
        group_instances = instance_detail['Instances']

        for instance in group_instances:
            instance_id = instance['InstanceId']
            instance_ids.append(instance_id)
    return instance_ids
Answered By: msvstl

I like this approach in case there are multiple reservations:

response = ec2.describe_instances()
for reservation in response['Reservations']:
    for instance in reservation['Instances']:
        print(instance['InstanceId'])
Answered By: thatguyfig

This is the simplest solution I have found to date:

ec2 = boto3.resource('ec2')
ids= [instance.id for instance in ec2.instances.all()]
Answered By: buster