-
Notifications
You must be signed in to change notification settings - Fork 1
/
check-ri-usage.py
124 lines (114 loc) · 4.48 KB
/
check-ri-usage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import boto3
import botocore
import json
from datetime import datetime, date, timedelta
import csv
import ConfigParser
import os
import argparse
def json_serial(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
raise TypeError ("Type %s not serializable" % type(obj))
def get_regions(session):
client = session.client('ec2')
regions = client.describe_regions()
return [
region['RegionName']
for region in regions['Regions']
]
def get_reservations(account, session, regions):
res = []
for region in regions:
client = session.client('ec2', region_name=region)
for reserved_instance in client.describe_reserved_instances(
Filters=[{'Name': 'state', 'Values': ['active']}])['ReservedInstances']:
res += [
{
'Account': account,
'region': region,
'OfferingType': reserved_instance['OfferingType'],
'InstanceType': reserved_instance['InstanceType'],
'InstanceCount': reserved_instance['InstanceCount'],
'End': reserved_instance['End'],
'Unused': 0
}
]
return res
def get_instances(account, session, regions):
res = []
for region in regions:
client = session.client('ec2', region_name=region)
reservations = client.describe_instances()
res += [
{
'account': account,
'type': instance['InstanceType'],
'region': region,
'used': 0
}
for reservation in reservations['Reservations']
for instance in reservation['Instances']
]
return res
def check_used_ri(instances, reservations):
for reservation in reservations:
to_use = reservation['InstanceCount']
for instance in instances:
if instance['region'] == reservation['region'] and instance['used'] == 0 and instance['type'] == reservation['InstanceType']:
instance['used'] = 1
to_use -= 1
if to_use == 0:
break
reservation['Unused'] = to_use
return reservations
def generate_csv(data, args, header_name):
filename = "report.csv"
if args['o']:
filename = args['o']
with open(filename, 'wb') as file:
writer = csv.DictWriter(file, header_name)
writer.writeheader()
for row in data:
writer.writerow(row)
def init():
config_path = os.environ.get('HOME') + "/.aws/credentials"
parser = ConfigParser.ConfigParser()
parser.read(config_path)
if parser.sections():
return parser.sections()
return []
def main():
instances = []
reservations = []
parser = argparse.ArgumentParser(description="Analyse reserved instances")
parser.add_argument("--profile", nargs="+", help="Specify AWS profile(s) (stored in ~/.aws/credentials) for the program to use")
parser.add_argument("-o", nargs="?", help="Specify output csv file")
parser.add_argument("--profiles-all", nargs="?", help="Run it on all profile")
aws_access_key = os.environ.get('AWS_ACCESS_KEY_ID')
aws_secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
aws_region = os.environ.get('AWS_DEFAULT_REGION')
args = vars(parser.parse_args())
if 'profiles-all' in args:
keys = init()
elif 'profile' in args and args['profile']:
keys = args['profile']
else:
keys = init()
for key in keys:
print 'Processing %s...' % key
try:
if aws_access_key and aws_secret_key and aws_region:
session = boto3.Session(aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key, region_name=aws_region)
else:
session = boto3.Session(profile_name=key)
regions = get_regions(session)
instances += get_instances(key, session, regions)
reservations += get_reservations(key, session, regions)
except botocore.exceptions.ClientError, error:
print error
result = check_used_ri(instances, reservations)
generate_csv(result, args, ['Account', 'region', 'OfferingType', 'InstanceType', 'InstanceCount', 'End', 'Unused'])
print json.dumps(result, indent=4, default=json_serial)
if __name__ == '__main__':
main()