"""Utilities for determining configuration for AWS environment.""" import logging import boto3 from product_workflow import config VPC_ENVIRONMENT_MAPPING = { 'dev': 'dev', 'qa': 'prod', 'prod': 'prod', } def get_vpc_id(ec2_client): """Get VPC corresponding to environment. Raises: SystemExit: If VPC cannot be found Returns: str: ID of VPC """ response = ec2_client.describe_vpcs( Filters=[ { 'Name': 'tag:Name', 'Values': [ VPC_ENVIRONMENT_MAPPING[config.ENVIRONMENT], ] }, ], ) if response['Vpcs']: vpc_id = response['Vpcs'][0]['VpcId'] return vpc_id else: logging.info('VPC named {} not found'.format( VPC_ENVIRONMENT_MAPPING[config.ENVIRONMENT])) raise SystemExit('Could not retrieve VPC ID') def get_security_group(vpc_id, ec2_client, service_name='ows-timed-release'): """Returns security group corresponding to service. Args: vpc_id (string): ID of VPC for use in lookup filter Raises: SystemExit: If security group cannot be found Returns: str: ID of security group for service """ security_group_name = '{}-{}-task-security-group'.format( config.ENVIRONMENT, service_name) response = ec2_client.describe_security_groups( Filters=[ { 'Name': 'group-name', 'Values': [ security_group_name, ] }, { 'Name': 'vpc-id', 'Values': [ vpc_id, ] }, ], ) if response['SecurityGroups']: """ Infrastructure automation enforces uniqueness, but just in case, pick the first returned group """ security_group_id = response['SecurityGroups'][0]['GroupId'] return security_group_id else: logging.info('Security group named {} not found'.format( security_group_name)) raise SystemExit('Could not retrieve security group') def get_subnets(vpc_id, ec2_client): """Returns subnet IDs with most available IP addresses. Args: vpc_id (string): ID of VPC for use in lookup filter Raises: SystemExit: If subnets cannot be found Returns: list: IDs of subnets """ response = ec2_client.describe_subnets( Filters=[ { 'Name': 'tag:Name', 'Values': [ '*private*', ] }, { 'Name': 'tag:tier', 'Values': [ 'private', ] }, { 'Name': 'vpc-id', 'Values': [ vpc_id, ] }, ], ) if response['Subnets']: """ Find and return up to two subnets with the most available IP addresses """ sorted_subnets = sorted( response['Subnets'], key=lambda k: k['AvailableIpAddressCount'], reverse=True ) subnet_ids = [subnet['SubnetId'] for subnet in sorted_subnets] return subnet_ids[0:2] else: logging.info('No subnets found in VPC ID {}'.format(vpc_id)) raise SystemExit('Could not retrieve subnet IDs') def get_network_config(): """Return network configuration for fargate.""" ec2_client = boto3.client('ec2', region_name=config.AWS_REGION) return { 'awsvpcConfiguration': { 'subnets': get_subnets(get_vpc_id(ec2_client), ec2_client), 'securityGroups': [ get_security_group(get_vpc_id(ec2_client), ec2_client) ], 'assignPublicIp': 'DISABLED' } }