From 38124ab1c9e6c0039c838860ae291dfeeda30ac6 Mon Sep 17 00:00:00 2001 From: Brian Pandola Date: Sun, 24 Jan 2021 04:00:25 -0800 Subject: [PATCH] Fix ec2 filter by empty tag value (#3605) * Fix ec2 filter by empty tag value Return `None` instead of an empty string when the tag key does not exist and replace the falsy check with a more explicit `is None`, which allows empty string values to correctly pass through the filter comparator. Behavior confirmed against a real AWS backend. Closes #3603 * Make test case more explicit Test case now pulled directly from the issue report (#3603). Co-authored-by: Bert Blommers --- moto/ec2/models.py | 2 +- moto/ec2/utils.py | 2 +- tests/test_ec2/test_amis.py | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/moto/ec2/models.py b/moto/ec2/models.py index dbbfb2838..a569ae186 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -249,7 +249,7 @@ class TaggedEC2Resource(BaseModel): if tag["key"] == tagname: return tag["value"] - return "" + return None elif filter_name == "tag-key": return [tag["key"] for tag in tags] elif filter_name == "tag-value": diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index 4a101f923..76d788bd4 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -458,7 +458,7 @@ def filter_internet_gateways(igws, filter_dict): def is_filter_matching(obj, filter, filter_value): value = obj.get_filter_value(filter) - if not filter_value: + if filter_value is None: return False if isinstance(value, six.string_types): diff --git a/tests/test_ec2/test_amis.py b/tests/test_ec2/test_amis.py index 8ea4cb865..ac0e7fe11 100644 --- a/tests/test_ec2/test_amis.py +++ b/tests/test_ec2/test_amis.py @@ -921,3 +921,44 @@ def test_create_image_with_tag_specification(): ex.value.response["Error"]["Message"].should.equal( "'invalid-resource-type' is not a valid taggable resource type for this operation." ) + + +@mock_ec2 +def test_ami_filter_by_empty_tag(): + ec2 = boto3.resource("ec2", region_name="us-west-1") + client = boto3.client("ec2", region_name="us-west-1") + + fake_images = [] + instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] + for i in range(10): + image = client.create_image( + InstanceId=instance.instance_id, + Name="MyAMI{}".format(i), + Description="Test", + ) + + ec2.create_tags( + Resources=[image["ImageId"]], + Tags=[ + { + "Key": "Base_AMI_Name", + "Value": "Deep Learning Base AMI (Amazon Linux 2) Version 31.0", + }, + {"Key": "OS_Version", "Value": "AWS Linux 2"}, + ], + ) + fake_images.append(image) + # Add release tags to some of the images in the middle + for image in fake_images[3:6]: + ec2.create_tags( + Resources=[image["ImageId"]], Tags=[{"Key": "RELEASE", "Value": ""}] + ) + images_filter = [ + { + "Name": "tag:Base_AMI_Name", + "Values": ["Deep Learning Base AMI (Amazon Linux 2) Version 31.0"], + }, + {"Name": "tag:OS_Version", "Values": ["AWS Linux 2"]}, + {"Name": "tag:RELEASE", "Values": [""]}, + ] + assert len(client.describe_images(Filters=images_filter)["Images"]) == 3