From 20e00dd0954ed332ba53cfb37227f12450258b51 Mon Sep 17 00:00:00 2001 From: Kieran Doonan Date: Tue, 5 Jul 2016 11:20:28 +0100 Subject: [PATCH 1/4] added tests for broken tag filter --- tests/test_ec2/test_tags.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_ec2/test_tags.py b/tests/test_ec2/test_tags.py index d8b585842..adf2a697b 100644 --- a/tests/test_ec2/test_tags.py +++ b/tests/test_ec2/test_tags.py @@ -345,3 +345,17 @@ def test_retrieved_snapshots_must_contain_their_tags(): # Check whether tag is present with correct value retrieved_tags[tag_key].should.equal(tag_value) + + +@mock_ec2 +def test_filter_instances_by_tags(): + conn = boto.connect_ec2(aws_access_key_id='the_key', aws_secret_access_key='the_secret') + reservation = conn.run_instances('ami-1234abcd') + instance_a = reservation.instances[0] + instance_a.add_tag("Key1", "Value1") + reservation_b = conn.run_instances('ami-1234abcd') + instance_b = reservation_b.instances[0] + instance_b.add_tag("Key1", "Value2") + + reservations = conn.get_all_instances(filters={'tag:Key1': 'Value*'}) + reservations.should.have.length_of(2) From d3dcb8d3b5c221a86b64f2a33c4019694fb7a599 Mon Sep 17 00:00:00 2001 From: Kieran Doonan Date: Tue, 5 Jul 2016 11:28:35 +0100 Subject: [PATCH 2/4] tag_filter_matches now uses regex for key/value matches --- moto/ec2/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index e07367081..d8bc6528a 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -348,8 +348,10 @@ def tag_filter_matches(obj, filter_name, filter_values): tag_values = get_obj_tag_values(obj) return len(set(filter_values).intersection(tag_values)) > 0 else: - tag_value = get_obj_tag(obj, filter_name) - return tag_value in filter_values + import re + tag_value = get_obj_tag(obj, filter_name) or '' + regex_filters = [re.compile(simple_aws_filter_to_re(f)) for f in filter_values] + return any(regex.match(tag_value) for regex in regex_filters) filter_dict_attribute_mapping = { From 5f770ffabbb8bef424a95f4e36215d3ffe1f60e9 Mon Sep 17 00:00:00 2001 From: Kieran Doonan Date: Tue, 5 Jul 2016 11:31:47 +0100 Subject: [PATCH 3/4] added more wildcard test for tags --- tests/test_ec2/test_tags.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_ec2/test_tags.py b/tests/test_ec2/test_tags.py index adf2a697b..a25d31e2d 100644 --- a/tests/test_ec2/test_tags.py +++ b/tests/test_ec2/test_tags.py @@ -348,7 +348,7 @@ def test_retrieved_snapshots_must_contain_their_tags(): @mock_ec2 -def test_filter_instances_by_tags(): +def test_filter_instances_by_wildcard_tags(): conn = boto.connect_ec2(aws_access_key_id='the_key', aws_secret_access_key='the_secret') reservation = conn.run_instances('ami-1234abcd') instance_a = reservation.instances[0] @@ -359,3 +359,9 @@ def test_filter_instances_by_tags(): reservations = conn.get_all_instances(filters={'tag:Key1': 'Value*'}) reservations.should.have.length_of(2) + + reservations = conn.get_all_instances(filters={'tag-key': 'Key*'}) + reservations.should.have.length_of(2) + + reservations = conn.get_all_instances(filters={'tag-value': 'Value*'}) + reservations.should.have.length_of(2) From 619255e25aa08d335130d34a781f498dabc352e5 Mon Sep 17 00:00:00 2001 From: Kieran Doonan Date: Tue, 5 Jul 2016 11:44:39 +0100 Subject: [PATCH 4/4] tag-key and tag-value filters now do a regex match --- moto/ec2/utils.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index d8bc6528a..d9ebb4258 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -341,17 +341,19 @@ def get_obj_tag_values(obj): return tags def tag_filter_matches(obj, filter_name, filter_values): + regex_filters = [re.compile(simple_aws_filter_to_re(f)) for f in filter_values] if filter_name == 'tag-key': - tag_names = get_obj_tag_names(obj) - return len(set(filter_values).intersection(tag_names)) > 0 + tag_values = get_obj_tag_names(obj) elif filter_name == 'tag-value': tag_values = get_obj_tag_values(obj) - return len(set(filter_values).intersection(tag_values)) > 0 else: - import re - tag_value = get_obj_tag(obj, filter_name) or '' - regex_filters = [re.compile(simple_aws_filter_to_re(f)) for f in filter_values] - return any(regex.match(tag_value) for regex in regex_filters) + tag_values = [get_obj_tag(obj, filter_name) or ''] + + for tag_value in tag_values: + if any(regex.match(tag_value) for regex in regex_filters): + return True + + return False filter_dict_attribute_mapping = {