Merge pull request #2306 from bkovacki/extend-describe-network-interface-filter
Extend EC2 DescribeNetworkInterface filter support
This commit is contained in:
commit
67b3d07e5d
@ -201,7 +201,7 @@ class TaggedEC2Resource(BaseModel):
|
|||||||
|
|
||||||
class NetworkInterface(TaggedEC2Resource):
|
class NetworkInterface(TaggedEC2Resource):
|
||||||
def __init__(self, ec2_backend, subnet, private_ip_address, device_index=0,
|
def __init__(self, ec2_backend, subnet, private_ip_address, device_index=0,
|
||||||
public_ip_auto_assign=True, group_ids=None):
|
public_ip_auto_assign=True, group_ids=None, description=None):
|
||||||
self.ec2_backend = ec2_backend
|
self.ec2_backend = ec2_backend
|
||||||
self.id = random_eni_id()
|
self.id = random_eni_id()
|
||||||
self.device_index = device_index
|
self.device_index = device_index
|
||||||
@ -209,6 +209,7 @@ class NetworkInterface(TaggedEC2Resource):
|
|||||||
self.subnet = subnet
|
self.subnet = subnet
|
||||||
self.instance = None
|
self.instance = None
|
||||||
self.attachment_id = None
|
self.attachment_id = None
|
||||||
|
self.description = description
|
||||||
|
|
||||||
self.public_ip = None
|
self.public_ip = None
|
||||||
self.public_ip_auto_assign = public_ip_auto_assign
|
self.public_ip_auto_assign = public_ip_auto_assign
|
||||||
@ -246,11 +247,13 @@ class NetworkInterface(TaggedEC2Resource):
|
|||||||
subnet = None
|
subnet = None
|
||||||
|
|
||||||
private_ip_address = properties.get('PrivateIpAddress', None)
|
private_ip_address = properties.get('PrivateIpAddress', None)
|
||||||
|
description = properties.get('Description', None)
|
||||||
|
|
||||||
network_interface = ec2_backend.create_network_interface(
|
network_interface = ec2_backend.create_network_interface(
|
||||||
subnet,
|
subnet,
|
||||||
private_ip_address,
|
private_ip_address,
|
||||||
group_ids=security_group_ids
|
group_ids=security_group_ids,
|
||||||
|
description=description
|
||||||
)
|
)
|
||||||
return network_interface
|
return network_interface
|
||||||
|
|
||||||
@ -298,6 +301,8 @@ class NetworkInterface(TaggedEC2Resource):
|
|||||||
return [group.id for group in self._group_set]
|
return [group.id for group in self._group_set]
|
||||||
elif filter_name == 'availability-zone':
|
elif filter_name == 'availability-zone':
|
||||||
return self.subnet.availability_zone
|
return self.subnet.availability_zone
|
||||||
|
elif filter_name == 'description':
|
||||||
|
return self.description
|
||||||
else:
|
else:
|
||||||
return super(NetworkInterface, self).get_filter_value(
|
return super(NetworkInterface, self).get_filter_value(
|
||||||
filter_name, 'DescribeNetworkInterfaces')
|
filter_name, 'DescribeNetworkInterfaces')
|
||||||
@ -308,9 +313,9 @@ class NetworkInterfaceBackend(object):
|
|||||||
self.enis = {}
|
self.enis = {}
|
||||||
super(NetworkInterfaceBackend, self).__init__()
|
super(NetworkInterfaceBackend, self).__init__()
|
||||||
|
|
||||||
def create_network_interface(self, subnet, private_ip_address, group_ids=None, **kwargs):
|
def create_network_interface(self, subnet, private_ip_address, group_ids=None, description=None, **kwargs):
|
||||||
eni = NetworkInterface(
|
eni = NetworkInterface(
|
||||||
self, subnet, private_ip_address, group_ids=group_ids, **kwargs)
|
self, subnet, private_ip_address, group_ids=group_ids, description=description, **kwargs)
|
||||||
self.enis[eni.id] = eni
|
self.enis[eni.id] = eni
|
||||||
return eni
|
return eni
|
||||||
|
|
||||||
@ -343,6 +348,12 @@ class NetworkInterfaceBackend(object):
|
|||||||
if group.id in _filter_value:
|
if group.id in _filter_value:
|
||||||
enis.append(eni)
|
enis.append(eni)
|
||||||
break
|
break
|
||||||
|
elif _filter == 'private-ip-address:':
|
||||||
|
enis = [eni for eni in enis if eni.private_ip_address in _filter_value]
|
||||||
|
elif _filter == 'subnet-id':
|
||||||
|
enis = [eni for eni in enis if eni.subnet.id in _filter_value]
|
||||||
|
elif _filter == 'description':
|
||||||
|
enis = [eni for eni in enis if eni.description in _filter_value]
|
||||||
else:
|
else:
|
||||||
self.raise_not_implemented_error(
|
self.raise_not_implemented_error(
|
||||||
"The filter '{0}' for DescribeNetworkInterfaces".format(_filter))
|
"The filter '{0}' for DescribeNetworkInterfaces".format(_filter))
|
||||||
|
@ -10,9 +10,10 @@ class ElasticNetworkInterfaces(BaseResponse):
|
|||||||
private_ip_address = self._get_param('PrivateIpAddress')
|
private_ip_address = self._get_param('PrivateIpAddress')
|
||||||
groups = self._get_multi_param('SecurityGroupId')
|
groups = self._get_multi_param('SecurityGroupId')
|
||||||
subnet = self.ec2_backend.get_subnet(subnet_id)
|
subnet = self.ec2_backend.get_subnet(subnet_id)
|
||||||
|
description = self._get_param('Description')
|
||||||
if self.is_not_dryrun('CreateNetworkInterface'):
|
if self.is_not_dryrun('CreateNetworkInterface'):
|
||||||
eni = self.ec2_backend.create_network_interface(
|
eni = self.ec2_backend.create_network_interface(
|
||||||
subnet, private_ip_address, groups)
|
subnet, private_ip_address, groups, description)
|
||||||
template = self.response_template(
|
template = self.response_template(
|
||||||
CREATE_NETWORK_INTERFACE_RESPONSE)
|
CREATE_NETWORK_INTERFACE_RESPONSE)
|
||||||
return template.render(eni=eni)
|
return template.render(eni=eni)
|
||||||
@ -78,7 +79,11 @@ CREATE_NETWORK_INTERFACE_RESPONSE = """
|
|||||||
<subnetId>{{ eni.subnet.id }}</subnetId>
|
<subnetId>{{ eni.subnet.id }}</subnetId>
|
||||||
<vpcId>{{ eni.subnet.vpc_id }}</vpcId>
|
<vpcId>{{ eni.subnet.vpc_id }}</vpcId>
|
||||||
<availabilityZone>us-west-2a</availabilityZone>
|
<availabilityZone>us-west-2a</availabilityZone>
|
||||||
|
{% if eni.description %}
|
||||||
|
<description>{{ eni.description }}</description>
|
||||||
|
{% else %}
|
||||||
<description/>
|
<description/>
|
||||||
|
{% endif %}
|
||||||
<ownerId>498654062920</ownerId>
|
<ownerId>498654062920</ownerId>
|
||||||
<requesterManaged>false</requesterManaged>
|
<requesterManaged>false</requesterManaged>
|
||||||
<status>pending</status>
|
<status>pending</status>
|
||||||
@ -121,7 +126,7 @@ DESCRIBE_NETWORK_INTERFACES_RESPONSE = """<DescribeNetworkInterfacesResponse xml
|
|||||||
<subnetId>{{ eni.subnet.id }}</subnetId>
|
<subnetId>{{ eni.subnet.id }}</subnetId>
|
||||||
<vpcId>{{ eni.subnet.vpc_id }}</vpcId>
|
<vpcId>{{ eni.subnet.vpc_id }}</vpcId>
|
||||||
<availabilityZone>us-west-2a</availabilityZone>
|
<availabilityZone>us-west-2a</availabilityZone>
|
||||||
<description>Primary network interface</description>
|
<description>{{ eni.description }}</description>
|
||||||
<ownerId>190610284047</ownerId>
|
<ownerId>190610284047</ownerId>
|
||||||
<requesterManaged>false</requesterManaged>
|
<requesterManaged>false</requesterManaged>
|
||||||
{% if eni.attachment_id %}
|
{% if eni.attachment_id %}
|
||||||
|
@ -161,7 +161,7 @@ def test_elastic_network_interfaces_filtering():
|
|||||||
subnet.id, groups=[security_group1.id, security_group2.id])
|
subnet.id, groups=[security_group1.id, security_group2.id])
|
||||||
eni2 = conn.create_network_interface(
|
eni2 = conn.create_network_interface(
|
||||||
subnet.id, groups=[security_group1.id])
|
subnet.id, groups=[security_group1.id])
|
||||||
eni3 = conn.create_network_interface(subnet.id)
|
eni3 = conn.create_network_interface(subnet.id, description='test description')
|
||||||
|
|
||||||
all_enis = conn.get_all_network_interfaces()
|
all_enis = conn.get_all_network_interfaces()
|
||||||
all_enis.should.have.length_of(3)
|
all_enis.should.have.length_of(3)
|
||||||
@ -189,6 +189,12 @@ def test_elastic_network_interfaces_filtering():
|
|||||||
enis_by_group.should.have.length_of(1)
|
enis_by_group.should.have.length_of(1)
|
||||||
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id]))
|
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id]))
|
||||||
|
|
||||||
|
# Filter by Description
|
||||||
|
enis_by_description = conn.get_all_network_interfaces(
|
||||||
|
filters={'description': eni3.description })
|
||||||
|
enis_by_description.should.have.length_of(1)
|
||||||
|
enis_by_description[0].description.should.equal(eni3.description)
|
||||||
|
|
||||||
# Unsupported filter
|
# Unsupported filter
|
||||||
conn.get_all_network_interfaces.when.called_with(
|
conn.get_all_network_interfaces.when.called_with(
|
||||||
filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError)
|
filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError)
|
||||||
@ -343,6 +349,106 @@ def test_elastic_network_interfaces_get_by_subnet_id():
|
|||||||
enis.should.have.length_of(0)
|
enis.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_elastic_network_interfaces_get_by_description():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-2')
|
||||||
|
ec2_client = boto3.client('ec2', region_name='us-west-2')
|
||||||
|
|
||||||
|
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
subnet = ec2.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
|
||||||
|
|
||||||
|
eni1 = ec2.create_network_interface(
|
||||||
|
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5', Description='test interface')
|
||||||
|
|
||||||
|
# The status of the new interface should be 'available'
|
||||||
|
waiter = ec2_client.get_waiter('network_interface_available')
|
||||||
|
waiter.wait(NetworkInterfaceIds=[eni1.id])
|
||||||
|
|
||||||
|
filters = [{'Name': 'description', 'Values': [eni1.description]}]
|
||||||
|
enis = list(ec2.network_interfaces.filter(Filters=filters))
|
||||||
|
enis.should.have.length_of(1)
|
||||||
|
|
||||||
|
filters = [{'Name': 'description', 'Values': ['bad description']}]
|
||||||
|
enis = list(ec2.network_interfaces.filter(Filters=filters))
|
||||||
|
enis.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_elastic_network_interfaces_describe_network_interfaces_with_filter():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-2')
|
||||||
|
ec2_client = boto3.client('ec2', region_name='us-west-2')
|
||||||
|
|
||||||
|
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
subnet = ec2.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
|
||||||
|
|
||||||
|
eni1 = ec2.create_network_interface(
|
||||||
|
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5', Description='test interface')
|
||||||
|
|
||||||
|
# The status of the new interface should be 'available'
|
||||||
|
waiter = ec2_client.get_waiter('network_interface_available')
|
||||||
|
waiter.wait(NetworkInterfaceIds=[eni1.id])
|
||||||
|
|
||||||
|
# Filter by network-interface-id
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'network-interface-id', 'Values': [eni1.id]}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(1)
|
||||||
|
response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id)
|
||||||
|
response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address)
|
||||||
|
response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description)
|
||||||
|
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'network-interface-id', 'Values': ['bad-id']}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(0)
|
||||||
|
|
||||||
|
# Filter by private-ip-address
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'private-ip-address', 'Values': [eni1.private_ip_address]}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(1)
|
||||||
|
response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id)
|
||||||
|
response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address)
|
||||||
|
response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description)
|
||||||
|
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'private-ip-address', 'Values': ['11.11.11.11']}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(0)
|
||||||
|
|
||||||
|
# Filter by sunet-id
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'subnet-id', 'Values': [eni1.subnet.id]}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(1)
|
||||||
|
response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id)
|
||||||
|
response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address)
|
||||||
|
response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description)
|
||||||
|
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'subnet-id', 'Values': ['sn-bad-id']}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(0)
|
||||||
|
|
||||||
|
# Filter by description
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'description', 'Values': [eni1.description]}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(1)
|
||||||
|
response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id)
|
||||||
|
response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address)
|
||||||
|
response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description)
|
||||||
|
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'description', 'Values': ['bad description']}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(0)
|
||||||
|
|
||||||
|
# Filter by multiple filters
|
||||||
|
response = ec2_client.describe_network_interfaces(
|
||||||
|
Filters=[{'Name': 'private-ip-address', 'Values': [eni1.private_ip_address]},
|
||||||
|
{'Name': 'network-interface-id', 'Values': [eni1.id]},
|
||||||
|
{'Name': 'subnet-id', 'Values': [eni1.subnet.id]}])
|
||||||
|
response['NetworkInterfaces'].should.have.length_of(1)
|
||||||
|
response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id)
|
||||||
|
response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address)
|
||||||
|
response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description)
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
@mock_cloudformation_deprecated
|
@mock_cloudformation_deprecated
|
||||||
def test_elastic_network_interfaces_cloudformation():
|
def test_elastic_network_interfaces_cloudformation():
|
||||||
|
Loading…
Reference in New Issue
Block a user