get_ebs_volumes - robjcook/sync GitHub Wiki

import boto3
import csv
from datetime import datetime

def get_ebs_volumes_with_specific_tags_to_csv(
    region_name='us-east-1', 
    output_file='ebs_volumes_tags.csv', 
    tag_keys_to_include=None,
    ignore_name_tag_prefix=None
):
    """
    Pulls a list of EBS volumes and their metadata from a specified AWS region.
    It creates a CSV file with each of the specified tag keys as its own column,
    while ignoring any volumes whose 'Name' tag value starts with a specified prefix.

    Args:
        region_name (str): The AWS region to query for EBS volumes.
        output_file (str): The name of the output CSV file.
        tag_keys_to_include (list): A list of strings representing the tag keys to 
                                    include as separate columns in the CSV.
        ignore_name_tag_prefix (str): A string prefix for the 'Name' tag value to ignore.
                                      For example, 'workerenv' will ignore any 
                                      volume with a 'Name' tag value starting with 'workerenv'.
    """
    if not tag_keys_to_include:
        print("No tag keys specified. Please provide a list of tag keys to include.")
        return

    try:
        ec2_client = boto3.client('ec2', region_name=region_name)
        print(f"Connecting to AWS region: {region_name}...")
        
        # Define the static metadata field names
        base_fieldnames = [
            'VolumeId', 'VolumeType', 'Size', 'Iops', 'State', 
            'AvailabilityZone', 'CreateTime', 'Encrypted', 'SnapshotId', 
            'Attachment_InstanceId', 'Attachment_Device'
        ]

        # Combine base field names with the user-specified tag keys to form the full header
        all_fieldnames = base_fieldnames + tag_keys_to_include

        # Prepare the CSV file for writing
        with open(output_file, 'w', newline='') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=all_fieldnames)
            writer.writeheader()

            print(f"Retrieving EBS volume data and writing to '{output_file}'...")
            
            volume_count = 0
            filtered_out_count = 0
            
            # Paginate through all EBS volumes
            paginator = ec2_client.get_paginator('describe_volumes')
            volume_pages = paginator.paginate()

            for page in volume_pages:
                for volume in page['Volumes']:
                    # Extract tags first, as we need them for filtering
                    tags_list = volume.get('Tags', [])
                    tags_dict = {tag['Key']: tag['Value'] for tag in tags_list}

                    # --- New Logic: Ignore volumes based on 'Name' tag prefix ---
                    name_tag_value = tags_dict.get('Name', '') # Get 'Name' tag value, default to empty string if not found
                    if ignore_name_tag_prefix and name_tag_value.startswith(ignore_name_tag_prefix):
                        filtered_out_count += 1
                        continue # Skip to the next volume

                    volume_count += 1
                    
                    # Create a dictionary for the current row
                    row_data = {
                        'VolumeId': volume.get('VolumeId'),
                        'VolumeType': volume.get('VolumeType'),
                        'Size': volume.get('Size'),
                        'Iops': volume.get('Iops', 'N/A'),
                        'State': volume.get('State'),
                        'AvailabilityZone': volume.get('AvailabilityZone'),
                        'CreateTime': volume.get('CreateTime', datetime.min).isoformat(),
                        'Encrypted': volume.get('Encrypted'),
                        'SnapshotId': volume.get('SnapshotId', 'N/A')
                    }
                    
                    # Handle attachments
                    attachments = volume.get('Attachments', [])
                    row_data['Attachment_InstanceId'] = attachments[0].get('InstanceId', 'N/A') if attachments else 'N/A'
                    row_data['Attachment_Device'] = attachments[0].get('Device', 'N/A') if attachments else 'N/A'
                    
                    # Add a value for each desired tag, using the already-created tags_dict
                    for tag_key in tag_keys_to_include:
                        row_data[tag_key] = tags_dict.get(tag_key, 'N/A')
                    
                    writer.writerow(row_data)

        print(f"Successfully retrieved and processed {volume_count} EBS volumes.")
        if filtered_out_count > 0:
            print(f"Ignored {filtered_out_count} volumes based on the 'Name' tag prefix: '{ignore_name_tag_prefix}'.")
        print(f"CSV file '{output_file}' created successfully.")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == '__main__':
    # --- Example Usage ---
    
    # Define the list of tag keys you want as individual columns
    my_desired_tags = ['Name', 'Environment', 'System']
    
    # Define the prefix for the 'Name' tag to ignore
    name_prefix_to_ignore = 'workerenv'
    
    get_ebs_volumes_with_specific_tags_to_csv(
        region_name='us-east-1',
        output_file='ebs_volumes_filtered_by_name.csv',
        tag_keys_to_include=my_desired_tags,
        ignore_name_tag_prefix=name_prefix_to_ignore
    )