Test filtering is used correctly in all APIs

Change-Id: Ia78b439fb045ec8862ce8718d1b24244c2ff7b07
This commit is contained in:
Feodor Tersin
2015-01-24 11:30:10 +04:00
parent 9346c9cbe1
commit 4da99aac24
21 changed files with 221 additions and 29 deletions

View File

@@ -207,9 +207,9 @@ class ImageDescriber(common.TaggableItemsDescriber):
'is-public': 'isPublic',
'kernel_id': 'kernelId',
'name': 'name',
'owner-id': 'ownerId',
'owner-id': 'imageOwnerId',
'ramdisk-id': 'ramdiskId',
'state': 'state',
'state': 'imageState',
}
def format(self, image, os_image):

View File

@@ -124,7 +124,7 @@ class InternetGatewayDescriber(common.TaggableItemsDescriber,
common.NonOpenstackItemsDescriber):
KIND = 'igw'
FILTER_MAP = {'internet-gateway-id': 'id',
FILTER_MAP = {'internet-gateway-id': 'internetGatewayId',
'attachment.state': ['attachmentSet', 'state'],
'attachment.vpc-id': ['attachmentSet', 'vpcId']}

View File

@@ -209,14 +209,14 @@ class RouteTableDescriber(common.TaggableItemsDescriber,
'association.route-table-id': ['associationSet',
'routeTableId'],
'association.subnet-id': ['associationSet', 'subnetId'],
'association.main': ['association', 'main'],
'association.main': ['associationSet', 'main'],
'route-table-id': 'routeTableId',
'route.destination-cidr-block': ['routeSet',
'destinationCidrBlock'],
'route.gateway-id': ['routeSet', 'gatewayId'],
'route.instance-id': ['routeSet', 'instanceId'],
'route.origin': ['route', 'origin'],
'route.state': ['route', 'state'],
'route.origin': ['routeSet', 'origin'],
'route.state': ['routeSet', 'state'],
'vpc-id': 'vpcId'}
def format(self, route_table):

View File

@@ -137,7 +137,7 @@ class SubnetDescriber(common.TaggableItemsDescriber):
'cidr': 'cidrBlock',
'cidrBlock': 'cidrBlock',
'cidr-block': 'cidrBlock',
'subnet-id': 'id',
'subnet-id': 'subnetId',
'state': 'state',
'vpc-id': 'vpcId'}

View File

@@ -116,3 +116,18 @@ class ApiTestCase(test_base.BaseTestCase):
if matchers.ListMatches(call_args, args, orderless_lists=True):
return
self.assertEqual(False, True)
def check_filtering(self, operation, resultset_key, filters):
for name, value in filters:
resp = self.execute(operation,
{'Filter.1.Name': name,
'Filter.1.Value.1': str(value)})
self.assertEqual(200, resp['http_status_code'])
self.assertTrue(len(resp[resultset_key]) > 0)
resp = self.execute(operation,
{'Filter.1.Name': name,
'Filter.1.Value.1': 'dummy filter value'})
self.assertEqual(200, resp['http_status_code'])
self.assertTrue(resp[resultset_key] is None or
len(resp[resultset_key]) == 0)

View File

@@ -176,6 +176,7 @@ ID_OS_FLOATING_IP_2 = random_os_id()
IP_ADDRESS_1 = '192.168.1.100'
IP_ADDRESS_2 = '192.168.1.200'
IP_ADDRESS_NOVA_1 = '192.168.2.100'
# security group constants
@@ -604,7 +605,7 @@ EC2_INSTANCE_2 = {
'privateIpAddress': None,
'amiLaunchIndex': 0,
'placement': {'availabilityZone': NAME_AVAILABILITY_ZONE},
'dnsName': None,
'dnsName': IP_ADDRESS_NOVA_1,
'dnsNameV6': IPV6_INSTANCE_2,
'instanceState': {'code': 0, 'name': 'pending'},
'imageId': None,
@@ -620,6 +621,7 @@ EC2_INSTANCE_2 = {
'volumeId': ID_EC2_VOLUME_2,
'attachTime': None}}],
'instanceType': 'fake_flavor',
'ipAddress': IP_ADDRESS_NOVA_1,
'rootDeviceName': ROOT_DEVICE_NAME_INSTANCE_2,
'clientToken': CLIENT_TOKEN_INSTANCE_2,
}
@@ -707,7 +709,10 @@ OS_INSTANCE_2 = OSInstance(
addresses={
ID_EC2_SUBNET_1: [{'addr': IPV6_INSTANCE_2,
'version': 6,
'OS-EXT-IPS:type': 'fixed'}]},
'OS-EXT-IPS:type': 'fixed'},
{'addr': IP_ADDRESS_NOVA_1,
'version': 4,
'OS-EXT-IPS:type': 'floating'}]},
)
@@ -1147,6 +1152,7 @@ EC2_IMAGE_2 = {
'architecture': None,
'rootDeviceType': 'ebs',
'rootDeviceName': ROOT_DEVICE_NAME_IMAGE_2,
'architecture': 'x86_64',
'blockDeviceMapping': [
{'deviceName': '/dev/sdb1',
'ebs': {'snapshotId': ID_EC2_SNAPSHOT_1}}],
@@ -1225,6 +1231,7 @@ OS_IMAGE_2 = {
'properties': {
'type': 'machine',
'root_device_name': '/dev/sdb1',
'architecture': 'x86_64',
'mappings': [{'device': '/dev/sda1',
'virtual': 'root'}],
'block_device_mapping': [

View File

@@ -617,6 +617,17 @@ class AddressTestCase(base.ApiTestCase):
matchers.ListMatches([fakes.EC2_ADDRESS_1,
fakes.EC2_ADDRESS_2]))
self.check_filtering(
'DescribeAddresses', 'addressesSet',
[('allocation-id', fakes.ID_EC2_ADDRESS_1),
('association-id', fakes.ID_EC2_ASSOCIATION_2),
('domain', 'vpc'),
('instance-id', fakes.ID_EC2_INSTANCE_1),
('network-interface-id', fakes.ID_EC2_NETWORK_INTERFACE_2),
('network-interface-owner-id', fakes.ID_OS_PROJECT),
('privateIpAddress', fakes.IP_NETWORK_INTERFACE_2),
('public-ip', fakes.IP_ADDRESS_2)])
def test_describe_addresses_ec2_classic(self):
address.address_engine = (
address.AddressEngineNova())

View File

@@ -29,6 +29,11 @@ class AvailabilityZoneCase(base.ApiTestCase):
matchers.ListMatches([fakes.EC2_AVAILABILITY_ZONE]))
self.nova_availability_zones.list.assert_called_once()
self.check_filtering(
'DescribeAvailabilityZones', 'availabilityZoneInfo',
[('state', 'available'),
('zone-name', fakes.NAME_AVAILABILITY_ZONE)])
def test_describe_availability_zones_verbose(self):
self.nova_availability_zones.list.return_value = [
fakes.NovaAvailabilityZone(fakes.OS_AVAILABILITY_ZONE),

View File

@@ -102,6 +102,11 @@ class DhcpOptionsTestCase(base.ApiTestCase):
fakes.EC2_DHCP_OPTIONS_2],
orderless_lists=True))
self.check_filtering(
'DescribeDhcpOptions', 'dhcpOptionsSet',
[('dhcp_options_id', fakes.ID_EC2_DHCP_OPTIONS_1),
('key', 'netbios-node-type')])
def test_associate_dhcp_options(self):
self.db_api.get_item_by_id.side_effect = (
fakes.get_db_api_get_item_by_id(

View File

@@ -231,6 +231,21 @@ class ImageTestCase(base.ApiTestCase):
self.db_api.get_items_by_ids.assert_any_call(
mock.ANY, 'ami', set([fakes.ID_EC2_IMAGE_1]))
self.check_filtering(
'DescribeImages', 'imagesSet',
[('architecture', 'x86_64'),
# TODO(ft): store a description in DB
# ('description', ''),
('image-id', fakes.ID_EC2_IMAGE_1),
('image-type', 'machine'),
# TODO(ft): support filtering by a boolean value
# ('is-public', True),
('kernel_id', fakes.ID_EC2_IMAGE_AKI_1,),
('name', 'fake_name'),
('owner-id', fakes.ID_OS_PROJECT),
('ramdisk-id', fakes.ID_EC2_IMAGE_ARI_1),
('state', 'available')])
def test_describe_images_invalid_parameters(self):
self._setup_model()

View File

@@ -898,16 +898,6 @@ class InstanceTestCase(base.ApiTestCase):
fakes.EC2_RESERVATION_2]},
orderless_lists=True))
resp = self.execute('DescribeInstances',
{'Filter.1.Name': 'key-name',
'Filter.1.Value.1': 'a',
'Filter.1.Value.2': 'b',
'Filter.2.Name': 'client-token',
'Filter.2.Value.1': 'a string'})
self.assertEqual({'http_status_code': 200,
'reservationSet': []},
resp)
self.db_api.get_items_by_ids.return_value = [fakes.DB_INSTANCE_2]
resp = self.execute('DescribeInstances', {'InstanceId.1':
fakes.ID_EC2_INSTANCE_2})
@@ -918,6 +908,46 @@ class InstanceTestCase(base.ApiTestCase):
{'reservationSet': [fakes.EC2_RESERVATION_2]},
orderless_lists=True))
self.check_filtering(
'DescribeInstances', 'reservationSet',
[('block-device-mapping.device-name',
fakes.ROOT_DEVICE_NAME_INSTANCE_2),
('client-token', fakes.CLIENT_TOKEN_INSTANCE_2),
# TODO(ft): support filtering by none/empty value
# ('dns-name', ''),
('image-id', fakes.ID_EC2_IMAGE_1),
('instance-id', fakes.ID_EC2_INSTANCE_2),
('instance-type', 'fake_flavor'),
('ip-address', fakes.IP_ADDRESS_2),
('kernel-id', fakes.ID_EC2_IMAGE_AKI_1),
('key-name', fakes.NAME_KEY_PAIR),
# TODO(ft): support filtering by a none/empty value
# ('launch-index', 0),
# TODO(ft): fill the field in fakes with correct value
# ('launch-time', ),
('private-dns-name', fakes.ID_EC2_INSTANCE_1),
('private-ip-address', fakes.IP_NETWORK_INTERFACE_2),
('ramdisk-id', fakes.ID_EC2_IMAGE_ARI_1),
('root-device-name', fakes.ROOT_DEVICE_NAME_INSTANCE_1),
('root-device-type', 'ebs'),
('subnet-id', fakes.ID_EC2_SUBNET_2),
('vpc-id', fakes.ID_EC2_VPC_1),
('network-interface.description',
fakes.DESCRIPTION_NETWORK_INTERFACE_2),
('network-interface.subnet-id', fakes.ID_EC2_SUBNET_2),
('network-interface.vpc-id', fakes.ID_EC2_VPC_1),
('network-interface.network-interface.id',
fakes.ID_EC2_NETWORK_INTERFACE_2),
('network-interface.owner-id', fakes.ID_OS_PROJECT),
# TODO(ft): support filtering by a boolean value
# ('network-interface.requester-managed', False),
('network-interface.status', 'in-use'),
# TODO(ft): declare a constant for the mac in fakes
('network-interface.mac-address', 'fb:10:2e:b2:ba:b7'),
# TODO(ft): support filtering by a boolean value
# ('network-interface.source-destination-check', True),
])
def test_describe_instances_ec2_classic(self):
instance_api.instance_engine = (
instance_api.InstanceEngineNova())

View File

@@ -274,6 +274,12 @@ class IgwTestCase(base.ApiTestCase):
matchers.ListMatches([fakes.EC2_IGW_1,
fakes.EC2_IGW_2]))
self.check_filtering(
'DescribeInternetGateways', 'internetGatewaySet',
[('internet-gateway-id', fakes.ID_EC2_IGW_2),
('attachment.state', 'available'),
('attachment.vpc-id', fakes.ID_EC2_VPC_1)])
@base.skip_not_implemented
def test_describe_igw_no_vpc(self):
pass

View File

@@ -92,6 +92,11 @@ class KeyPairCase(base.ApiTestCase):
{'keyMaterial'})]))
self.nova_key_pairs.list.assert_called_once()
self.check_filtering(
'DescribeKeyPairs', 'keySet',
[('fingerprint', fakes.FINGERPRINT_KEY_PAIR),
('key-name', fakes.NAME_KEY_PAIR)])
def test_describe_key_pairs_invalid(self):
self.nova_key_pairs.list.return_value = [fakes.NovaKeyPair(
fakes.OS_KEY_PAIR)]

View File

@@ -365,6 +365,29 @@ class NetworkInterfaceTestCase(base.ApiTestCase):
[fakes.EC2_NETWORK_INTERFACE_1,
fakes.EC2_NETWORK_INTERFACE_2]))
self.check_filtering(
'DescribeNetworkInterfaces', 'networkInterfaceSet',
[('addresses.private-ip-address',
fakes.IP_NETWORK_INTERFACE_2_EXT_1,),
# TODO(ft): support filtering by a boolean value
# ('addresses.primary', False),
('description', fakes.DESCRIPTION_NETWORK_INTERFACE_1),
# TODO(ft): add security groups to fake data
# ('group-id', ),
# ('group-name'),
# TODO(ft): declare a constant for the mac in fakes
('mac-address', 'fb:10:2e:b2:ba:b7'),
('network-interface-id', fakes.ID_EC2_NETWORK_INTERFACE_1),
('owner-id', fakes.ID_OS_PROJECT),
('private-ip-address', fakes.IP_NETWORK_INTERFACE_1),
# TODO(ft): support filtering by a boolean value
# ('requester-managed', False),
# TODO(ft): support filtering by a boolean value
# ('source-dest-check', True),
('status', 'available'),
('vpc-id', fakes.ID_EC2_VPC_1),
('subnet-id', fakes.ID_EC2_SUBNET_2)])
def test_describe_network_interface_attribute(self):
self.db_api.get_item_by_id.return_value = fakes.DB_NETWORK_INTERFACE_1

View File

@@ -696,6 +696,24 @@ class RouteTableTestCase(base.ApiTestCase):
matchers.ListMatches([fakes.EC2_ROUTE_TABLE_1,
fakes.EC2_ROUTE_TABLE_2]))
self.check_filtering(
'DescribeRouteTables', 'routeTableSet',
[('association.route-table-association-id',
fakes.ID_EC2_ROUTE_TABLE_ASSOCIATION_1),
('association.route-table-id', fakes.ID_EC2_ROUTE_TABLE_1),
# TODO(ft): add fake data for this case
# ('association.subnet-id', ),
# TODO(ft): support filtering by a boolean value
# ('association.main', True),
('route-table-id', fakes.ID_EC2_ROUTE_TABLE_1),
('route.destination-cidr-block', fakes.CIDR_EXTERNAL_NETWORK),
('route.gateway-id', 'local'),
('route.instance-id', fakes.ID_EC2_INSTANCE_1),
('route.origin', 'CreateRouteTable'),
('route.state', 'active'),
('vpc-id', fakes.ID_EC2_VPC_1)
])
def test_describe_route_tables_variations(self):
igw_1 = tools.purge_dict(fakes.DB_IGW_1, ('vpc_id',))
igw_2 = tools.update_dict(fakes.DB_IGW_2,

View File

@@ -281,6 +281,13 @@ class SecurityGroupTestCase(base.ApiTestCase):
[fakes.EC2_SECURITY_GROUP_2],
orderless_lists=True))
self.check_filtering(
'DescribeSecurityGroups', 'securityGroupInfo',
[('vpc-id', fakes.ID_EC2_VPC_1),
# TODO(ft): declare a constant for the group name in fakes
('group-name', 'groupname'),
('group-id', fakes.ID_EC2_SECURITY_GROUP_1)])
def test_describe_security_groups_nova(self):
security_group.security_group_engine = (
security_group.SecurityGroupEngineNova())

View File

@@ -57,6 +57,22 @@ class SnapshotTestCase(base.ApiTestCase):
self.db_api.get_items_by_ids.assert_any_call(
mock.ANY, 'snap', set([fakes.ID_EC2_SNAPSHOT_1]))
self.check_filtering(
'DescribeSnapshots', 'snapshotSet',
[
# NOTE(ft): declare a constant for the description in fakes
('description', 'fake description'),
('owner-id', fakes.ID_OS_PROJECT),
('progress', '100%'),
('snapshot-id', fakes.ID_EC2_SNAPSHOT_1),
('start-time', fakes.TIME_CREATE_SNAPSHOT_2),
('status', 'completed'),
('volume-id', fakes.ID_EC2_VOLUME_2),
# TODO(ft): support filtering by a number value
# NOTE(ft): declare a constant for the volume size in fakes
# ('volume-size', 1)
])
def test_describe_snapshots_invalid_parameters(self):
self.cinder.volume_snapshots.list.return_value = [
fakes.OSSnapshot(fakes.OS_SNAPSHOT_1),

View File

@@ -253,6 +253,19 @@ class SubnetTestCase(base.ApiTestCase):
matchers.ListMatches([fakes.EC2_SUBNET_1,
fakes.EC2_SUBNET_2]))
self.check_filtering(
'DescribeSubnets', 'subnetSet',
[
# TODO(ft): support filtering by a number value
# NOTE(ft): declare a constant for the count in fakes
# ('available-ip-address-count', 253),
('cidr', fakes.CIDR_SUBNET_2),
('cidrBlock', fakes.CIDR_SUBNET_2),
('cidr-block', fakes.CIDR_SUBNET_2),
('subnet-id', fakes.ID_EC2_SUBNET_2),
('state', 'available'),
('vpc-id', fakes.ID_EC2_VPC_1)])
@base.skip_not_implemented
def test_describe_subnets_no_vpc(self):
pass

View File

@@ -193,16 +193,12 @@ class TagTestCase(base.ApiTestCase):
orderless_lists=True),
verbose=True)
# NOTE(ft): check filtering is plugged
filter_fields = ['resource-type', 'resource-id', 'key', 'value']
filter_param = dict(('Filter.%s.Name' % num, field)
for num, field in enumerate(filter_fields))
filter_param.update(dict(('Filter.%s.Value.1' % num, 'fake')
for num, field in enumerate(filter_fields)))
resp = self.execute('DescribeTags', filter_param)
self.assertEqual({'http_status_code': 200,
'tagSet': []},
resp)
self.check_filtering(
'DescribeTags', 'tagSet',
[('resource-type', 'vpc'),
('resource-id', fakes.ID_EC2_VPC_1),
('key', 'key1'),
('value', 'value2')])
# NOTE(ft): check all resource types are displayed correctly
for r_id, r_type in [('dopt', 'dhcp-options'),

View File

@@ -62,6 +62,17 @@ class VolumeTestCase(base.ApiTestCase):
self.db_api.get_items_by_ids.assert_any_call(
mock.ANY, 'vol', set([fakes.ID_EC2_VOLUME_1]))
self.check_filtering(
'DescribeVolumes', 'volumeSet',
[('availability-zone', fakes.NAME_AVAILABILITY_ZONE),
('create-time', fakes.TIME_CREATE_VOLUME_2),
# TODO(ft): support filtering by a number value
# NOTE(ft): declare a constant for the volume size in fakes
# ('size', 1),
('snapshot-id', fakes.ID_EC2_SNAPSHOT_1),
('status', 'available'),
('volume-id', fakes.ID_EC2_VOLUME_1)])
def test_describe_volumes_invalid_parameters(self):
self.cinder.volumes.list.return_value = [
fakes.CinderVolume(fakes.OS_VOLUME_1),

View File

@@ -231,6 +231,15 @@ class VpcTestCase(base.ApiTestCase):
fakes.EC2_VPC_2]))
self.db_api.get_items.assert_called_once_with(mock.ANY, 'vpc')
self.check_filtering(
'DescribeVpcs', 'vpcSet',
[('cidr', fakes.CIDR_VPC_1),
('dhcp-options-id', 'default'),
# TODO(ft): support filtering by a boolean value
# ('is-default', False),
('state', 'available'),
('vpc-id', fakes.ID_EC2_VPC_1)])
def test_describe_vpcs_no_router(self):
self.neutron.list_routers.return_value = {'routers': []}
self.db_api.get_items.return_value = [fakes.DB_VPC_1]