def test_handle_spec(self): self.make_mock_vpc() # Need to take a peek inside the VPC so we can properly evaluate the # output later on con = vpc.connect_to_region("ap-southeast-2") d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") route_spec = {u"10.2.0.0/16": [self.i1ip]} d['cluster_node_subnets'] = \ vpc.make_cluster_node_subnet_list(d, route_spec) i, eni = vpc.find_instance_and_eni_by_ip(d, self.i1ip) rt_id = d['route_tables'][0].id con.associate_route_table(route_table_id=rt_id, subnet_id=self.new_subnet_a.id) con.associate_route_table(route_table_id=rt_id, subnet_id=self.new_subnet_b.id) # Test handle_spec vid = self.new_vpc.id self.lc.clear() vpc.handle_spec("ap-southeast-2", vid, route_spec, [], []) self.lc.check( ('root', 'DEBUG', 'Handle route spec'), ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"), ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid), ('root', 'DEBUG', 'Route spec processing. No failed IPs.'), ('root', 'INFO', "--- adding route in RT '%s' 10.2.0.0/16 -> %s (%s, %s)" % (rt_id, self.i1ip, self.i1.id, eni.id))) # mock the get_instance_private_ip_from_route() function in vpc. Reason # being: The boto mocking library (moto) doesn't handle ENIs in routes # correctly. Therefore, a match against the information we get from the # routes will never work. So, we provide a wrapper, which fills the # instance's ENI information into the route. This means that this # function now will always match. It's good for testing the 'match' # part of the code. old_func = vpc.get_instance_private_ip_from_route def my_get_instance_private_ip_from_route(instance, route): route.interface_id = instance.interfaces[0].id return old_func(instance, route) vpc.get_instance_private_ip_from_route = \ my_get_instance_private_ip_from_route self.lc.clear() vpc.handle_spec("ap-southeast-2", vid, route_spec, [], []) vpc.get_instance_private_ip_from_route = old_func self.lc.check( ('root', 'DEBUG', 'Handle route spec'), ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"), ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid), ('root', 'DEBUG', 'Route spec processing. No failed IPs.'), ('root', 'INFO', "--- route exists already in RT '%s': 10.2.0.0/16 -> " "%s (%s, %s)" % (rt_id, self.i1ip, self.i1.id, eni.id)))
def test_connect(self): self.make_mock_vpc() # With a test VPC created, we now test our own functions con = vpc.connect_to_region("ap-southeast-2") d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") self.assertEqual( sorted([ 'subnets', 'route_tables', 'instance_by_id', 'instances', 'zones', 'vpc' ]), sorted(d.keys())) self.assertEqual(self.new_vpc.id, d['vpc'].id) self.assertTrue(self.new_subnet_a.id in [s.id for s in d['subnets']]) self.assertTrue(self.new_subnet_b.id in [s.id for s in d['subnets']]) self.assertTrue(len(d['zones']) == 3) self.assertTrue(len(d['route_tables']) == 1) self.assertTrue(len(d['instance_by_id'].keys()) == 2) self.assertTrue(d['instance_by_id'][self.i1.id].id == self.i1.id) self.assertTrue(d['instance_by_id'][self.i2.id].id == self.i2.id) self.assertTrue( vpc.find_instance_and_eni_by_ip(d, self.i1ip)[0].id == self.i1.id) self.assertTrue( vpc.find_instance_and_eni_by_ip(d, self.i2ip)[0].id == self.i2.id)
def _prepare_mock_env(self): self.make_mock_vpc() con = vpc.connect_to_region("ap-southeast-2") d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") i1, eni1 = vpc.find_instance_and_eni_by_ip(d, self.i1ip) i2, eni2 = vpc.find_instance_and_eni_by_ip(d, self.i2ip) rt_id = d['route_tables'][0].id return con, d, i1, eni1, i2, eni2, rt_id
def test_connect(self): self.make_mock_vpc() # With a test VPC created, we now test our own functions # In the mocked test the meta data won't contain the info we need (vpc # and region name), because the emulated EC2 instance isn't in any # region or vpc. meta = vpc.get_ec2_meta_data() self.assertTrue(meta == {}) self.assertRaises(VpcRouteSetError, vpc.connect_to_region, "blah") con = vpc.connect_to_region("ap-southeast-2") # Error when specifying non-existent VPC self.assertRaises(VpcRouteSetError, vpc.get_vpc_overview, con, "non-existent-vpc", "ap-southeast-2") # Get the default: First VPC if no VPC is specified d = vpc.get_vpc_overview(con, None, "ap-southeast-2") self.assertEqual(d['vpc'].id, "vpc-be745e76") # Get specified VPC d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") self.assertEqual(d['vpc'].id, "vpc-be745e76") self.assertEqual( sorted([ 'subnets', 'route_tables', 'instance_by_id', 'ip_subnet_lookup', 'instances', 'rt_subnet_lookup', 'zones', 'vpc' ]), sorted(d.keys())) self.assertEqual(self.new_vpc.id, d['vpc'].id) self.assertTrue(self.new_subnet_a.id in [s.id for s in d['subnets']]) self.assertTrue(self.new_subnet_b.id in [s.id for s in d['subnets']]) self.assertTrue(len(d['zones']) == 3) self.assertTrue(len(d['route_tables']) == 1) self.assertTrue(len(d['instance_by_id'].keys()) == 2) self.assertTrue(d['instance_by_id'][self.i1.id].id == self.i1.id) self.assertTrue(d['instance_by_id'][self.i2.id].id == self.i2.id) self.assertRaises(VpcRouteSetError, vpc.find_instance_and_eni_by_ip, d, "9.9.9.9") # Non existent IP self.assertTrue( vpc.find_instance_and_eni_by_ip(d, self.i1ip)[0].id == self.i1.id) self.assertTrue( vpc.find_instance_and_eni_by_ip(d, self.i2ip)[0].id == self.i2.id)
def test_process_route_spec_config(self): self.make_mock_vpc() con = vpc.connect_to_region("ap-southeast-2") d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") i1, eni1 = vpc.find_instance_and_eni_by_ip(d, self.i1ip) i2, eni2 = vpc.find_instance_and_eni_by_ip(d, self.i2ip) rt_id = d['route_tables'][0].id route_spec = {u"10.1.0.0/16": [self.i1ip, self.i2ip]} # Process a simple route spec, a route should have been added self.lc.clear() vpc.process_route_spec_config(con, d, route_spec, []) # One of the hosts is randomly chosen. We seeded the random number # generator at in this module, so we know that it will choose the # second host in this case. self.lc.check( ('root', 'DEBUG', 'Route spec processing. No failed IPs.'), ('root', 'INFO', "--- adding route in RT '%s' " "10.1.0.0/16 -> %s (%s, %s)" % (rt_id, self.i2ip, i2.id, eni2.id))) # One of the two IPs failed, switch over d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") self.lc.clear() vpc.process_route_spec_config(con, d, route_spec, [self.i1ip]) self.lc.check( ('root', 'DEBUG', 'Route spec processing. Failed IPs: %s' % self.i1ip), ('root', 'INFO', "--- updating existing route in RT '%s' 10.1.0.0/16 -> " "%s (%s, %s) (old IP: None, reason: old IP failed or not " "eligible anymore)" % (rt_id, self.i2ip, i2.id, eni2.id))) # Now all IPs for a route have failed d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") self.lc.clear() vpc.process_route_spec_config(con, d, route_spec, [self.i1ip, self.i2ip]) self.lc.check( ('root', 'DEBUG', 'Route spec processing. Failed IPs: %s,%s' % (self.i1ip, self.i2ip)), ('root', 'WARNING', '--- cannot find available target for route update 10.1.0.0/16! ' 'Nothing I can do...')) # Add new route, remove old one route_spec = {u"10.2.0.0/16": [self.i1ip]} d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2") self.lc.clear() vpc.process_route_spec_config(con, d, route_spec, []) self.lc.check( ('root', 'DEBUG', 'Route spec processing. No failed IPs.'), ('root', 'INFO', "--- route not in spec, deleting in RT '%s': " "10.1.0.0/16 -> ... (%s, (unknown))" % (rt_id, i2.id)), ('root', 'INFO', "--- adding route in RT '%s' " "10.2.0.0/16 -> %s (%s, %s)" % (rt_id, self.i1ip, i1.id, eni1.id)))