Skip to content

Commit

Permalink
Merge pull request #1 from isilanes/isilanes
Browse files Browse the repository at this point in the history
Changes seem good, I'll merge and probably adjust some of the main logic.
  • Loading branch information
adsanz authored Oct 9, 2022
2 parents be002e0 + 1d23ac2 commit 6a49811
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vscode
.vscode
.idea
144 changes: 102 additions & 42 deletions lister.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
#!/usr/bin/python3

import boto3
import argparse
from argparse import RawTextHelpFormatter
import datetime
import json
import datetime
import argparse

import boto3
from rich.json import JSON
from rich.console import Console
from rich.table import Table


REGIONS = (
'us-west-1',
'us-west-2',
'us-east-1',
'us-east-2',
'eu-west-1',
'eu-west-2',
'eu-west-3',
'eu-central-1',
'eu-north-1',
'ap-south-1',
'ap-southeast-1',
'ap-northeast-1',
'ap-northeast-2',
'ap-northeast-3',
'ap-southeast-1',
'ap-southeast-2',
'sa-east-1',
'ca-central-1',
)


parser = argparse.ArgumentParser(description="""
This script will list your ec2 instance with a given profile.
You may also define a region (if not configured on the profile this is required), and you can filter. A few examples:
Expand All @@ -34,39 +56,54 @@
- Find out how many instances per region you have
lister.py -p leo -l
""",formatter_class=RawTextHelpFormatter)
""", formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-r','--region', help='Region to be used for ec2 listing', required=False, default=None)
parser.add_argument('-p','--profile', help='Profile to authenticate', required=True)
parser.add_argument('-fk','--filter_key', help='Key used for filtering', required=False, default=None, nargs='*')
parser.add_argument('-fv','--filter_value', help='Value used for filtering (one or more)', required=False, default=None, nargs='*')
parser.add_argument('-l','--list', help='Ammount of instances per region (one or more)', required=False, default=None, action='store_true')
parser.add_argument('-i','--instance-id', help='Get instance details nicely formated', required=False, default=None)
parser.add_argument('-i','--instance-id', help='Get instance details nicely formatted', required=False, default=None)
parser.add_argument('-l','--list', help='Amount of instances per region (one or more)', required=False, default=None, action='store_true')
args = vars(parser.parse_args())

console = Console()
if args['region'] != None:
session = boto3.session.Session(profile_name=args['profile'], region_name=args['region'])
else:
session = boto3.session.Session(profile_name=args['profile'])
ec2 = session.resource('ec2')

def lister(ec2):
if args['list'] != None:
regions = ['us-west-1', 'us-west-2', 'us-east-1', 'us-east-2', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-central-1', 'eu-north-1', 'ap-south-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-northeast-2',
'ap-northeast-3', 'ap-southeast-1', 'ap-southeast-2', 'sa-east-1', 'ca-central-1']
for region in regions:
instances = 0
with console.status("[bold green]Getting instances...", spinner="dots") as status:
for instance in ec2.instances.all():
instances = instances+1
if instances != 0:
console.log("Found [bold underline white on black]{}[/] instances on region [bold underline white on black]{}[/]".format(instances,region), style="bold green" )
else:
console.log("Found [bold underline red on black]{}[/] instances on region [bold underline white on black]{}[/]".format(instances,region), style="bold red" )

def instance(ec2):


def get_ec2(profile: str, region: str):
session = boto3.session.Session(profile_name=profile, region_name=region)

return session.resource("ec2")


def lister() -> None:
"""
List how many instances we have for each region.
Args:
None.
Return:
Nothing.
"""
for region in REGIONS:
with console.status(f"[bold green]Getting instances for[/] {region} ...", spinner="dots"):
ec2 = get_ec2(profile=args.get("profile"), region=region)
instances = list(ec2.instances.all())

color = "white"
style = "bold green"
if not instances:
color = "red"
style = "bold red"

msg = (
f"Found [bold underline {color} on black]{len(instances)}[/] instances on"
f" region [bold underline white on black]{region}[/]"
)
console.log(msg, style=style)


def show_instance(ec2):
with console.status("[bold green]Getting instances...", spinner="dots"):
instance = ec2.Instance(args['instance_details'])
instance = ec2.Instance(args.get("instance_id"))
table = Table(show_header=True, header_style="bold magenta", show_lines=True)
table.add_column("Attribute", style="white bold dim", width=20)
table.add_column("Value", style="white dim")
Expand All @@ -79,20 +116,26 @@ def instance(ec2):
table.add_row("Instance Public DNS", instance.public_dns_name)
table.add_row("Instance Private DNS", instance.private_dns_name)
table.add_row("Instance Key Name", instance.key_name)
table.add_row("Instance IAM Role", instance.iam_instance_profile)
table.add_row("Instance IAM Role", JSON(json.dumps(instance.iam_instance_profile)))
table.add_row("Instance VPC ID", instance.vpc_id)
table.add_row("Instance Subnet ID", instance.subnet_id)
table.add_row("Instance Security Groups", JSON(json.dumps(instance.security_groups)))
table.add_row("Instance Tags", JSON(json.dumps(instance.tags)))
console.print(table)


def main(ec2):
if args['region'] != None:
session = boto3.session.Session(profile_name=args['profile'], region_name=args['region'])
else:
session = boto3.session.Session(profile_name=args['profile'])

if args['filter_key'] and args['filter_value'] != None:
filter = [{'Name': 'instance-state-name', 'Values': ['running']}]
# allow multiple sets of filter keys and values
for fk,fv in zip(args['filter_key'],args['filter_value']):
if "," in fv:
filter_list= [{'Name': fk, 'Values': fv.split(',')}]
filter_list = [{'Name': fk, 'Values': fv.split(',')}]
else:
filter_list = [{'Name': fk, 'Values': [fv]}]
filter += filter_list
Expand All @@ -102,37 +145,54 @@ def main(ec2):
ec2_list = []

ec2 = session.resource('ec2')
with console.status("[bold green]Listing instances...", spinner="dots") as status:
with console.status("[bold green]Listing instances...", spinner="dots"):
for instance in ec2.instances.filter(
Filters=filter):
uptime = (datetime.datetime.now().astimezone() - instance.launch_time).days
pub_ip = instance.public_ip_address
# No need to check if priv IP are empty, since AWS will always assign a private IP to instances

# No need to check if private IPs are empty, since AWS will always assign a private IP to instances
priv_ip_list = []
for priv_ip in instance.network_interfaces_attribute:
priv_ip_list.append(priv_ip['PrivateIpAddress'])
name = "None"
if pub_ip == None:

if pub_ip is None:
pub_ip = "None"
if instance.tags == None:

if instance.tags is None:
tags = "None"
else:
for tags in instance.tags:
if tags["Key"] == "Name":
name = tags["Value"]

ec2_list.append([instance.instance_id,name, pub_ip, ", ".join(priv_ip_list), str(uptime)+" Days"])

ec2_table = Table(title="EC2 Instances")
for header in ['Instance ID','Name','Public IP', 'Private IP', 'Uptime (days)']:

for header in ['Instance ID', 'Name', 'Public IP', 'Private IP', 'Uptime (days)']:
ec2_table.add_column(header, justify="center", style="cyan", no_wrap=True)

for row in ec2_list:
ec2_table.add_row(*row)

console.print(ec2_table)

if args['list'] != None:
lister(ec2)
elif args['instance_id'] != None:
instance(ec2)
else:
main(ec2)

if __name__ == "__main__":
profile_name = args.get("profile")
region_name = args.get("region")

ec2 = None
if region_name:
ec2 = get_ec2(profile=profile_name, region=region_name)

if args.get("list"):
lister()

elif args.get("instance_id"):
show_instance(ec2)

else:
main(ec2)

0 comments on commit 6a49811

Please sign in to comment.