Lambda function to search for all running EC2 instances, add tag 'Name' if not present, and then add tags to it's associated volumes?

Viewed 1354

I have some code that works to add tags to all pending and running instances, and then searches for their associated volumes, and adds tags to those as well. However, if I spin up a new instance with NO tags at all, I get a KeyError and it does not work. What I'm looking to do is:

  1. Search for all running and pending EC2's
  2. If 'Name' tag does not exist on the instance, add a key: 'Name' tag as well as key: 'test_key', value: 'test_value'.
  3. If key: 'Name' tag does exist, just add the key: 'test_key' , value: 'test_value' to EC2's
  4. Add tags to all volumes associated with running/pending instances

Here is the code:

#!/usr/bin/env python

import boto3


ec2 = boto3.resource('ec2')
ec2client = boto3.client('ec2')


#-----Define Lambda function-----#
def lambda_handler(event, context):

#-----Check& filter Instances which  Instance State is running-----#
    instances = ec2client.describe_instances(
        Filters=[{
            'Name': 'instance-state-name',
            'Values': ['pending', 'running']
        }]
        )

#-----Define dictionary to store Tag Key & value------#
    dict={}

    mytags = [{
        "Key" : "test_key", "Value" : "test_value"
        }]

#-----Store Key & Value of Instance ------#
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            ec2.create_tags(
                Resources = [instance["InstanceId"] ],
                Tags = mytags)
            for tag in instance['Tags']:
                if tag['Key'] == 'Name':
                    print ( instance['InstanceId'],tag['Value'])
                    #ids.append(( instance['InstanceId'],tag['Value']))
                    dict[instance['InstanceId']]= tag['Value']
                
#-----Store Key & Value with attached instance ID of all volumes ------#     
    volumes = ec2.volumes.all() 
    for volume in volumes:

#-----compare dictionary value Key:InstanceID and volume attached Key:InstanceID ------#     
        for a in volume.attachments:
            for key, value in dict.items():


#-----Add tags to volumes ------#     

                if a['InstanceId'] == key:
                     volume.create_tags(Tags =[{
                        'Key': 'test_key', 'Value': 'test_value'}
                    ])

It works fine if there is a 'Name' tag on the new instance, but does not work if the 'Name' tag isn't there. It throws the following error:

{ "errorMessage": "'Tags'", "errorType": "KeyError", "stackTrace": [ " File "/var/task/lambda_function.py", line 38, in lambda_handler\n for tag in instance['Tags']:\n" ] }

I think this is because it's searching for a tag but the new instance has no tags so it errors.

1 Answers

If an instance has no tags, there won't be any Tags field. So you have to check for this:

    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            ec2.create_tags(
                Resources = [instance["InstanceId"] ],
                Tags = mytags)
            if 'Tags' in instance:
              for tag in instance['Tags']:
                  if tag['Key'] == 'Name':
                      print ( instance['InstanceId'],tag['Value'])
                      #ids.append(( instance['InstanceId'],tag['Value']))
                      dict[instance['InstanceId']]= tag['Value']       
Related