Fix TagFilter
implementation in tag:GetResources
(#3366)
The `tag_filter` method has been re-arranged to mimic the actual AWS behavior: Return `True` if *any* tag matches a filter and *all* filters are matched. Python's closures are late-binding, so we have to modify the lambdas accordingly! Closes #2814
This commit is contained in:
parent
d00cefa25c
commit
c1b2c78db2
@ -113,32 +113,35 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
|
|||||||
# https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
|
# https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
|
||||||
|
|
||||||
# TODO move these to their respective backends
|
# TODO move these to their respective backends
|
||||||
filters = [lambda t, v: True]
|
filters = []
|
||||||
for tag_filter_dict in tag_filters:
|
for tag_filter_dict in tag_filters:
|
||||||
values = tag_filter_dict.get("Values", [])
|
values = tag_filter_dict.get("Values", [])
|
||||||
if len(values) == 0:
|
if len(values) == 0:
|
||||||
# Check key matches
|
# Check key matches
|
||||||
filters.append(lambda t, v: t == tag_filter_dict["Key"])
|
filters.append(lambda t, v, key=tag_filter_dict["Key"]: t == key)
|
||||||
elif len(values) == 1:
|
elif len(values) == 1:
|
||||||
# Check its exactly the same as key, value
|
# Check its exactly the same as key, value
|
||||||
filters.append(
|
filters.append(
|
||||||
lambda t, v: t == tag_filter_dict["Key"] and v == values[0]
|
lambda t, v, key=tag_filter_dict["Key"], value=values[0]: t == key
|
||||||
|
and v == value
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Check key matches and value is one of the provided values
|
# Check key matches and value is one of the provided values
|
||||||
filters.append(lambda t, v: t == tag_filter_dict["Key"] and v in values)
|
filters.append(
|
||||||
|
lambda t, v, key=tag_filter_dict["Key"], vl=values: t == key
|
||||||
|
and v in vl
|
||||||
|
)
|
||||||
|
|
||||||
def tag_filter(tag_list):
|
def tag_filter(tag_list):
|
||||||
result = []
|
result = []
|
||||||
if tag_filters:
|
if tag_filters:
|
||||||
for tag in tag_list:
|
for f in filters:
|
||||||
temp_result = []
|
temp_result = []
|
||||||
for f in filters:
|
for tag in tag_list:
|
||||||
f_result = f(tag["Key"], tag["Value"])
|
f_result = f(tag["Key"], tag["Value"])
|
||||||
temp_result.append(f_result)
|
temp_result.append(f_result)
|
||||||
result.append(all(temp_result))
|
result.append(any(temp_result))
|
||||||
|
return all(result)
|
||||||
return any(result)
|
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -293,3 +293,62 @@ def test_get_resources_s3():
|
|||||||
response_keys.remove(resource["Tags"][0]["Key"])
|
response_keys.remove(resource["Tags"][0]["Key"])
|
||||||
|
|
||||||
response_keys.should.have.length_of(0)
|
response_keys.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
@mock_resourcegroupstaggingapi
|
||||||
|
def test_multiple_tag_filters():
|
||||||
|
client = boto3.client("ec2", region_name="eu-central-1")
|
||||||
|
|
||||||
|
resp = client.run_instances(
|
||||||
|
ImageId="ami-123",
|
||||||
|
MinCount=1,
|
||||||
|
MaxCount=1,
|
||||||
|
InstanceType="t2.micro",
|
||||||
|
TagSpecifications=[
|
||||||
|
{
|
||||||
|
"ResourceType": "instance",
|
||||||
|
"Tags": [
|
||||||
|
{"Key": "MY_TAG1", "Value": "MY_UNIQUE_VALUE"},
|
||||||
|
{"Key": "MY_TAG2", "Value": "MY_SHARED_VALUE"},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ResourceType": "instance",
|
||||||
|
"Tags": [{"Key": "MY_TAG3", "Value": "MY_VALUE3"}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
instance_1_id = resp["Instances"][0]["InstanceId"]
|
||||||
|
|
||||||
|
resp = client.run_instances(
|
||||||
|
ImageId="ami-456",
|
||||||
|
MinCount=1,
|
||||||
|
MaxCount=1,
|
||||||
|
InstanceType="t2.micro",
|
||||||
|
TagSpecifications=[
|
||||||
|
{
|
||||||
|
"ResourceType": "instance",
|
||||||
|
"Tags": [
|
||||||
|
{"Key": "MY_TAG1", "Value": "MY_ALT_UNIQUE_VALUE"},
|
||||||
|
{"Key": "MY_TAG2", "Value": "MY_SHARED_VALUE"},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ResourceType": "instance",
|
||||||
|
"Tags": [{"Key": "MY_ALT_TAG3", "Value": "MY_VALUE3"}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
instance_2_id = resp["Instances"][0]["InstanceId"]
|
||||||
|
|
||||||
|
rtapi = boto3.client("resourcegroupstaggingapi", region_name="eu-central-1")
|
||||||
|
results = rtapi.get_resources(
|
||||||
|
TagFilters=[
|
||||||
|
{"Key": "MY_TAG1", "Values": ["MY_UNIQUE_VALUE"]},
|
||||||
|
{"Key": "MY_TAG2", "Values": ["MY_SHARED_VALUE"]},
|
||||||
|
]
|
||||||
|
).get("ResourceTagMappingList", [])
|
||||||
|
results.should.have.length_of(1)
|
||||||
|
instance_1_id.should.be.within(results[0]["ResourceARN"])
|
||||||
|
instance_2_id.shouldnt.be.within(results[0]["ResourceARN"])
|
||||||
|
Loading…
Reference in New Issue
Block a user