Merge branch 'feature/vpc-filters'

This commit is contained in:
Omer Katz 2014-10-01 15:56:23 +03:00
commit 4ec95bac74
3 changed files with 111 additions and 9 deletions

View File

@ -1,9 +1,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
import copy import copy
import itertools import itertools
from collections import defaultdict from collections import defaultdict
import six
import boto import boto
from boto.ec2.instance import Instance as BotoInstance, Reservation from boto.ec2.instance import Instance as BotoInstance, Reservation
from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
@ -70,7 +70,7 @@ from .utils import (
random_volume_id, random_volume_id,
random_vpc_id, random_vpc_id,
random_vpc_peering_connection_id, random_vpc_peering_connection_id,
) generic_filter)
class InstanceState(object): class InstanceState(object):
@ -93,6 +93,12 @@ class TaggedEC2Instance(object):
if tag['key'] == tagname: if tag['key'] == tagname:
return tag['value'] return tag['value']
if filter_name == 'tag-key':
return [tag['key'] for tag in tags]
if filter_name == 'tag-value':
return [tag['value'] for tag in tags]
class NetworkInterface(object): class NetworkInterface(object):
def __init__(self, subnet, private_ip_address, device_index=0, public_ip_auto_assign=True, group_ids=None): def __init__(self, subnet, private_ip_address, device_index=0, public_ip_auto_assign=True, group_ids=None):
@ -1159,7 +1165,7 @@ class VPC(TaggedEC2Instance):
filter_value = super(VPC, self).get_filter_value(filter_name) filter_value = super(VPC, self).get_filter_value(filter_name)
if not filter_value: if filter_value is None:
msg = "The filter '{0}' for DescribeVPCs has not been" \ msg = "The filter '{0}' for DescribeVPCs has not been" \
" implemented in Moto yet. Feel free to open an issue at" \ " implemented in Moto yet. Feel free to open an issue at" \
" https://github.com/spulec/moto/issues".format(filter_name) " https://github.com/spulec/moto/issues".format(filter_name)
@ -1198,11 +1204,7 @@ class VPCBackend(object):
else: else:
vpcs = self.vpcs.values() vpcs = self.vpcs.values()
if filters: return generic_filter(filters, vpcs)
for (_filter, _filter_value) in filters.items():
vpcs = [ vpc for vpc in vpcs if vpc.get_filter_value(_filter) in _filter_value ]
return vpcs
def delete_vpc(self, vpc_id): def delete_vpc(self, vpc_id):
# Delete route table if only main route table remains. # Delete route table if only main route table remains.

View File

@ -278,6 +278,27 @@ def filter_reservations(reservations, filter_dict):
return result return result
def is_filter_matching(obj, filter, filter_value):
value = obj.get_filter_value(filter)
if isinstance(value, six.string_types):
return value in filter_value
try:
value = set(value)
return (value and value.issubset(filter_value)) or value.issuperset(filter_value)
except TypeError:
return value in filter_value
def generic_filter(filters, objects):
if filters:
for (_filter, _filter_value) in filters.items():
objects = [obj for obj in objects if is_filter_matching(obj, _filter, _filter_value)]
return objects
# not really random ( http://xkcd.com/221/ ) # not really random ( http://xkcd.com/221/ )
def random_key_pair(): def random_key_pair():
return { return {

View File

@ -129,3 +129,82 @@ def test_vpc_get_by_tag():
vpc_ids = tuple(map(lambda v: v.id, vpcs)) vpc_ids = tuple(map(lambda v: v.id, vpcs))
vpc1.id.should.be.within(vpc_ids) vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_key_superset():
conn = boto.connect_vpc()
vpc1 = conn.create_vpc("10.0.0.0/16")
vpc2 = conn.create_vpc("10.0.0.0/16")
vpc3 = conn.create_vpc("10.0.0.0/24")
vpc1.add_tag('Name', 'TestVPC')
vpc1.add_tag('Key', 'TestVPC2')
vpc2.add_tag('Name', 'TestVPC')
vpc2.add_tag('Key', 'TestVPC2')
vpc3.add_tag('Key', 'TestVPC2')
vpcs = conn.get_all_vpcs(filters={'tag-key': 'Name'})
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v.id, vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_key_subset():
conn = boto.connect_vpc()
vpc1 = conn.create_vpc("10.0.0.0/16")
vpc2 = conn.create_vpc("10.0.0.0/16")
vpc3 = conn.create_vpc("10.0.0.0/24")
vpc1.add_tag('Name', 'TestVPC')
vpc1.add_tag('Key', 'TestVPC2')
vpc2.add_tag('Name', 'TestVPC')
vpc2.add_tag('Key', 'TestVPC2')
vpc3.add_tag('Test', 'TestVPC2')
vpcs = conn.get_all_vpcs(filters={'tag-key': ['Name', 'Key']})
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v.id, vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_value_superset():
conn = boto.connect_vpc()
vpc1 = conn.create_vpc("10.0.0.0/16")
vpc2 = conn.create_vpc("10.0.0.0/16")
vpc3 = conn.create_vpc("10.0.0.0/24")
vpc1.add_tag('Name', 'TestVPC')
vpc1.add_tag('Key', 'TestVPC2')
vpc2.add_tag('Name', 'TestVPC')
vpc2.add_tag('Key', 'TestVPC2')
vpc3.add_tag('Key', 'TestVPC2')
vpcs = conn.get_all_vpcs(filters={'tag-value': 'TestVPC'})
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v.id, vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_value_subset():
conn = boto.connect_vpc()
vpc1 = conn.create_vpc("10.0.0.0/16")
vpc2 = conn.create_vpc("10.0.0.0/16")
vpc3 = conn.create_vpc("10.0.0.0/24")
vpc1.add_tag('Name', 'TestVPC')
vpc1.add_tag('Key', 'TestVPC2')
vpc2.add_tag('Name', 'TestVPC')
vpc2.add_tag('Key', 'TestVPC2')
vpcs = conn.get_all_vpcs(filters={'tag-value': ['TestVPC', 'TestVPC2']})
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v.id, vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)