Repository URL to install this package:
|
Version:
0.3.30 ▾
|
import os
import sys
import subprocess
from ConfigParser import SafeConfigParser
from boto import ec2
from . import utils
from . import hosts
GROUP_TO_STACK = dict(
aws_prod='us-east-1',
aws_stage='stage-us-east-1-150610-005505',
)
STACK_TO_REGION = {
'us-east-1': 'us-east-1',
'stage-us-east-1': 'us-east-1',
'stage-us-east-1-150610-005505': 'us-east-1',
}
class AWSCredsProvider(object):
DESCRIPTION = None
def __init__(self, stack_name):
self.stack = stack_name
self.region = STACK_TO_REGION[stack_name]
@property
def access_key(self):
raise NotImplementedError
@property
def secret(self):
raise NotImplementedError
@classmethod
def get_provider(cls, stack_name):
excs = []
for kls in (PassCredsProvider, EnvCredsProvider, AWSCLIProvider):
try:
prov = kls(stack_name)
if None not in (prov.access_key, prov.secret):
print >>sys.stderr, "Using AWS credentials from {} for stack {}".format(
prov.DESCRIPTION, prov.stack
)
return prov
except Exception:
excs.append((sys.exc_info()))
if len(excs) == 1:
raise excs[0]
else:
raise Exception(
"No AWS credentials could be found. " +
"The following errors occurred:\n" +
('\n'.join(e[0].message for e in excs) or
'No credentials provider found')
)
class PassCredsProvider(AWSCredsProvider):
DESCRIPTION = '`pass` password manager'
PASS_LOCATION = 'dev/teams/hub/apps/hubboss/'
ACCESS_KEY_NAME = 'aws_access_key'
SECRET_KEY_NAME = 'aws_secret_access_key'
def __init__(self, stack_name):
AWSCredsProvider.__init__(self, stack_name)
self._secret = None
self._access_key = None
@property
def access_key(self):
if getattr(self, '_access_key', None) is None:
self._access_key = self._get_pass_entry(self.ACCESS_KEY_NAME)
return self._access_key
@property
def secret(self):
if getattr(self, '_secret', None) is None:
self._secret = self._get_pass_entry(self.SECRET_KEY_NAME)
return self._secret
def _get_pass_entry(self, key, attempt_update=True):
result = self._pass_show(
self.PASS_LOCATION + key,
)
if result is None and attempt_update:
return self._get_pass_entry(key, False)
return result
def _pass_show(self, path):
try:
return subprocess.check_output(['pass', 'show', path]).strip()
except subprocess.CalledProcessError:
return None
class AWSCLIProvider(AWSCredsProvider):
DESCRIPTION = 'AWS configuration (~/.aws)'
def __init__(self, stack_name):
AWSCredsProvider.__init__(self, stack_name)
self._config = SafeConfigParser()
self._creds = SafeConfigParser()
self._config.read(utils.normpath('~/.aws/config'))
self._creds.read(utils.normpath('~/.aws/credentials'))
self.profile = 'default'
for profile in self._config.sections():
if self._config.get(profile, 'region') == self.region:
self.profile = profile
break
@property
def access_key(self):
return self._creds.get(self.profile, 'aws_access_key_id')
@property
def secret(self):
return self._creds.get(self.profile, 'aws_secret_access_key')
class EnvCredsProvider(AWSCredsProvider):
DESCRIPTION = 'Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)'
@property
def access_key(self):
return os.environ.get('AWS_ACCESS_KEY_ID', None)
@property
def secret(self):
return os.environ.get('AWS_SECRET_ACCESS_KEY', None)
@utils.memoize
def get_all_instances(stack_name):
creds = AWSCredsProvider.get_provider(stack_name)
con = ec2.connect_to_region(
STACK_TO_REGION[stack_name],
aws_access_key_id=creds.access_key,
aws_secret_access_key=creds.secret
)
reservations = con.get_all_instances(
filters={
"tag:aws:cloudformation:stack-name": stack_name,
"tag:secondary-role": "hub",
"instance-state-name": "running",
}
)
return utils.flatten([reservation.instances for reservation in reservations])
def get_aws_hosts(config, group_name):
stack_name = GROUP_TO_STACK[group_name]
# We want to return the hosts with consistent short names. So we
# need to get a consistent ordering of the ec2 nodes
instances = get_all_instances(stack_name)
instances.sort(key=lambda inst: inst.private_dns_name)
short_group_name = _gen_short_name(group_name)
for i, instance in enumerate(instances):
url = "https://{}:2376".format(instance.private_ip_address)
yield hosts.Host(
name="{}{}".format(short_group_name, i + 1),
base_url=url,
tls=config.get_tls(url),
environment=group_name,
ip=instance.private_ip_address
)
def _gen_short_name(group_name):
return ''.join([sub[0] for sub in group_name.split('_')])