Skip to content
Advertisement

For loop is taking only the last element in the list

I am sorry for a simple question, but tried multiple options without any solution. he Problem I have is the for loop is taking only the last value in the list(Regions).

import boto3
import csv
import io
from io import BytesIO
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart


ses = boto3.client('ses')
email_from = 'example@gmail.com'
email_to = 'example@gmail.com'
email_cc = 'example@gmail.com'
emaiL_subject = 'Unused_Security'
email_body = '***Link to S3 Object***'


def lambda_handler(event, context):
    regions = ['eu-west-1','eu-west-2','us-east-2','us-west-1','us-west-2','us-east-1']
    for region in regions:
        csvio = io.BytesIO()
        writer = csv.writer(csvio)
        writer.writerow([
            'Account Name',
            'Region',
            'Id'
        ])
        ec2 = boto3.resource('ec2', region_name=region)
        sgs = list(ec2.security_groups.all())
        insts = list(ec2.instances.all())
        all_sgs = set([sg.group_id for sg in sgs])
        all_inst_sgs = set([sg['GroupId'] for inst in insts for sg in
        inst.security_groups])
        unused_sgs = all_sgs - all_inst_sgs
        for elem in unused_sgs:
            writer.writerow([
                Account_Name,
                region,
                elem
                ])
        s3 = boto3.client('s3')
        s3.put_object(Body=csvio.getvalue(), ContentType='application/vnd.ms-excel', Bucket='unused-sg', Key='Unused_Security.csv', ACL='public-read') 

        csvio.close()
        s3.get_object(Bucket='unused-sg', Key='Unused_Security.csv') 
    response = ses.send_email(
        Source = email_from,
        Destination={
            'ToAddresses': [
                email_to,
            ],
            'CcAddresses': [
                email_cc,
            ]
        },
        Message={
            'Subject': {
                'Data': emaiL_subject
            },
            'Body': {
                'Text': {
                    'Data': email_body
                }
            }
        }
    )

This is the list and it takes only the last value

regions = ['eu-west-1','eu-west-2','us-east-2','us-west-1','us-west-2','us-east-1']

It has to take all the values in the list(Regions) and display the result. But it takes only the last value(us-east-1). Please advice what is causing the error.

Advertisement

Answer

Here:

for region in regions:
    csvio = io.BytesIO()
    writer = csv.writer(csvio)
    # ...
    s3.put_object(Body=csvio.getvalue(), ContentType='application/vnd.ms-excel', Bucket='unused-sg', Key='Unused_Security.csv', ACL='public-read') 

you are creating a new csv file for each region, overwriting the previous one. You want to keep this out of the loop:

csvio = io.BytesIO()
writer = csv.writer(csvio)
for region in regions:
    # massage the data 
    # write to the csv
    # ...

# now we're outside the loop we write the full thing
s3 = boto3.client('s3')
s3.put_object(Body=csvio.getvalue(), ContentType='application/vnd.ms-excel', Bucket='unused-sg', Key='Unused_Security.csv', ACL='public-read') 
csvio.close()
Advertisement