示例#1
0
    def test_destroy_network_interfaces_(self):
        """Test destroying network interfaces"""
        vpc = DiscoVPC('auto-vpc', 'auto-vpc-type', vpc={
            'CidrBlock': '10.0.0.0/28',
            'VpcId': 'mock_vpc_id'
        })

        vpc.boto3_ec2.describe_network_interfaces = MagicMock(return_value={'NetworkInterfaces': [{
            'NetworkInterfaceId': 'net-1',
            'Attachment': {
                'AttachmentId': 'attach-1234'
            }
        }, {
            'NetworkInterfaceId': 'net-2'
        }]})

        vpc.boto3_ec2.detach_network_interface = MagicMock()
        vpc.boto3_ec2.delete_network_interface = MagicMock()

        vpc._destroy_interfaces()

        vpc.boto3_ec2.detach_network_interface.assert_called_once_with(
            AttachmentId='attach-1234',
            Force=True
        )
        vpc.boto3_ec2.delete_network_interface.assert_has_calls([
            call(NetworkInterfaceId='net-1'),
            call(NetworkInterfaceId='net-2')
        ])
示例#2
0
    def test_destroy_network_interfaces_(self):
        """Test destroying network interfaces"""
        vpc = DiscoVPC('auto-vpc',
                       'auto-vpc-type',
                       vpc={
                           'CidrBlock': '10.0.0.0/28',
                           'VpcId': 'mock_vpc_id'
                       })

        vpc.boto3_ec2.describe_network_interfaces = MagicMock(
            return_value={
                'NetworkInterfaces': [{
                    'NetworkInterfaceId': 'net-1',
                    'Attachment': {
                        'AttachmentId': 'attach-1234'
                    }
                }, {
                    'NetworkInterfaceId': 'net-2'
                }]
            })

        vpc.boto3_ec2.detach_network_interface = MagicMock()
        vpc.boto3_ec2.delete_network_interface = MagicMock()

        vpc._destroy_interfaces()

        vpc.boto3_ec2.detach_network_interface.assert_called_once_with(
            AttachmentId='attach-1234', Force=True)
        vpc.boto3_ec2.delete_network_interface.assert_has_calls([
            call(NetworkInterfaceId='net-1'),
            call(NetworkInterfaceId='net-2')
        ])
示例#3
0
    def test_create_meta_networks_static_dynamic(self, meta_network_mock, config_mock, endpoints_mock):
        """Test creating meta networks with a mix of static and dynamic ip ranges"""
        vpc_mock = {'CidrBlock': '10.0.0.0/28',
                    'VpcId': 'mock_vpc_id',
                    'DhcpOptionsId': 'mock_dhcp_options_id'}

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'vpc_cidr': '10.0.0.0/28',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': '10.0.0.4/31',
                'maintenance_cidr': 'auto'
            }
        })

        def _create_meta_network_mock(network_name, vpc, cidr):
            ret = MagicMock()
            ret.name = network_name
            ret.vpc = vpc
            ret.network_cidr = cidr

            return ret

        meta_network_mock.side_effect = _create_meta_network_mock

        auto_vpc = DiscoVPC('auto-vpc', 'auto-vpc-type', vpc_mock)

        meta_networks = auto_vpc._create_new_meta_networks()
        self.assertItemsEqual(['intranet', 'tunnel', 'dmz', 'maintenance'], meta_networks.keys())

        expected_ip_ranges = ['10.0.0.0/30', '10.0.0.4/31', '10.0.0.8/30', '10.0.0.12/30']
        actual_ip_ranges = [str(meta_network.network_cidr) for meta_network in meta_networks.values()]

        self.assertItemsEqual(actual_ip_ranges, expected_ip_ranges)
示例#4
0
def create_vpc_command(args):
    """ handle vpc create command actions"""
    if DiscoVPC.fetch_environment(environment_name=args.vpc_name):
        logging.error("VPC with same name already exists.")
        sys.exit(1)
    else:
        vpc = DiscoVPC(args.vpc_name, args.vpc_type)
        logging.info("VPC %s(%s) has been created", args.vpc_name, vpc.vpc.id)
示例#5
0
    def setUp(self):
        mock_ec2().start()

        self.disco_vpc1 = DiscoVPC('mock-vpc-1', 'sandbox')
        self.disco_vpc2 = DiscoVPC('mock-vpc-2', 'sandbox')
        self.disco_vpc3 = DiscoVPC('mock-vpc-3', 'sandbox')

        self.client = boto3.client('ec2')

        self.disco_vpc_peerings = DiscoVPCPeerings()
    def setUp(self):
        mock_ec2().start()

        self.disco_vpc1 = DiscoVPC('mock-vpc-1', 'sandbox')
        self.disco_vpc2 = DiscoVPC('mock-vpc-2', 'sandbox')
        self.disco_vpc3 = DiscoVPC('mock-vpc-3', 'sandbox')

        self.client = boto3.client('ec2')

        self.disco_vpc_peerings = DiscoVPCPeerings()
示例#7
0
def create_vpc_command(args):
    """ handle vpc create command actions"""
    if DiscoVPC.fetch_environment(environment_name=args.vpc_name):
        print("VPC with same name already exists.")
        sys.exit(1)
    else:
        tags = tag2dict(key_values_to_tags(args.tags)) if args.tags else None
        vpc = DiscoVPC(args.vpc_name, args.vpc_type, skip_enis_pre_allocate=args.skip_enis,
                       vpc_tags=tags)
        print("VPC {0}({1}) has been created".format(args.vpc_name, vpc.get_vpc_id()))
示例#8
0
def create_vpc_command(args):
    """ handle vpc create command actions"""
    if DiscoVPC.fetch_environment(environment_name=args.vpc_name):
        print("VPC with same name already exists.")
        sys.exit(1)
    else:
        tags = key_values_to_tags(args.tags) if args.tags else None
        vpc = DiscoVPC(args.vpc_name, args.vpc_type, skip_enis_pre_allocate=args.skip_enis,
                       vpc_tags=tags)
        print("VPC {0}({1}) has been created".format(args.vpc_name, vpc.get_vpc_id()))
示例#9
0
def update_vpc_command(args):
    """ handle vpc update command actions"""
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    else:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    if vpc:
        vpc.update(args.dry_run)
    else:
        print("No matching VPC found")
        sys.exit(2)
示例#10
0
def destroy_vpc_command(args):
    """ handle vpc destroy command actions"""
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    else:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    if vpc:
        vpc.destroy()
    else:
        print("No matching VPC found")
        sys.exit(2)
示例#11
0
def update_vpc_command(args):
    """ handle vpc update command actions"""
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    else:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    if vpc:
        vpc.update(args.dry_run)
    else:
        print("No matching VPC found")
        sys.exit(2)
示例#12
0
def destroy_vpc_command(args):
    """ handle vpc destroy command actions"""
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    else:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    if vpc:
        vpc.destroy()
    else:
        print("No matching VPC found")
        sys.exit(2)
示例#13
0
def proxy_peerings_command(args):
    """ handle peerins command actions"""
    if args.vpc_name and args.vpc_id:
        logging.error("Don't use vpc_name and vpc_id at the same time.")
        sys.exit(2)

    if args.vpc_name:
        vpc_id = DiscoVPC.find_vpc_id_by_name(args.vpc_name)
    elif args.vpc_id:
        vpc_id = args.vpc_id
    else:
        vpc_id = None

    if args.list_peerings:
        vpc_map = {vpc.id: vpc for vpc in DiscoVPC.list_vpcs()}
        peerings = sorted(DiscoVPC.list_peerings(vpc_id, include_failed=True),
                          key=lambda p: vpc_map.get(p.accepter_vpc_info.vpc_id)
                          .tags.get("Name"))

        for peering in peerings:
            vpc1 = vpc_map.get(peering.accepter_vpc_info.vpc_id)
            vpc2 = vpc_map.get(peering.requester_vpc_info.vpc_id)

            line = u"{0:<14} {1:<8} {2:<20} {3:<21}".format(
                peering.id, peering.status_code,
                "{}<->{}".format(vpc1.tags.get("Name"), vpc2.tags.get("Name")),
                "{}<->{}".format(peering.accepter_vpc_info.cidr_block,
                                 peering.requester_vpc_info.cidr_block))
            print(line)
    elif args.delete_peerings:
        DiscoVPC.delete_peerings(vpc_id)
    elif args.create_peerings:
        peering_configs = DiscoVPC.parse_peerings_config(vpc_id)
        DiscoVPC.create_peering_connections(peering_configs)
示例#14
0
def proxy_peerings_command(args):
    """ handle peerins command actions"""
    if args.vpc_name and args.vpc_id:
        logging.error("Don't use vpc_name and vpc_id at the same time.")
        sys.exit(2)

    if args.vpc_name:
        vpc_id = DiscoVPC.find_vpc_id_by_name(args.vpc_name)
    elif args.vpc_id:
        vpc_id = args.vpc_id
    else:
        vpc_id = None

    if args.list_peerings:
        vpc_map = {vpc.id: vpc for vpc in DiscoVPC.list_vpcs()}
        peerings = sorted(
            DiscoVPC.list_peerings(vpc_id, include_failed=True),
            key=lambda p: vpc_map.get(p.accepter_vpc_info.vpc_id).tags.get("Name"))

        for peering in peerings:
            vpc1 = vpc_map.get(peering.accepter_vpc_info.vpc_id)
            vpc2 = vpc_map.get(peering.requester_vpc_info.vpc_id)

            line = u"{0:<14} {1:<8} {2:<20} {3:<21}".format(
                peering.id, peering.status_code, "{}<->{}".format(
                    vpc1.tags.get("Name"), vpc2.tags.get("Name")),
                "{}<->{}".format(
                    peering.accepter_vpc_info.cidr_block,
                    peering.requester_vpc_info.cidr_block))
            print(line)
    elif args.delete_peerings:
        DiscoVPC.delete_peerings(vpc_id)
    elif args.create_peerings:
        peering_configs = DiscoVPC.parse_peerings_config(vpc_id)
        DiscoVPC.create_peering_connections(peering_configs)
示例#15
0
def list_vpc_command(args):
    """ handle list vpcs command actions """
    for vpc_env in DiscoVPC.list_vpcs():
        line = u"{0}\t{1:<15}".format(vpc_env['id'], vpc_env['tags'].get("Name", "-"))
        if args.env_type:
            line += u"\t{0}".format(vpc_env['tags'].get("type", "-"))
        print(line)
示例#16
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    aws = DiscoAWS(config, env)
    disco_elasticache = DiscoElastiCache(vpc, aws=aws)

    if args['list']:
        for cluster in disco_elasticache.list():
            size = 'N/A'
            if cluster['Status'] == 'available':
                size = len(cluster['NodeGroups'][0]['NodeGroupMembers'])
            print("{0:<25} {1:5} {2:>5}".format(cluster['Description'],
                                                cluster['Status'],
                                                size))
    elif args['update']:
        if args['--cluster']:
            disco_elasticache.update(args['--cluster'])
        else:
            disco_elasticache.update_all()

    elif args['delete']:
        disco_elasticache.delete(args['--cluster'], wait=args['--wait'])
示例#17
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    parser = get_parser()
    args = parser.parse_args()
    configure_logging(args.debug, args.silent)

    bucket_name = args.bucket or DiscoVPC.get_credential_buckets_from_env_name(
        config, args.env)[0]
    s3_bucket = DiscoS3Bucket(bucket_name)

    if args.mode == "list":
        print("\n".join(s3_bucket.listkeys(args.prefix)))
    elif args.mode == "get":
        print(s3_bucket.get_key(args.key_name))
    elif args.mode == "set":
        use_password = args.key_password
        key_value = args.key_value
        if use_password:
            key_value = getpass.getpass()
        elif key_value == "-":
            key_value = sys.stdin.read()
        s3_bucket.set_key(args.key_name, key_value)
    elif args.mode == "delete":
        s3_bucket.delete_key(args.key_name)
    elif args.mode == "setfile":
        key_value = s3_bucket.get_key(args.key_name)
        s3_bucket.get_contents_to_file(args.key_name, args.file_name)
示例#18
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    aws = DiscoAWS(config, env)
    disco_elasticache = DiscoElastiCache(vpc, aws=aws)

    if args['list']:
        for cluster in disco_elasticache.list():
            size = 'N/A'
            if cluster['Status'] == 'available':
                size = len(cluster['NodeGroups'][0]['NodeGroupMembers'])
            print("{0:<25} {1:5} {2:>5}".format(cluster['Description'],
                                                cluster['Status'], size))
    elif args['update']:
        if args['--cluster']:
            disco_elasticache.update(args['--cluster'])
        else:
            disco_elasticache.update_all()

    elif args['delete']:
        disco_elasticache.delete(args['--cluster'], wait=args['--wait'])
示例#19
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    if args['list']:
        format_string = "{0:<50} {1:33} {2}"
        print(format_string.format("ELB Name", "Availability Zones", "ELB Id"),
              file=sys.stderr)
        for elb_info in sorted(DiscoELB(vpc).list_for_display()):
            print(
                format_string.format(elb_info['elb_name'],
                                     elb_info['availability_zones'],
                                     elb_info["elb_id"]))
    elif args['update']:
        DiscoAWS(config, env).update_elb(args['--hostclass'])
示例#20
0
def list_vpc_command(args):
    """ handle list vpcs command actions """
    for vpc_env in DiscoVPC.list_vpcs():
        line = u"{0}\t{1:<15}".format(vpc_env['id'], vpc_env['tags'].get("Name", "-"))
        if args.env_type:
            line += u"\t{0}".format(vpc_env['tags'].get("type", "-"))
        print(line)
示例#21
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    parser = get_parser()
    args = parser.parse_args()
    configure_logging(args.debug)

    bucket_name = args.bucket or DiscoVPC.get_credential_buckets_from_env_name(config, args.env)[0]
    s3_bucket = DiscoS3Bucket(bucket_name)

    if args.mode == "list":
        print("\n".join(s3_bucket.listkeys(args.prefix)))
    elif args.mode == "get":
        print(s3_bucket.get_key(args.key_name))
    elif args.mode == "set":
        use_password = args.key_password
        key_value = args.key_value
        if use_password:
            key_value = getpass.getpass()
        elif key_value == "-":
            key_value = sys.stdin.read()
        s3_bucket.set_key(args.key_name, key_value)
    elif args.mode == "delete":
        s3_bucket.delete_key(args.key_name)
    elif args.mode == "setfile":
        key_value = s3_bucket.get_key(args.key_name)
        s3_bucket.get_contents_to_file(args.key_name, args.file_name)
示例#22
0
def create_vpc_command(args):
    """ handle vpc create command actions"""
    if DiscoVPC.fetch_environment(environment_name=args.vpc_name):
        logging.error("VPC with same name already exists.")
        sys.exit(1)
    else:
        vpc = DiscoVPC(args.vpc_name, args.vpc_type)
        logging.info("VPC %s(%s) has been created", args.vpc_name, vpc.vpc.id)
示例#23
0
    def test_create_meta_networks_static_dynamic(self, meta_network_mock,
                                                 config_mock, endpoints_mock):
        """Test creating meta networks with a mix of static and dynamic ip ranges"""
        vpc_mock = {
            'CidrBlock': '10.0.0.0/28',
            'VpcId': 'mock_vpc_id',
            'DhcpOptionsId': 'mock_dhcp_options_id'
        }

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'vpc_cidr': '10.0.0.0/28',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': '10.0.0.4/31',
                'maintenance_cidr': 'auto'
            }
        })

        def _create_meta_network_mock(network_name, vpc, cidr):
            ret = MagicMock()
            ret.name = network_name
            ret.vpc = vpc
            ret.network_cidr = cidr

            return ret

        meta_network_mock.side_effect = _create_meta_network_mock

        auto_vpc = DiscoVPC('auto-vpc', 'auto-vpc-type', vpc_mock)

        meta_networks = auto_vpc._create_new_meta_networks()
        self.assertItemsEqual(['intranet', 'tunnel', 'dmz', 'maintenance'],
                              meta_networks.keys())

        expected_ip_ranges = [
            '10.0.0.0/30', '10.0.0.4/31', '10.0.0.8/30', '10.0.0.12/30'
        ]
        actual_ip_ranges = [
            str(meta_network.network_cidr)
            for meta_network in meta_networks.values()
        ]

        self.assertItemsEqual(actual_ip_ranges, expected_ip_ranges)
示例#24
0
def proxy_peerings_command(args):
    """ handle peerings command actions"""
    if args.vpc_name and args.vpc_id:
        print("Don't use vpc_name and vpc_id at the same time.")
        sys.exit(2)

    vpc = None
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    elif args.vpc_id:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    vpc_id = vpc.get_vpc_id() if vpc else None

    disco_peerings = DiscoVPCPeerings()

    if args.list_peerings:
        vpc_map = {vpc['id']: vpc for vpc in DiscoVPC.list_vpcs()}
        peerings = sorted(
            disco_peerings.list_peerings(vpc_id, include_failed=True),
            key=lambda p: vpc_map.get(p['AccepterVpcInfo']['VpcId'])['tags'].get("Name"))

        for peering in peerings:

            vpc1 = vpc_map.get(peering['AccepterVpcInfo']['VpcId'])
            vpc2 = vpc_map.get(peering['RequesterVpcInfo']['VpcId'])

            line = u"{0:<14} {1:<8} {2:<20} {3:<21}".format(
                peering['VpcPeeringConnectionId'], peering['Status']['Code'], "{}<->{}".format(
                    vpc1['tags'].get("Name") if vpc1 is not None else "",
                    vpc2['tags'].get("Name") if vpc2 is not None else ""),
                "{}<->{}".format(
                    peering['AccepterVpcInfo'].get('CidrBlock'),
                    peering['RequesterVpcInfo'].get('CidrBlock')))
            print(line)
    elif args.delete_peerings:
        disco_peerings.delete_peerings(vpc_id)
    elif args.create_peerings:
        disco_peerings.update_peering_connections(vpc)
示例#25
0
def proxy_peerings_command(args):
    """ handle peerings command actions"""
    if args.vpc_name and args.vpc_id:
        print("Don't use vpc_name and vpc_id at the same time.")
        sys.exit(2)

    vpc = None
    if args.vpc_name:
        vpc = DiscoVPC.fetch_environment(environment_name=args.vpc_name)
    elif args.vpc_id:
        vpc = DiscoVPC.fetch_environment(vpc_id=args.vpc_id)

    vpc_id = vpc.get_vpc_id() if vpc else None

    disco_peerings = DiscoVPCPeerings()

    if args.list_peerings:
        vpc_map = {vpc['id']: vpc for vpc in DiscoVPC.list_vpcs()}
        peerings = sorted(
            disco_peerings.list_peerings(vpc_id, include_failed=True),
            key=lambda p: vpc_map.get(p['AccepterVpcInfo']['VpcId'])['tags'].get("Name"))

        for peering in peerings:

            vpc1 = vpc_map.get(peering['AccepterVpcInfo']['VpcId'])
            vpc2 = vpc_map.get(peering['RequesterVpcInfo']['VpcId'])

            line = u"{0:<14} {1:<8} {2:<20} {3:<21}".format(
                peering['VpcPeeringConnectionId'], peering['Status']['Code'], "{}<->{}".format(
                    vpc1['tags'].get("Name") if vpc1 is not None else "",
                    vpc2['tags'].get("Name") if vpc2 is not None else ""),
                "{}<->{}".format(
                    peering['AccepterVpcInfo'].get('CidrBlock'),
                    peering['RequesterVpcInfo'].get('CidrBlock')))
            print(line)
    elif args.delete_peerings:
        disco_peerings.delete_peerings(vpc_id)
    elif args.create_peerings:
        disco_peerings.update_peering_connections(vpc)
示例#26
0
    def test_reserve_hostclass_ip_addresses(self, meta_network_mock,
                                            boto3_resource_mock,
                                            boto3_client_mock, config_mock,
                                            sleep_mock, gateways_mock,
                                            sns_mock, endpoints_mock,
                                            rds_mock):
        """Test hostclass IP addresses are being reserved during VPC creation"""

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'ip_space': '10.0.0.0/24',
                'vpc_cidr_size': '26',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': 'auto',
                'maintenance_cidr': 'auto',
                'ntp_server': '10.0.0.5'
            }
        })

        # pylint: disable=C0103
        def _create_vpc_mock(CidrBlock):
            return {
                'Vpc': {
                    'CidrBlock': CidrBlock,
                    'VpcId': 'mock_vpc_id',
                    'DhcpOptionsId': 'mock_dhcp_options_id'
                }
            }

        client_mock = MagicMock()
        client_mock.create_vpc.side_effect = _create_vpc_mock
        client_mock.get_all_zones.return_value = [MagicMock()]
        client_mock.describe_dhcp_options.return_value = {
            'DhcpOptions': [MagicMock()]
        }
        boto3_client_mock.return_value = client_mock
        network_mock = MagicMock()
        meta_network_mock.return_value = network_mock

        DiscoVPC('auto-vpc', 'auto-vpc-type', aws_config=get_mock_config())

        expected_calls = []
        default_config = get_default_config_dict()
        for section in default_config:
            if section.startswith("mhc") and default_config[section].get(
                    "ip_address"):
                expected_calls.append(
                    call(default_config[section].get("ip_address")))
        network_mock.get_interface.assert_has_calls(expected_calls)
示例#27
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    parser = get_parser()
    args = parser.parse_args()
    configure_logging(args.debug)

    s3_bucket_name = args.bucket or DiscoVPC.get_credential_buckets_from_env_name(config, args.env)[0]
    app_auth_dir = args.dir or None
    env = args.env or s3_bucket_name.split('.')[-1]

    if args.mode == "update":
        app_auth = DiscoAppAuth(env, s3_bucket_name, app_auth_dir)
        app_auth.update(args.force)
示例#28
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    parser = get_parser()
    args = parser.parse_args()
    configure_logging(args.debug)

    s3_bucket_name = args.bucket or DiscoVPC.get_credential_buckets_from_env_name(config, args.env)[0]
    app_auth_dir = args.dir or None
    env = args.env or s3_bucket_name.split('.')[-1]

    if args.mode == "update":
        app_auth = DiscoAppAuth(env, s3_bucket_name, app_auth_dir)
        app_auth.update(args.force)
示例#29
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    args = docopt(__doc__)

    configure_logging(args["--debug"])

    if args["hashpassword"]:
        print(password_hash())
        sys.exit(0)

    bucket_name = args.get(
        "--bucket") or DiscoVPC.get_credential_buckets_from_env_name(
            config, args["--env"])[0]
    s3_accounts = S3AccountBackend(DiscoS3Bucket(bucket_name))

    if args["install"]:
        s3_accounts.install_all()
    elif args["adduser"]:
        username = args["--name"] or os.environ.get("USER")
        user_template = s3_accounts.new_user_config(
            password_hash(args["--password"]))
        group_config = s3_accounts.new_group_config()
        user_config = s3_accounts.edit_account_config(user_template)
        s3_accounts.add_account(username, user_config)
        s3_accounts.add_account(username, group_config)
    elif args["addgroup"]:
        group_config = s3_accounts.new_group_config()
        s3_accounts.add_account(args["--name"], group_config)
    elif args["edituser"]:
        username = args["--name"] or os.environ.get("USER")
        user_config = s3_accounts.get_user_config(username)
        kwargs = {"active": args["--active"]} if args["--active"] else {}
        user_config = s3_accounts.edit_account_config(user_config, **kwargs)
        s3_accounts.add_account(username, user_config)
        s3_accounts.refresh_groups()
    elif args["editgroup"]:
        # there is nothing to edit for a group.. but..
        group_config = s3_accounts.get_group_config(args["--name"])
        group_config = s3_accounts.edit_account_config(group_config)
        s3_accounts.add_account(args["--name"], group_config)
    elif args["listgroups"]:
        print("\n".join(s3_accounts.list_groups()))
    elif args["listusers"]:
        print("\n".join(s3_accounts.list_users()))
示例#30
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    args = docopt(__doc__)

    configure_logging(args["--debug"])

    if args["hashpassword"]:
        print(password_hash())
        sys.exit(0)

    bucket_name = args.get("--bucket") or DiscoVPC.get_credential_buckets_from_env_name(
        config, args["--env"])[0]
    s3_accounts = S3AccountBackend(DiscoS3Bucket(bucket_name))

    if args["install"]:
        s3_accounts.install_all()
    elif args["adduser"]:
        username = args["--name"] or os.environ.get("USER")
        user_template = s3_accounts.new_user_config(password_hash(args["--password"]))
        group_config = s3_accounts.new_group_config()
        user_config = s3_accounts.edit_account_config(user_template)
        s3_accounts.add_account(username, user_config)
        s3_accounts.add_account(username, group_config)
    elif args["addgroup"]:
        group_config = s3_accounts.new_group_config()
        s3_accounts.add_account(args["--name"], group_config)
    elif args["edituser"]:
        username = args["--name"] or os.environ.get("USER")
        user_config = s3_accounts.get_user_config(username)
        kwargs = {"active": args["--active"]} if args["--active"] else {}
        user_config = s3_accounts.edit_account_config(user_config, **kwargs)
        s3_accounts.add_account(username, user_config)
        s3_accounts.refresh_groups()
    elif args["editgroup"]:
        # there is nothing to edit for a group.. but..
        group_config = s3_accounts.get_group_config(args["--name"])
        group_config = s3_accounts.edit_account_config(group_config)
        s3_accounts.add_account(args["--name"], group_config)
    elif args["listgroups"]:
        print("\n".join(s3_accounts.list_groups()))
    elif args["listusers"]:
        print("\n".join(s3_accounts.list_users()))
示例#31
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    if args['list']:
        for elb in sorted(DiscoELB(vpc).list()):
            print("{0:<20} {1:25}".format(elb['LoadBalancerName'], ','.join(elb['AvailabilityZones'])))
    elif args['update']:
        DiscoAWS(config, env).update_elb(args['--hostclass'])
示例#32
0
    def test_create_auto_vpc(self, meta_network_mock, boto3_resource_mock,
                             boto3_client_mock, config_mock, sleep_mock,
                             gateways_mock, sns_mock, endpoints_mock,
                             rds_mock):
        """Test creating a VPC with a dynamic ip range"""
        # FIXME This needs to mock way too many things. DiscoVPC needs to be refactored

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'ip_space': '10.0.0.0/24',
                'vpc_cidr_size': '26',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': 'auto',
                'maintenance_cidr': 'auto',
                'ntp_server': '10.0.0.5'
            }
        })

        # pylint: disable=C0103
        def _create_vpc_mock(CidrBlock):
            return {
                'Vpc': {
                    'CidrBlock': CidrBlock,
                    'VpcId': 'mock_vpc_id',
                    'DhcpOptionsId': 'mock_dhcp_options_id'
                }
            }

        client_mock = MagicMock()
        client_mock.create_vpc.side_effect = _create_vpc_mock
        client_mock.get_all_zones.return_value = [MagicMock()]
        client_mock.describe_dhcp_options.return_value = {
            'DhcpOptions': [MagicMock()]
        }
        boto3_client_mock.return_value = client_mock

        auto_vpc = DiscoVPC('auto-vpc', 'auto-vpc-type')

        possible_vpcs = [
            '10.0.0.0/26', '10.0.0.64/26', '10.0.0.128/26', '10.0.0.192/26'
        ]
        self.assertIn(str(auto_vpc.vpc['CidrBlock']), possible_vpcs)
示例#33
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    if args['list']:
        for elb in sorted(DiscoELB(vpc).list()):
            print("{0:<20} {1:25}".format(elb['LoadBalancerName'],
                                          ','.join(elb['AvailabilityZones'])))
    elif args['update']:
        DiscoAWS(config, env).update_elb(args['--hostclass'])
示例#34
0
def run():
    """Parses command line and dispatches the commands"""
    args = docopt(__doc__)

    configure_logging(args["--debug"])

    config = read_config()

    env = args.get("--env") or config.get("disco_aws", "default_environment")
    vpc = DiscoVPC.fetch_environment(environment_name=env)
    if not vpc:
        print("Environment does not exist: {}".format(env))
        sys.exit(1)

    if args['list']:
        format_string = "{0:<50} {1:33} {2}"
        print(format_string.format("ELB Name", "Availability Zones", "ELB Id"), file=sys.stderr)
        for elb_info in sorted(DiscoELB(vpc).list_for_display()):
            print(format_string.format(elb_info['elb_name'], elb_info['availability_zones'],
                                       elb_info["elb_id"]))
    elif args['update']:
        DiscoAWS(config, env).update_elb(args['--hostclass'])
class DiscoVPCPeeringsTests(unittest.TestCase):
    """Test DiscoVPCPeerings"""

    @patch("disco_aws_automation.disco_vpc.DiscoSNS", MagicMock())
    @patch("disco_aws_automation.disco_vpc.DiscoRDS", MagicMock())
    @patch("disco_aws_automation.disco_vpc.DiscoVPCEndpoints", MagicMock())
    def setUp(self):
        mock_ec2().start()

        self.disco_vpc1 = DiscoVPC('mock-vpc-1', 'sandbox')
        self.disco_vpc2 = DiscoVPC('mock-vpc-2', 'sandbox')
        self.disco_vpc3 = DiscoVPC('mock-vpc-3', 'sandbox')

        self.client = boto3.client('ec2')

        self.disco_vpc_peerings = DiscoVPCPeerings()

    @patch('disco_aws_automation.disco_vpc.DiscoMetaNetwork.create_peering_route')
    @patch('disco_aws_automation.disco_vpc_peerings.read_config')
    def test_update_peering_connections(self, config_mock, create_peering_route_mock):
        """ Verify new peering connections are created properly """

        config_mock.return_value = get_mock_config({
            'peerings': {
                'connection_1': 'mock-vpc-1:sandbox/intranet mock-vpc-2:sandbox/intranet'
            }
        })

        # End setting up test

        # Calling method under test
        self.disco_vpc_peerings.update_peering_connections(self.disco_vpc1)

        # Asserting correct behavior

        peeerings = self.client.describe_vpc_peering_connections().get('VpcPeeringConnections')

        self.assertEqual(1, len(peeerings))

        peering_id = peeerings[0]['VpcPeeringConnectionId']

        self.assertEqual(self.disco_vpc1.get_vpc_id(), peeerings[0]['RequesterVpcInfo']['VpcId'])
        self.assertEqual(self.disco_vpc2.get_vpc_id(), peeerings[0]['AccepterVpcInfo']['VpcId'])

        # create_peering_route should have been called twice, once for each VPC
        create_peering_route_mock.assert_called_with(peering_id, '10.101.0.0/20')
        self.assertEqual(2, create_peering_route_mock.call_count)

    def test_parse_peering_connection(self):
        """test parsing a peering connection line with wildcards"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            'mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'
        )

        expected = [
            PeeringConnection.from_peering_line('mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
        ]

        self.assertItemsEqual(actual, expected)

    def test_parse_peering_connection_wildcards(self):
        """test parsing a peering connection line with wildcards"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            '*:sandbox/intranet mock-vpc-3:sandbox/intranet'
        )

        expected = [
            PeeringConnection.from_peering_line('mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
            PeeringConnection.from_peering_line('mock-vpc-2:sandbox/intranet mock-vpc-3:sandbox/intranet')
        ]

        self.assertItemsEqual(actual, expected)

    def test_parse_peering_double_wildcards(self):
        """test parsing a peering connection line with wildcards on both sides"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            '*:sandbox/intranet *:sandbox/intranet'
        )

        expected = [
            PeeringConnection.from_peering_line('mock-vpc-1:sandbox/intranet mock-vpc-2:sandbox/intranet'),
            PeeringConnection.from_peering_line('mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
            PeeringConnection.from_peering_line('mock-vpc-2:sandbox/intranet mock-vpc-3:sandbox/intranet')
        ]

        self.assertItemsEqual(actual, expected)
示例#36
0
def run():
    """Parses command line and dispatches the commands"""
    config = read_config()

    args = docopt(__doc__)

    configure_logging(args["--debug"])

    env = args["--environment"] or config.get("disco_aws",
                                              "default_environment")

    force_deployable = None if args["--deployable"] is None else is_truthy(
        args["--deployable"])

    pipeline_definition = []
    if args["--pipeline"]:
        with open(args["--pipeline"], "r") as f:
            reader = csv.DictReader(f)
            pipeline_definition = [line for line in reader]

    aws = DiscoAWS(config, env)

    if config.has_option('test', 'env'):
        test_env = config.get('test', 'env')
        test_aws = DiscoAWS(config, test_env)
    else:
        test_aws = aws

    bake = DiscoBake(config, aws.connection)

    if args["--ami"] and args["--hostclass"]:
        image = bake.get_image(args["--ami"])
        if args["--hostclass"] != bake.ami_hostclass(image):
            logger.error('AMI %s does not belong to hostclass %s',
                         args["--ami"], args["--hostclass"])
            sys.exit(1)

    vpc = DiscoVPC.fetch_environment(environment_name=env)

    deploy = DiscoDeploy(aws,
                         test_aws,
                         bake,
                         DiscoGroup(env),
                         DiscoELB(vpc),
                         DiscoSSM(environment_name=env),
                         pipeline_definition=pipeline_definition,
                         ami=args.get("--ami"),
                         hostclass=args.get("--hostclass"),
                         allow_any_hostclass=args["--allow-any-hostclass"])

    if args["test"]:
        try:
            deploy.test(dry_run=args["--dry-run"],
                        deployment_strategy=args["--strategy"],
                        ticket_id=args["--ticket"],
                        force_deployable=force_deployable)
        except RuntimeError as err:
            logger.error(str(err))
            sys.exit(1)
    elif args["update"]:
        try:
            deploy.update(dry_run=args["--dry-run"],
                          deployment_strategy=args["--strategy"],
                          ticket_id=args["--ticket"],
                          force_deployable=force_deployable)
        except RuntimeError as err:
            logger.error(str(err))
            sys.exit(1)
    elif args["list"]:
        missing = "-" if pipeline_definition else ""
        if args["--tested"]:
            for (_hostclass,
                 ami) in deploy.get_latest_tested_amis().iteritems():
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
        elif args["--untested"]:
            for (_hostclass,
                 ami) in deploy.get_latest_untested_amis().iteritems():
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
        elif args["--failed"]:
            for (_hostclass,
                 ami) in deploy.get_latest_failed_amis().iteritems():
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
        elif args["--testable"]:
            for ami in deploy.get_test_amis():
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
        elif args["--updatable"]:
            for ami in deploy.get_update_amis():
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
        elif args["--failures"]:
            failures = deploy.get_failed_amis()
            for ami in failures:
                print("{} {:40} {}".format(
                    ami.id,
                    ami.name.split()[0],
                    deploy.get_integration_test(ami.name.split()[0])
                    or missing))
            sys.exit(1 if failures else 0)
示例#37
0
    def test_create_vpc_with_custom_tags(self, boto3_resource_mock,
                                         boto3_client_mock, config_mock,
                                         endpoints_mock, sns_mock, rds_mock):
        """Test creating a VPC with a dynamic ip range and tags"""
        # FIXME This needs to mock way too many things. DiscoVPC needs to be refactored

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'ip_space': '10.0.0.0/24',
                'vpc_cidr_size': '26',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': 'auto',
                'maintenance_cidr': 'auto',
                'ntp_server': '10.0.0.5',
                'application': 'test'
            }
        })

        # pylint: disable=C0103
        def _create_vpc_mock(CidrBlock):
            return {
                'Vpc': {
                    'CidrBlock': CidrBlock,
                    'VpcId': 'mock_vpc_id',
                    'DhcpOptionsId': 'mock_dhcp_options_id'
                }
            }

        client_mock = MagicMock()
        client_mock.create_vpc.side_effect = _create_vpc_mock
        boto3_client_mock.return_value = client_mock

        resource_mock = MagicMock()
        resource_mock.Vpc.create_tags.return_value = []
        boto3_resource_mock.return_value = resource_mock

        client_mock.describe_vpn_gateways.return_value = {'VpnGateways': []}

        my_tags_options = {'productline': 'astronauts', 'mytag': 'tag_value'}
        DiscoVPC._get_vpc_cidr = MagicMock()
        DiscoVPC._get_vpc_cidr.return_value = '10.0.0.0/26'
        with patch("disco_aws_automation.DiscoVPC._create_new_meta_networks",
                   return_value=MagicMock(return_value={})):
            with patch("disco_aws_automation.DiscoVPC._update_dhcp_options",
                       return_value=None):
                # The expect list of tag dictionaries
                expected_vpc_tags = [{
                    'Value': 'auto-vpc',
                    'Key': 'Name'
                }, {
                    'Value': 'auto-vpc-type',
                    'Key': 'type'
                }, {
                    'Value': 'ANY',
                    'Key': 'create_date'
                }, {
                    'Value': 'astronauts',
                    'Key': 'productline'
                }, {
                    'Value': 'tag_value',
                    'Key': 'mytag'
                }, {
                    'Value': 'test',
                    'Key': 'application'
                }]

                DiscoVPC('auto-vpc', 'auto-vpc-type', vpc_tags=my_tags_options)
                # Get the create_tags argument
                call_args_tags = resource_mock.Vpc.return_value.create_tags.call_args[
                    1]
                # Verify Option Name
                self.assertEqual(['Tags'], call_args_tags.keys())
                call_tags_dict = call_args_tags['Tags']
                # Verify the number of tag Dictionaries in the list
                self.assertEqual(6, len(call_tags_dict))
                # Verify each tag options
                for tag_option in call_tags_dict:
                    if tag_option['Key'] == 'create_date':
                        tag_option['Value'] = 'ANY'
                    self.assertIn(tag_option, expected_vpc_tags)
示例#38
0
    def test_create_vpc_ntp_names(self, meta_network_mock, boto3_resource_mock,
                                  boto3_client_mock, config_mock, sleep_mock,
                                  gateways_mock, sns_mock, endpoints_mock,
                                  rds_mock, gethostbyname_mock):
        """Test creating VPC with NTP server names"""
        # FIXME This needs to mock way too many things. DiscoVPC needs to be refactored

        local_dict = {
            'dhcp_options_created': False,
            'ntp_servers_dict': {
                '0.mock.ntp.server': '100.10.10.10',
                '1.mock.ntp.server': '100.10.10.11',
                '2.mock.ntp.server': '100.10.10.12'
            },
            'new_mock_dhcp_options_id': 'new_mock_dhcp_options_id',
            'mock_vpc_id': 'mock_vpc_id'
        }

        config_mock.return_value = get_mock_config({
            'envtype:auto-vpc-type': {
                'ip_space': '10.0.0.0/24',
                'vpc_cidr_size': '26',
                'intranet_cidr': 'auto',
                'tunnel_cidr': 'auto',
                'dmz_cidr': 'auto',
                'maintenance_cidr': 'auto',
                'ntp_server': ' '.join(local_dict['ntp_servers_dict'].keys())
            }
        })

        # pylint: disable=C0103
        def _create_vpc_mock(CidrBlock):
            return {
                'Vpc': {
                    'CidrBlock': CidrBlock,
                    'VpcId': local_dict['mock_vpc_id'],
                    'DhcpOptionsId': 'mock_dhcp_options_id'
                }
            }

        def _create_create_dhcp_mock(**args):
            local_dict['dhcp_options_created'] = True
            return {
                'DhcpOptions': {
                    'DhcpOptionsId': local_dict['new_mock_dhcp_options_id']
                }
            }

        def _create_describe_dhcp_mock(**args):
            return {'DhcpOptions': [{'DhcpOptionsId': local_dict['new_mock_dhcp_options_id']}]} \
                if local_dict['dhcp_options_created'] else {'DhcpOptions': []}

        def _create_gethostbyname_mock(hostname):
            return local_dict['ntp_servers_dict'][hostname]

        client_mock = MagicMock()
        client_mock.create_vpc.side_effect = _create_vpc_mock
        client_mock.get_all_zones.return_value = [MagicMock()]
        client_mock.create_dhcp_options.side_effect = _create_create_dhcp_mock
        client_mock.describe_dhcp_options.side_effect = _create_describe_dhcp_mock
        gethostbyname_mock.side_effect = _create_gethostbyname_mock
        boto3_client_mock.return_value = client_mock

        # Calling method under test
        DiscoVPC('auto-vpc', 'auto-vpc-type')

        # Verifying result
        actual_ntp_servers = [
            option['Values'] for option in
            client_mock.create_dhcp_options.call_args[1]['DhcpConfigurations']
            if option['Key'] == 'ntp-servers'
        ][0]
        self.assertEqual(set(actual_ntp_servers),
                         set(local_dict['ntp_servers_dict'].values()))

        client_mock.associate_dhcp_options.assert_has_calls([
            call(DhcpOptionsId=local_dict['new_mock_dhcp_options_id'],
                 VpcId=local_dict['mock_vpc_id'])
        ])
示例#39
0
class DiscoVPCPeeringsTests(unittest.TestCase):
    """Test DiscoVPCPeerings"""
    @patch("disco_aws_automation.disco_vpc.DiscoSNS", MagicMock())
    @patch("disco_aws_automation.disco_vpc.DiscoRDS", MagicMock())
    @patch("disco_aws_automation.disco_vpc.DiscoVPCEndpoints", MagicMock())
    def setUp(self):
        mock_ec2().start()

        self.disco_vpc1 = DiscoVPC('mock-vpc-1', 'sandbox')
        self.disco_vpc2 = DiscoVPC('mock-vpc-2', 'sandbox')
        self.disco_vpc3 = DiscoVPC('mock-vpc-3', 'sandbox')

        self.client = boto3.client('ec2')

        self.disco_vpc_peerings = DiscoVPCPeerings()

    @patch(
        'disco_aws_automation.disco_vpc.DiscoMetaNetwork.create_peering_route')
    @patch('disco_aws_automation.disco_vpc_peerings.read_config')
    def test_update_peering_connections(self, config_mock,
                                        create_peering_route_mock):
        """ Verify new peering connections are created properly """

        config_mock.return_value = get_mock_config({
            'peerings': {
                'connection_1':
                'mock-vpc-1:sandbox/intranet mock-vpc-2:sandbox/intranet'
            }
        })

        # End setting up test

        # Calling method under test
        self.disco_vpc_peerings.update_peering_connections(self.disco_vpc1)

        # Asserting correct behavior

        peeerings = self.client.describe_vpc_peering_connections().get(
            'VpcPeeringConnections')

        self.assertEqual(1, len(peeerings))

        peering_id = peeerings[0]['VpcPeeringConnectionId']

        self.assertEqual(self.disco_vpc1.get_vpc_id(),
                         peeerings[0]['RequesterVpcInfo']['VpcId'])
        self.assertEqual(self.disco_vpc2.get_vpc_id(),
                         peeerings[0]['AccepterVpcInfo']['VpcId'])

        # create_peering_route should have been called twice, once for each VPC
        create_peering_route_mock.assert_called_with(peering_id,
                                                     '10.101.0.0/20')
        self.assertEqual(2, create_peering_route_mock.call_count)

    def test_parse_peering_connection(self):
        """test parsing a peering connection line with wildcards"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            'mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet')

        expected = [
            PeeringConnection.from_peering_line(
                'mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
        ]

        self.assertItemsEqual(actual, expected)

    def test_parse_peering_connection_wildcards(self):
        """test parsing a peering connection line with wildcards"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            '*:sandbox/intranet mock-vpc-3:sandbox/intranet')

        expected = [
            PeeringConnection.from_peering_line(
                'mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
            PeeringConnection.from_peering_line(
                'mock-vpc-2:sandbox/intranet mock-vpc-3:sandbox/intranet')
        ]

        self.assertItemsEqual(actual, expected)

    def test_parse_peering_double_wildcards(self):
        """test parsing a peering connection line with wildcards on both sides"""
        actual = self.disco_vpc_peerings._resolve_peering_connection_line(
            '*:sandbox/intranet *:sandbox/intranet')

        expected = [
            PeeringConnection.from_peering_line(
                'mock-vpc-1:sandbox/intranet mock-vpc-2:sandbox/intranet'),
            PeeringConnection.from_peering_line(
                'mock-vpc-1:sandbox/intranet mock-vpc-3:sandbox/intranet'),
            PeeringConnection.from_peering_line(
                'mock-vpc-2:sandbox/intranet mock-vpc-3:sandbox/intranet')
        ]

        self.assertItemsEqual(actual, expected)