cTOifQqxtMAK6Y0uarrvGet a list of All Detached AWS EC2 Instances from an ASG
Get a list of All Detached AWS EC2 Instances from an ASG
This task involves identifying AWS EC2 instances that are not currently associated with any Auto Scaling Groups (ASGs).
Note: region_name = None, fetches the results from all regions.
inputs
outputs
import boto3
from botocore.exceptions import NoCredentialsError, PartialCredentialsError, BotoCoreError, ClientError
creds = _get_creds(cred_label)['creds']
access_key = creds['username']
secret_key = creds['password']
def list_all_regions():
ec2 = boto3.client('ec2', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name='us-east-1')
return [region['RegionName'] for region in ec2.describe_regions()['Regions']]
def list_detached_ec2_instances(region=None):
regions = [region] if region else list_all_regions()
detached_instances = []
for region in regions:
try:
ec2_client = boto3.client('ec2', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name=region)
asg_client = boto3.client('autoscaling', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name=region)
except (NoCredentialsError, PartialCredentialsError, BotoCoreError) as e:
print(f"Failed for {region}: {str(e)}")
continue
try:
all_instances = []
paginator = ec2_client.get_paginator('describe_instances')
for page in paginator.paginate():
for reservation in page['Reservations']:
for instance in reservation['Instances']:
all_instances.append(instance['InstanceId'])
# Get all instance IDs in Auto Scaling Groups
asg_instances = []
paginator = asg_client.get_paginator('describe_auto_scaling_instances')
for page in paginator.paginate():
for asg_instance in page['AutoScalingInstances']:
asg_instances.append(asg_instance['InstanceId'])
# Determine detached instances by finding instances not in any ASG
detached_instances_ids = set(all_instances) - set(asg_instances)
# Fetch details for detached instances
if detached_instances_ids:
for instance_id in detached_instances_ids:
response = ec2_client.describe_instances(InstanceIds=[instance_id])
for reservation in response['Reservations']:
for instance in reservation['Instances']:
detached_instances.append({
'InstanceId': instance['InstanceId'],
'InstanceType': instance['InstanceType'],
'LaunchTime': instance['LaunchTime'],
'State': instance['State']['Name'],
'Region': region
})
except ClientError as e:
print(f"Failed for {region}: {e}")
return detached_instances
def display_detached_instance_details(data):
# Check if any data is present
if not data:
print("No detached instances found.")
return
# Initialize the table with the desired structure and headers
table = context.newtable()
table.title = "Detached EC2 Instance Details"
table.num_cols = 5 # Number of columns according to headers
table.num_rows = 1 # Starts with one row for headers
table.has_header_row = True
# Define header names based on the new structure
headers = ["Instance ID", "Instance Type", "Launch Time", "State", "Region"]
# Set headers in the first row
for col_num, header in enumerate(headers):
table.setval(0, col_num, header)
# Sort the instance data by launch time for better organization
data.sort(key=lambda x: x["LaunchTime"], reverse=True)
# Populate the table with instance data
for row_num, instance in enumerate(data, start=1): # Starting from the second row
table.num_rows += 1 # Add a row for each instance
values = [
instance["InstanceId"],
instance["InstanceType"],
instance["LaunchTime"].strftime('%Y-%m-%d %H:%M:%S'), # Format the datetime
instance["State"],
instance["Region"]
]
for col_num, value in enumerate(values):
table.setval(row_num, col_num, value)
# Example usage
#region_name = None # Set this to a specific region or None to check all regions
detached_instances = list_detached_ec2_instances(region_name)
display_detached_instance_details(detached_instances)
copied