Created
December 11, 2019 05:24
-
-
Save pinkeen/306d51b460511680120ef5c92a080ff8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import absolute_import, division, print_function | |
__metaclass__ = type | |
import re | |
import sys | |
import json | |
import datetime | |
import itertools | |
import traceback | |
import configparser | |
import itertools | |
try: | |
import boto3 | |
HAS_BOTO3 = True | |
except ImportError: | |
print('# This script requires boto3 library!', file=sys.stderr) | |
sys.exit(5) | |
ROLE_TAG = 'Role' | |
ENVIRONMENT_TAG = 'AppName' | |
FILTERS = { | |
'instance-state-name': ['running', 'pending'], | |
} | |
TAG_FILTERS = { | |
'Infrastructure': 'mageops', | |
'Project': 'creativeshop', | |
'Environment': 'proto' | |
} | |
_to_snakecase_re_a = re.compile(r'((?:^|[a-z0-9])[A-Z])([A-Z](?:[a-z0-9]|$))') | |
_to_snakecase_re_b = re.compile(r'(?:([a-z0-9])([A-Z]))') | |
_to_safe_name_re = re.compile(r'[^a-z_:]+') | |
flatten = itertools.chain.from_iterable | |
def get_groups_for_tag(key, value): | |
if key == ROLE_TAG: return [value] | |
elements = split_by_case(key) | |
if elements[0] == to_safe_name(ROLE_TAG): | |
return ['_'.join(elements[1:]), value] | |
return [] | |
def get_groups_for_tags(tags): | |
return flatten([get_groups_for_tag(k, v) for k, v in tags.items()]) | |
def get_groups_for_instance(instance): | |
groups = [] | |
if 'tags' in instance: | |
groups.extend(get_groups_for_tags(instance['tags'])) | |
return map(to_safe_name, groups) | |
def get_hostname_for_instance(instance): | |
if 'public_dns_name' in instance: | |
return instance['public_dns_name'] | |
if 'public_ip_address' in instance: | |
return instance['public_ip_address'] | |
if 'private_ip_address' in instance: | |
return instance['private_ip_address'] | |
def remap_keys(object={}, keymap={}): | |
return { (keymap[key] if key in keymap else key): object[key] for key in object } | |
def pick_keys(object={}, keys=[]): | |
return { key: object[key] for key in keys if key in object } | |
def reject_keys(object={}, keys=[]): | |
return { key: object[key] for key in object if key not in keys } | |
def prefix_keys(object={}, prefix=''): | |
return { prefix + key: object[key] for key in object } | |
def pick_prefixed_keys(object={}, prefix=''): | |
return dict([(key, object[key]) for key in object if key.startswith(prefix)]) | |
def dict_to_filters(d): | |
return [{'Name': k, 'Values': v} for k, v in d.items()] | |
def tags_to_dict(l): | |
return {x['key']: x['value'] for x in l if 'key' in x and 'value' in x} | |
def snakecase(s): | |
return _to_snakecase_re_b.sub(r'\1_\2', | |
_to_snakecase_re_a.sub(r'\1_\2', s)).lower() | |
def split_by_case(s): | |
return snakecase(s).split('_') | |
def to_safe_name(s): | |
return _to_safe_name_re.sub('_', s.lower()) | |
def normalize_keys(d): | |
if type(d) is dict: | |
return {to_safe_name(snakecase(k)): normalize_keys(v) for k, v in d.items()} | |
if type(d) is list or type(d) is tuple: | |
return [normalize_keys(s) for s in d] | |
return d | |
def normalize_instance(instance): | |
instance = normalize_keys(instance) | |
if 'tags' in instance: | |
instance.update({'tags': tags_to_dict(instance['tags'])}) | |
return instance | |
def get_instances(filters={}): | |
session = boto3.Session() | |
paginator = boto3.client('ec2').get_paginator('describe_instances') | |
pages = paginator.paginate(Filters=dict_to_filters(filters)) | |
instances = flatten([reservation['Instances'] for reservation | |
in flatten([page['Reservations'] for page in pages])]) | |
return map(normalize_instance, instances) | |
def serialize(o): | |
if isinstance(o, (datetime.date, datetime.datetime)): | |
return o.isoformat() | |
def build_inventory(instances): | |
host_groups = {} | |
host_vars = {get_hostname_for_instance(instance): instance for instance in instances} | |
for hostname, instance in hostvars.items(): | |
for group_name in get_groups_for_instance(instance): | |
if not group_name in host_groups: | |
host_groups[group_name] = [] | |
host_groups[group_name]['hosts'].append(hostname) | |
if not 'all' in host_groups: | |
host_groups['all'] = host_groups.keys() | |
else | |
host_groups[''] | |
host_groups['all'].extend() | |
def inventory_to_json(inventory): | |
return json.dumps(inventory, sort_keys=True, indent=4, default=serialize) | |
def invnetory_to_init(inventory): | |
ini = configparser.ConfigParser() | |
def main(): | |
instances = get_instances(filters=FILTERS) | |
inventory = build_inventory(instances) | |
print() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment