Lambda Function timeout error

0

Hi AWS, I am writing a lambda function where it will list all the S3 buckets, list the tag with keyword cost in the key and fix it if there is a typo or semantics mistake, for e.g. cost_centre, cost_Centre, cost_centre & cost_Center to cost_centre. I have written this code for the same.

import json
import boto3
from botocore.exceptions import ClientError

def lambda_handler(event, context):
    client = boto3.client(service_name='s3')
    response = client.list_buckets()

    # list s3 buckets and the tags associated with the bucket
    for bucket in response['Buckets']:
        try:
            result = client.get_bucket_tagging(
                Bucket=bucket['Name']
                )
            value = result['TagSet']
            for tags in value:
                if 'cost' in tags['Key']:
                    print(f"The bucket name is: {bucket['Name']} and the tags are: {tags['Key']}:{tags['Value']}")
        except ClientError as e:
            if e.response['Error']['Code'] == 'TagSetNotFoundError':
                print("TagSet Not Found Error" + e)
            else:
                print(f"The bucket name is: {bucket['Name']} has no tags")

    # replace wrong tag with the right tag key
    for bucket in response['Buckets']:
        if tags['Key'] in ('cost_center', 'costcenter', 'costcentre', 'cost_Center', 'cost_Centre'):
            update_tag = client.put_bucket_tagging(
                Bucket=bucket['Name'],
                Tagging={
                    'TagSet': [
                        {
                            'Key': 'cost_centre',
                            'Value': tags['Value']
                        }
                    ]
                }
            )

We have more than 50 buckets in a given AWS account but instead of evaluating the results within the default time (15 mins) it is giving timeout. Can you help where I need to refactor my code?

NOTE: Each bucket has 5-6 tags like primary_owner, secondardy_owner etc. but I am only interested in checking cost_centre

Thanks

profile picture
Arjun
asked a year ago257 views
4 Answers
1

Hi, your code doesn't have dependencies on the input vars of the lambda handler. So, I would suggest that slightly refactor it to isolate a function looping across your list of buckets. Then, you test this function from your laptop to make sure it works as expected.

When you reach this stage, you can start looking at the Lambda config. You most probably have an issue with the Lambda execution role: see https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html

You need to make sure that the role has the proper credentials to list s3 buckets. See https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html for all possible permissions

profile pictureAWS
EXPERT
answered a year ago
0
Accepted Answer

Final working code:

import boto3
from botocore.exceptions import ClientError

# Tag with incorrect semantics/name
incorrect_tag = ['cost_center', 'cost_Center', 'cost_Centre', 'costcentre', 'costcenter', 'costCentre', 'costCenter', 'CostCenter', 'CostCentre', 'Cost_centre', 'Cost_center']

def lambda_handler(event, context):
    client = boto3.client(service_name='s3')
    response = client.list_buckets()

    # list s3 buckets and the tags associated with the bucket
    for bucket in response['Buckets']:
        try:
            result = client.get_bucket_tagging(
                Bucket=bucket['Name']
                )
            values = result['TagSet']
            for tags in values:
                if tags['Key'] in incorrect_tag:
                    tags['Key'] = 'cost_centre'
            print(values)
            
            # applying the tags to s3 bucket
            s3_add_tag = client.put_bucket_tagging(
                Bucket=bucket['Name'],
                Tagging={
                    'TagSet': values
                }
            )
            print(f"{bucket['Name']} has right tags {tags['Key']}:{tags['Value']}")
                
            print("success")
        except ClientError as e:
            if e.response['Error']['Code'] == 'TagSetNotFoundError':
                print("TagSet Not Found Error" + e)
            else:
                print(f"The bucket name is: {bucket['Name']} has no tags")
profile picture
Arjun
answered 10 months ago
0

Is your Lambda function attached to a VPC? If it is, you either need to create an S3 VPC endpoint, or better yet, remove it from the VPC, as it doesn't access any VPC resources.

If this is not the case, are you seeing any printouts in CloudWatch Logs? How long does it take to timeout?

profile pictureAWS
EXPERT
Uri
answered a year ago
  • Hi @Uri, the lambda function is in the VPC as it is mandatory in this situation to keep the function within the VPC. Having said that I am able to see a few buckets with tags attached to them but in case if I have more than 50 buckets it is only fetching the information for 2 or 3 maximum. It took default 15 mins and after that it throws the timeout error.

  • Why do you need it in the VPC? You should attach functions to the VPC only if it needs to access resources which are in the VPC itself.

0

The above configurations as suggested by @Uri and @Didier_AWS were there in place. The issue was because of the proxy.

For Linux or Mac:

$ export HTTP_PROXY=http://<YOUR PROXY IP>:<PORT> $ export HTTPS_PROXY=http://<YOUR PROXY IP>:<PORT>

For Windows:

set HTTP_PROXY=http://<YOUR PROXY IP>:<PORT> set HTTPS_PROXY=http://<YOUR PROXY IP>:<PORT>

But now I am facing a new issue. There is an issue in this piece of code as though it is updating the semantics and grammar of cost centre tag with the right semantics but it is removing other tags attached to the function and also adding the tag to the bucket which has no tags and also overriding the value of cost centre with the same value for every s3 bucket in the account.

# replace wrong tag with the right tag key
    for bucket in response['Buckets']:
        if tags['Key'] in ('cost_center', 'costcenter', 'costcentre', 'cost_Center', 'cost_Centre'):
            update_tag = client.put_bucket_tagging(
                Bucket=bucket['Name'],
                Tagging={
                    'TagSet': [
                        {
                            'Key': 'cost_centre',
                            'Value': tags['Value']
                        }
                    ]
                }
            )

Can someone help in fixing this code where it will only update the cost centre tag with wrong semantics and keep the value as it is as my purpose is to only fix the grammar and semantics of the tag cost_centre

profile picture
Arjun
answered a year ago
  • The put_bucket_tagging API sets the tags on the bucket. It does not add or modify one of the tags. What you need to do is read the tags into a map, modify the map in memory and then set the modified map.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions