1
votes

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
" does not work" - what does not work exactly? What are error messages?Marcin
Your code attempts to add the test_key even if it already exists. Also, it doesn't seem to add a Name tag if that's absent.jarmod
Does not work in that if an instance is created with no 'Name' tag, it does not add tags to the instance or the volume. It's errors out with: { "errorMessage": "'Tags'", "errorType": "KeyError", "stackTrace": [ " File \"/var/task/lambda_function.py\", line 38, in lambda_handler\n for tag in instance['Tags']:\n" ] }cdh12

1 Answers

1
votes

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']