From be7ebefd7df163869b8f1f14b96c3817b08bc74c Mon Sep 17 00:00:00 2001 From: Andrey Pavlov Date: Wed, 9 Dec 2015 16:55:52 +0300 Subject: [PATCH] fix races 1) fix bug with filtering filters were applied before unpaired items is added to result 2) fix races in default security group creation 3) add waiter for associate/disassociate address 4) fix security group classic test it should choose default group group only from classic groups 5) fix describe_vpc_with_filters test it can run in parallel with other test with same CIDR 6) fix networks list for instance run at subnet creation/deletion 7) fix selective decsribe by names it should not delete valid items from db Change-Id: Iadadefb8b4abebbb3b8efc0e536e5de30ed23dab --- api/test_addresses.py | 15 +++++++-------- api/test_security_groups.py | 10 +++++++--- api/test_vpcs.py | 2 +- base.py | 28 ++++++++++++++++++++++++++++ scenario/base.py | 4 ++++ scenario/test_paging.py | 15 ++++++++------- scenario/test_vpc_addresses.py | 6 ++++++ 7 files changed, 61 insertions(+), 19 deletions(-) diff --git a/api/test_addresses.py b/api/test_addresses.py index 71ae587..e845e70 100644 --- a/api/test_addresses.py +++ b/api/test_addresses.py @@ -266,6 +266,8 @@ class AddressTest(base.EC2TestCase): assoc_id = data['AssociationId'] clean_aa = self.addResourceCleanUp(self.client.disassociate_address, AssociationId=assoc_id) + self.get_address_assoc_waiter().wait_available( + {'AllocationId': alloc_id}) kwargs = { 'AllocationIds': [alloc_id], @@ -275,9 +277,7 @@ class AddressTest(base.EC2TestCase): data = self.client.disassociate_address(AssociationId=assoc_id) self.cancelResourceCleanUp(clean_aa) - - data = self.client.describe_addresses(*[], **kwargs) - self.assertIsNone(data['Addresses'][0].get('InstanceId')) + self.get_address_assoc_waiter().wait_delete({'AllocationId': alloc_id}) # NOTE(andrey-mp): cleanup time.sleep(3) @@ -316,6 +316,7 @@ class AddressTest(base.EC2TestCase): PublicIp=ip) clean_aa = self.addResourceCleanUp(self.client.disassociate_address, PublicIp=ip) + self.get_address_assoc_waiter().wait_available({'PublicIp': ip}) kwargs = { 'PublicIps': [ip], @@ -325,11 +326,7 @@ class AddressTest(base.EC2TestCase): data = self.client.disassociate_address(PublicIp=ip) self.cancelResourceCleanUp(clean_aa) - # NOTE(andrey-mp): Amazon needs some time to diassociate - time.sleep(2) - - data = self.client.describe_addresses(*[], **kwargs) - self.assertFalse(data['Addresses'][0].get('InstanceId')) + self.get_address_assoc_waiter().wait_delete({'PublicIp': ip}) time.sleep(3) @@ -418,3 +415,5 @@ class AddressTest(base.EC2TestCase): assoc_id = data['AssociationId'] self.addResourceCleanUp(self.client.disassociate_address, AssociationId=assoc_id) + self.get_address_assoc_waiter().wait_available( + {'AllocationId': alloc_id}) diff --git a/api/test_security_groups.py b/api/test_security_groups.py index 1c10ed5..7525ff7 100644 --- a/api/test_security_groups.py +++ b/api/test_security_groups.py @@ -32,10 +32,14 @@ class SecurityGroupBaseTest(base.EC2TestCase): def _test_rules(self, add_func, del_func, field, vpc_id=None): kwargs = dict() if vpc_id: - kwargs['Filters'] = [{'Name': 'vpc-id', - 'Values': [vpc_id]}] + kwargs['Filters'] = [{'Name': 'vpc-id', 'Values': [vpc_id]}] data = self.client.describe_security_groups(*[], **kwargs) - default_group = data['SecurityGroups'][0] + security_groups = data['SecurityGroups'] + if not vpc_id: + # TODO(andrey-mp): remove it when fitering by None will be + security_groups = [sg for sg in security_groups + if sg.get('VpcId') is None] + default_group = security_groups[0] name = data_utils.rand_name('sgName') desc = data_utils.rand_name('sgDesc') diff --git a/api/test_vpcs.py b/api/test_vpcs.py index be68ad7..9f56877 100644 --- a/api/test_vpcs.py +++ b/api/test_vpcs.py @@ -100,7 +100,7 @@ class VPCTest(base.EC2TestCase): self.get_vpc_waiter().wait_delete(vpc_id) def test_describe_vpcs_filters(self): - cidr = '10.1.0.0/16' + cidr = '10.163.0.0/16' data = self.client.create_vpc(CidrBlock=cidr) vpc_id = data['Vpc']['VpcId'] dv_clean = self.addResourceCleanUp(self.client.delete_vpc, diff --git a/base.py b/base.py index 005235e..1cdc122 100644 --- a/base.py +++ b/base.py @@ -336,6 +336,9 @@ class EC2TestCase(base.BaseTestCase): 'delete_vpn_gateway': ( 'get_vpn_gateway_waiter', lambda kwargs: kwargs['VpnGatewayId']), + 'disassociate_address': ( + 'get_address_assoc_waiter', + lambda kwargs: kwargs), } @classmethod @@ -460,6 +463,31 @@ class EC2TestCase(base.BaseTestCase): def get_subnet_waiter(cls): return EC2Waiter(cls._subnet_get_state) + @classmethod + def _address_assoc_get_state(cls, kwargs): + try: + ip = kwargs.get('PublicIp') + alloc_id = kwargs.get('AllocationId') + assoc_id = kwargs.get('AssociationId') + if ip: + data = cls.client.describe_addresses(PublicIps=[ip]) + elif alloc_id: + data = cls.client.describe_addresses(AllocationIds=[alloc_id]) + elif assoc_id: + data = cls.client.describe_addresses( + Filters=[{'Name': 'association-id', 'Values': [assoc_id]}]) + + if ('Addresses' in data and len(data['Addresses']) == 1 and + data['Addresses'][0].get('InstanceId')): + return 'available' + raise exceptions.NotFound() + except botocore.exceptions.ClientError: + raise exceptions.NotFound() + + @classmethod + def get_address_assoc_waiter(cls): + return EC2Waiter(cls._address_assoc_get_state) + @classmethod def _instance_get_state(cls, instance_id): try: diff --git a/scenario/base.py b/scenario/base.py index 10d6783..abfc2e7 100644 --- a/scenario/base.py +++ b/scenario/base.py @@ -45,9 +45,13 @@ class BaseScenarioTest(base.EC2TestCase): if is_vpc: self.addResourceCleanUp(self.client.disassociate_address, AssociationId=data['AssociationId']) + self.get_address_assoc_waiter().wait_available( + {'AllocationId': alloc_id}) else: self.addResourceCleanUp(self.client.disassociate_address, PublicIp=public_ip) + self.get_address_assoc_waiter().wait_available( + {'PublicIp': public_ip}) return public_ip diff --git a/scenario/test_paging.py b/scenario/test_paging.py index 886a73c..a789763 100644 --- a/scenario/test_paging.py +++ b/scenario/test_paging.py @@ -328,7 +328,9 @@ class InstancePagingTest(scenario_base.BaseScenarioTest): rcount += 1 self.assertEqual(self.RESERVATIONS_COUNT, rcount) count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT - self.assertEqual(count, self._count_own_instances(data)) + instances = set() + self._collect_own_instances(data, instances) + self.assertEqual(count, len(instances)) def test_simple_instances_paging_with_min_results(self): max_results = 5 @@ -340,16 +342,17 @@ class InstancePagingTest(scenario_base.BaseScenarioTest): real_count = 0 max_results = 5 kwargs = {'MaxResults': max_results} + instances = set() while True: data = self.client.describe_instances(*[], **kwargs) self.assertGreaterEqual(max_results, self._count_instances(data)) - real_count += self._count_own_instances(data) + self._collect_own_instances(data, instances) if 'NextToken' not in data: break kwargs['NextToken'] = data['NextToken'] count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT - self.assertEqual(count, real_count) + self.assertEqual(count, len(instances)) def test_invalid_paging(self): self.assertRaises('InvalidParameterValue', @@ -359,13 +362,11 @@ class InstancePagingTest(scenario_base.BaseScenarioTest): self.client.describe_instances, MaxResults=5, InstanceIds=[self.ids[0]]) - def _count_own_instances(self, data): - count = 0 + def _collect_own_instances(self, data, instances): for reservation in data['Reservations']: for instance in reservation['Instances']: if instance['InstanceId'] in self.ids: - count += 1 - return count + instances.add(instance['InstanceId']) def _count_instances(self, data): count = 0 diff --git a/scenario/test_vpc_addresses.py b/scenario/test_vpc_addresses.py index be0563e..d2ea480 100644 --- a/scenario/test_vpc_addresses.py +++ b/scenario/test_vpc_addresses.py @@ -80,6 +80,8 @@ class VpcAddressTest(scenario_base.BaseScenarioTest): assoc_id1 = data['AssociationId'] clean_aa1 = self.addResourceCleanUp(self.client.disassociate_address, AssociationId=assoc_id1) + self.get_address_assoc_waiter().wait_available( + {'AllocationId': alloc_id1}) instance = self.get_instance(instance_id) nis = instance.get('NetworkInterfaces', []) @@ -106,6 +108,8 @@ class VpcAddressTest(scenario_base.BaseScenarioTest): assoc_id2 = data['AssociationId'] clean_aa2 = self.addResourceCleanUp(self.client.disassociate_address, AssociationId=assoc_id2) + self.get_address_assoc_waiter().wait_available( + {'AllocationId': alloc_id2}) kwargs = { 'NetworkInterfaceId': ni_id2, @@ -147,3 +151,5 @@ class VpcAddressTest(scenario_base.BaseScenarioTest): self.client.disassociate_address(AssociationId=assoc_id1) self.cancelResourceCleanUp(clean_aa1) + self.get_address_assoc_waiter().wait_delete( + {'AllocationId': alloc_id1})