Friday, February 4, 2022

[SOLVED] Boto3 returns only one instance id after running ec2

Issue

Following code runs instances as per given requirement e.g 3, but it create tags, add loadbalancer target group to only one instance also return only one instance ID, and skips the remaining two instances.

I don't understand why, can you help me?

import boto3
import json
import botocore
import os
import sys
from collections import defaultdict

AMI = 'ami-047a51fa27710816e'
INSTANCE_TYPE = 't2.micro'
KEY_NAME = 'mikey'
REGION = 'us-east-1'


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

def lambda_handler(event, context):

    instance = client.run_instances(
        ImageId=AMI,
        InstanceType=INSTANCE_TYPE,
        KeyName=KEY_NAME,
        MaxCount=3,
        MinCount=3
    )
    
    print ("New instance created:", instance)
    instance_id = instance['Instances'][0]['InstanceId']
    waiter = client.get_waiter('instance_running')
    waiter.wait(InstanceIds=[instance_id],
    WaiterConfig={
        'Delay': 15
    })
    print (instance_id)
    
    response_tags = client.create_tags(
    Resources=[
        instance_id,
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'test'
        },
    ]
    )
    print ("Tags added")
    clients=boto3.client('elbv2')

    response_tg = clients.register_targets(
        TargetGroupArn='arn:aws:elasticloadbalancing:us-east-1:123456789123:targetgroup/target-demo/c64e6bfc00b4658f',
        Targets=[
           {
            'Id': instance_id
           },
        ]
   )
    return ('Instance created', instance_id)

Solution

The run_instances call will actually return all instance ids, you're just only processing one of them.

This is where you explicitly only extract a single instance id.

instance_id = instance['Instances'][0]['InstanceId']

What you should do is process all of them with something like this:

instance = client.run_instances() # Your full call here
instance_ids = [item['InstanceId'] for item in instance['Instances']]

waiter = client.get_waiter('instance_running')
waiter.wait(InstanceIds=instance_ids)

#... now all your instances are running
response_tags = client.create_tags(
    Resources=instance_ids,
    Tags=[{"Key": "Name", "Value": "Test"}]
)

elb_client = boto3.client("elbv2")

response_tg = elb_client.register_targets(
    TargetGroupArn="arn...",
    Targets=[{"Id": instance_id} for instance_id in instance_ids]
)

The variable instance_ids is now a list with the three instance ids and you'll have to update the register_targets and create_tags calls as well to reflect this.



Answered By - Maurice
Answer Checked By - Cary Denson (WPSolving Admin)