import logging from product_staging import config from product_staging.api.datasources import get_ec2_client, get_ecs_client logger = logging.getLogger(__name__) def run_task(task_name, container_name, env_vars): """Runs the Fargate task with the provided name.""" container_env = [{"name": k, "value": v} for k, v in env_vars.items()] vpc_id = get_vpc_id() response = get_ecs_client().run_task( cluster=task_name, launchType="FARGATE", taskDefinition=task_name, count=1, networkConfiguration={ "awsvpcConfiguration": { "subnets": get_subnets(vpc_id), "securityGroups": [get_security_group(vpc_id)], "assignPublicIp": "DISABLED", } }, tags=[ {"key": "environment", "value": config.ENVIRONMENT}, { "key": "service_name", "value": config.SERVICE_NAME, }, ], overrides={ "containerOverrides": [ {"name": container_name, "environment": container_env}, ], }, ) task_arn = response["tasks"][0]["taskArn"] return task_arn def get_vpc_id(): """Get VPC corresponding to environment. Raises: SystemExit: If VPC cannot be found Returns: str: ID of VPC """ response = get_ec2_client().describe_vpcs( Filters=[ { "Name": "tag:Name", "Values": [ "prod", ], }, ], ) if response["Vpcs"]: vpc_id = response["Vpcs"][0]["VpcId"] return vpc_id else: logging.info("VPC not found") raise SystemExit("Could not retrieve VPC ID") def get_security_group(vpc_id): """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 = ( f"{config.ENVIRONMENT}-{config.SERVICE_NAME}-task-security-group" ) response = get_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): """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 """ subnet_prefix = ( "prod_private" if config.ENVIRONMENT == config.PROD_ENVIRONMENT else "qa_priv" ) response = get_ec2_client().describe_subnets( Filters=[ { "Name": "tag:Name", "Values": [ f"{subnet_prefix}_subnet_*", ], }, { "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")