Exemplo n.º 1
0
 def _delete_region_vpc(cls, region):
     """delete VPC from AWS region with correct namespace tag"""
     region_vpc = aws.get_region_vpc(region)
     if region_vpc is not None:
         cls._delete_vpc_sgs(region, region_vpc['VpcId'])
         cls._delete_vpc_subnets(region, region_vpc['VpcId'])
         cls._delete_vpc_internet_gateways(region, region_vpc['VpcId'])
         aws.ec2_client(region).delete_vpc(VpcId=region_vpc['VpcId'])
         return True
     return False
Exemplo n.º 2
0
def _probe_region(region, instances):
    """return elastic IP addresses in region

    Requires ec2:DescribeAddresses permission.
    """
    ec2_client = aws.ec2_client(region)
    addresses = ec2_client.describe_addresses(Filters=[
        {'Name': "domain", 'Values': ["vpc"]},
        {'Name': "tag:Namespace", 'Values': [consts.NAMESPACE]}
    ])['Addresses']

    region_addresses = []
    for address in addresses:
        address_info = {
            'allocation_id': address['AllocationId'],
            'ip': address['PublicIp']
        }
        if 'AssociationId' in address:
            address_info['association_id'] = address['AssociationId']
        if 'InstanceId' in address:
            for instance in instances:
                if (instance['id'] == address['InstanceId'] and
                        instance['region'] == region):
                    address_info['instance_name'] = instance['name']
                    break
        region_addresses.append(address_info)

    return sorted(region_addresses, key=lambda k: k['ip'])
Exemplo n.º 3
0
    def main(self, cmd_args):
        """associate elastic IP address to an (other) instance

        Args:
            cmd_args (namedtuple): See add_documentation method.
        """
        address = find_addresses.main(cmd_args.ip)
        ec2_client = aws.ec2_client(address['region'])

        all_instances = find_instances.probe_regions()
        try:
            instance = next(instance for instance in all_instances
                            if instance['name'] == cmd_args.name)
        except StopIteration:
            halt.err(f"Instance named \"{cmd_args.name}\" not found.")

        if instance['region'] != address['region']:
            halt.err("Instance and address are in different regions.")
        if 'instance_name' in address:
            if instance['name'] == address['instance_name']:
                halt.err("Address already associated with specified instance.")

        if 'association_id' in address and cmd_args.force is False:
            halt.err(f"Elastic IP address {address['ip']} currently in use.",
                     "  Append the -f argument to force disassociation.")

        with aws.ClientErrorHalt():
            if 'association_id' in address:
                ec2_client.disassociate_address(
                    AssociationId=address['association_id'])
            ec2_client.associate_address(AllocationId=address['allocation_id'],
                                         InstanceId=instance['id'])

        print("")
        print("Address associated with instance.")
Exemplo n.º 4
0
 def _delete_vpc_subnets(region, vpc_id):
     """delete VPC's subnet(s) from AWS region"""
     ec2_client = aws.ec2_client(region)
     vpc_subnets = ec2_client.describe_subnets(Filters=[{
         'Name': "vpc-id",
         'Values': [vpc_id]
     }])['Subnets']
     for vpc_subnet in vpc_subnets:
         ec2_client.delete_subnet(SubnetId=vpc_subnet['SubnetId'])
Exemplo n.º 5
0
 def _region_namespace_key_fingerprint(self, region):
     """return key fingerprint if region has namespace EC2 key pair"""
     key_pairs = aws.ec2_client(region).describe_key_pairs(
         Filters=[{
             'Name': "key-name",
             'Values': [self._key_pair_name]
         }])['KeyPairs']
     if key_pairs:
         return key_pairs[0]['KeyFingerprint']
     return None
Exemplo n.º 6
0
    def _create_sg(cls, region, sg_name, sg_desc, vpc_id):
        """create new VPC security group on AWS"""
        ec2_client = aws.ec2_client(region)
        sg_id = ec2_client.create_security_group(Description=sg_desc,
                                                 GroupName=sg_name,
                                                 VpcId=vpc_id)['GroupId']
        aws.attach_tags(region, sg_id, sg_name)

        local_sg_ingress = cls._get_json_sg_ingress(sg_name)
        if local_sg_ingress:
            ec2_client.authorize_security_group_ingress(
                GroupId=sg_id, IpPermissions=local_sg_ingress)
Exemplo n.º 7
0
    def main(self, cmd_args):
        """stop instance(s)

        Args:
            cmd_args (namedtuple): See find_instances:add_argparse_args
        """
        instances = find_instances.main(cmd_args)

        instances_to_stop = False
        instances_stopping = False
        for instance in instances:
            print("")
            print(f"Attempting to stop {instance['name']} "
                f"({instance['id']})...")

            instance_state, _ = find_instances.get_state_and_ip(
                instance['region'], instance['id'])

            if instance_state == "stopped":
                print("  Instance is already stopped.")
                continue
            if instance_state == "stopping":
                instances_stopping = True
                print("  Instance is already in the process of stopping.")
                continue

            instances_to_stop = True
            aws.ec2_client(instance['region']).stop_instances(
                InstanceIds=[instance['id']])
            print(f"  Instance is now stopping.")

        print("")
        if instances_to_stop is True:
            print("Instance(s) may take a few minutes to fully stop.")
        elif instances_stopping is True:
            print("Instance(s) already stopping.")
        else:
            print("No instances to stop.")
Exemplo n.º 8
0
    def _create_vpc(cls, region):
        """create VPC with subnet(s) in region and attach tags"""
        ec2_client = aws.ec2_client(region)
        vpc_id = ec2_client.create_vpc(
            CidrBlock="172.31.0.0/16",
            AmazonProvidedIpv6CidrBlock=False)['Vpc']['VpcId']
        aws.attach_tags(region, vpc_id, consts.NAMESPACE)
        ec2_client.modify_vpc_attribute(EnableDnsSupport={'Value': True},
                                        VpcId=vpc_id)
        ec2_client.modify_vpc_attribute(EnableDnsHostnames={'Value': True},
                                        VpcId=vpc_id)

        route_table_id = cls._create_internet_gateway(region, vpc_id)
        cls._create_vpc_subnets(region, vpc_id, route_table_id)
Exemplo n.º 9
0
    def _delete_vpc_internet_gateways(region, vpc_id):
        """detach (and delete) internet gateway(s) attached (solely) to VPC"""
        ec2_client = aws.ec2_client(region)
        gateways = ec2_client.describe_internet_gateways(
            Filters=[{
                'Name': "attachment.vpc-id",
                'Values': [vpc_id]
            }])['InternetGateways']

        for gateway in gateways:
            ec2_client.detach_internet_gateway(
                InternetGatewayId=gateway['InternetGatewayId'], VpcId=vpc_id)
            # Only delete gateway if attached solely to namespace VPC
            if len(gateway['Attachments']) == 1:
                ec2_client.delete_internet_gateway(
                    InternetGatewayId=gateway['InternetGatewayId'])
Exemplo n.º 10
0
    def _update_sg(cls, region, sg_name, vpc_id):
        """update VPC security group that already exists on AWS"""
        ec2_client = aws.ec2_client(region)
        aws_sgs = aws.get_vpc_security_groups(region, vpc_id)

        sg_id = next(sg['GroupId'] for sg in aws_sgs
                     if sg['GroupName'] == sg_name)
        aws_sg_ingress = next(sg['IpPermissions'] for sg in aws_sgs
                              if sg['GroupName'] == sg_name)
        ec2_client.revoke_security_group_ingress(GroupId=sg_id,
                                                 IpPermissions=aws_sg_ingress)

        local_sg_ingress = cls._get_json_sg_ingress(sg_name)
        if local_sg_ingress:
            ec2_client.authorize_security_group_ingress(
                GroupId=sg_id, IpPermissions=local_sg_ingress)
Exemplo n.º 11
0
    def main(self, cmd_args):
        """disassociate elastic IP address from its instance

        Args:
            cmd_args (namedtuple): See add_documentation method.
        """
        address = find_addresses.main(cmd_args.ip)
        ec2_client = aws.ec2_client(address['region'])

        if 'association_id' not in address:
            halt.err("Elastic IP address not associated with anything.")

        with aws.ClientErrorHalt():
            ec2_client.disassociate_address(
                AssociationId=address['association_id'])

        print("")
        print("Elastic IP address disassociated.")
Exemplo n.º 12
0
def get_state_and_ip(region, instance_ip):
    """return state and (elastic) IP of instance

    Requires ec2:DescribeInstances permission.
    """
    response = aws.ec2_client(region).describe_instances(
        InstanceIds=[instance_ip])['Reservations'][0]['Instances'][0]

    instance_state = response['State']['Name']
    instance_ip = None
    for network_interface in response['NetworkInterfaces']:
        if 'Association' in network_interface:
            # IP is elastic unless association's 'IpOwnerId' is "amazon"
            instance_ip = network_interface['Association']['PublicIp']
            break
    else:
        # Script expects running instances to always have a public IP
        if instance_state == "running":
            instance_state = "???"

    return (instance_state, instance_ip)
Exemplo n.º 13
0
def _probe_region(region, tag_filter):
    """probe single AWS region for non-terminated named instances

    Requires ec2:DescribeInstances permission.

    Args:
        region (str): AWS region to probe.
        tag_filter (list[dict]): Filter out instances that don't have tags
            matching the filter. If None/empty, filter not used.

    Returns:
        list[dict]: Instance(s) found in region.
            'id' (str): ID of instance.
            'name' (str): Tag value for instance tag key "Name".
            'tags' (dict): Instance tag key-value pair(s).
    """
    reservations = aws.ec2_client(region).describe_instances(
        Filters=tag_filter)['Reservations']

    region_instances = []
    for reservation in reservations:
        for instance in reservation['Instances']:
            if instance['State']['Name'] in ("shutting-down", "terminated"):
                continue
            if not any(tag['Key'] == "Name" for tag in instance['Tags']):
                continue

            region_instances.append({
                'id':
                instance['InstanceId'],
                'tags':
                dict(
                    sorted(
                        {tag['Key']: tag['Value']
                         for tag in instance['Tags']}.items()))
            })
            region_instances[-1].update(
                {'name': region_instances[-1]['tags'].pop('Name')})

    return sorted(region_instances, key=lambda k: k['name'])
Exemplo n.º 14
0
    def _create_internet_gateway(region, vpc_id):
        """create internet gateway, attach it to VPC, and configure route"""
        ec2_client = aws.ec2_client(region)
        ig_id = ec2_client.create_internet_gateway(
        )['InternetGateway']['InternetGatewayId']
        aws.attach_tags(region, ig_id, consts.NAMESPACE)
        ec2_client.attach_internet_gateway(InternetGatewayId=ig_id,
                                           VpcId=vpc_id)

        # VPC's automatically created main route table is used
        rt_id = ec2_client.describe_route_tables(Filters=[{
            'Name': "vpc-id",
            'Values': [vpc_id]
        }, {
            'Name': "association.main",
            'Values': ["true"]
        }])['RouteTables'][0]['RouteTableId']
        aws.attach_tags(region, rt_id, consts.NAMESPACE)
        ec2_client.create_route(DestinationCidrBlock="0.0.0.0/0",
                                GatewayId=ig_id,
                                RouteTableId=rt_id)

        return rt_id
Exemplo n.º 15
0
    def _create_vpc_subnets(region, vpc_id, rt_id):
        """create VPC subnet in AWS region for each availability zone

        Args:
            region (str): Region to create subnets in.
            vpc_id (str): ID of VPC to create subnets under.
            rt_id (str): ID of route table to attach subnets to.
        """
        ec2_client = aws.ec2_client(region)
        azs = ec2_client.describe_availability_zones()['AvailabilityZones']
        for index, az in enumerate(azs):
            if az['State'] != "available":
                continue
            if index * 16 >= 256:
                break
            subnet_id = ec2_client.create_subnet(
                AvailabilityZone=az['ZoneName'],
                CidrBlock=f"172.31.{index*16}.0/20",
                VpcId=vpc_id)['Subnet']['SubnetId']
            ec2_client.modify_subnet_attribute(
                MapPublicIpOnLaunch={'Value': True}, SubnetId=subnet_id)
            ec2_client.associate_route_table(RouteTableId=rt_id,
                                             SubnetId=subnet_id)
Exemplo n.º 16
0
    def main(self, cmd_args):
        """release elastic IP address (give up possession)

        Args:
            cmd_args (namedtuple): See add_documentation method.
        """
        address = find_addresses.main(cmd_args.ip)
        ec2_client = aws.ec2_client(address['region'])

        if 'association_id' in address and cmd_args.force is False:
            halt.err(f"Elastic IP address {address['ip']} currently in use.",
                     "  Append the -f argument to force disassociation.")

        print("")
        if 'association_id' in address:
            ec2_client.disassociate_address(
                AssociationId=address['association_id'])
        ec2_client.release_address(AllocationId=address['allocation_id'])

        if 'association_id' in address:
            print(f"Elastic IP address {address['ip']} "
                  "disassociated and released.")
        else:
            print(f"Elastic IP address {address['ip']} released.")
Exemplo n.º 17
0
 def _create_region_key_pair(self, region, public_key_bytes):
     """create EC2 key pair in region and return public key fingerprint"""
     return aws.ec2_client(region).import_key_pair(
         KeyName=self._key_pair_name,
         PublicKeyMaterial=public_key_bytes)['KeyFingerprint']
Exemplo n.º 18
0
 def _delete_vpc_sgs(region, vpc_id):
     """delete VPC's security group(s) from AWS region"""
     ec2_client = aws.ec2_client(region)
     aws_sgs = aws.get_vpc_security_groups(region, vpc_id)
     for aws_sg in aws_sgs:
         ec2_client.delete_security_group(GroupId=aws_sg['GroupId'])
Exemplo n.º 19
0
 def _delete_region_key_pair(self, region):
     """delete namespace EC2 key pair from region"""
     if self._region_namespace_key_fingerprint(region) is not None:
         aws.ec2_client(region).delete_key_pair(KeyName=self._key_pair_name)
         return True
     return False
Exemplo n.º 20
0
 def __init__(self, cmd_args):
     self._ec2_client = aws.ec2_client(cmd_args.region)