AWS CLI filter bug - filters being OR'ed, not AND'ed

0

When using the CLI to query subnets, filters are being OR'ed, while the Filter documentation clearly states that they are supposed to be AND'ed:

If you specify multiple filters, the filters are joined with an AND, and the request returns only results that match all of the specified filters.

For example (VPC and subnet ids have been anonymized):

aws --region eu-west-1 ec2 describe-subnets  --filter Name=vpc-id,Values=vpc-1 --filter Name=tag:Type,Values=private | jq  '[ .Subnets[] | select(.Tags[].Key == "Name") | select(.Tags[].Value | contains("default")) | {id: .SubnetId, vpc: .VpcId, name: (.Tags[]|select(.Key=="Name")|.Value), type: (.Tags[]|select(.Key=="Type")|.Value) } ]'

This is supposed to give back subnets that have VpcId "vpc-1" AND tag:Type "private", but instead I get a list of subnets from 3 different VPCs

[
  { "id": "subnet-1", "vpc": "vpc-1", "name": "private/default/a", "type": "private" },
  { "id": "subnet-2", "vpc": "vpc-1", "name": "private/default/b", "type": "private" },
  { "id": "subnet-3", "vpc": "vpc-1", "name": "private/default/c", "type": "private" },
  { "id": "subnet-4", "vpc": "vpc-2", "name": "private/default/a", "type": "private" },
  { "id": "subnet-5", "vpc": "vpc-2", "name": "private/default/b", "type": "private" },
  { "id": "subnet-6", "vpc": "vpc-2", "name": "private/default/c", "type": "private" },
  { "id": "subnet-7", "vpc": "vpc-3", "name": "private/default/a", "type": "private" },
  { "id": "subnet-8", "vpc": "vpc-3", "name": "private/default/b", "type": "private" },
  { "id": "subnet-9", "vpc": "vpc-3", "name": "private/default/c", "type": "private" }
]

I saw this behavior on CLI v.2.8.13, and then upgraded to 2.11.11 and am still seeing it.

I tried the exact same query in Python using boto3, and got the correct behavior:

>>> client = boto3.client(service_name='ec2', region_name='eu-west-1')
>>> for subnet in client.describe_subnets(Filters=[{'Name': 'vpc-id', 'Values': ['vpc-1']}, {'Name': 'tag:Type', 'Values': ['private']}])['Subnets']:
...     name = [tag['Value'] for tag in subnet['Tags'] if tag['Key'] == 'Name']
...     type = [tag['Value'] for tag in subnet['Tags'] if tag['Key'] == 'Type']
...     print(f"id={subnet['SubnetId']}, vpc={subnet['VpcId']}, {name=}, {type=}")
...
id=subnet-1, vpc=vpc-1, name=['private/default/a'], type=['private']
id=subnet-2, vpc=vpc-1, name=['private/default/b'], type=['private']
id=subnet-3, vpc=vpc-1, name=['private/default/c'], type=['private']
已提问 1 年前386 查看次数
2 回答
0
已接受的回答

Put them under one filter to get the AND:

aws --region eu-west-1 ec2 describe-subnets  \
--filter Name=vpc-id,Values=vpc-1 Name=tag:Type,Values=private \
| jq  '[ .Subnets[] | select(.Tags[].Key == "Name") | select(.Tags[].Value | contains("default")) | {id: .SubnetId, vpc: .VpcId, name: (.Tags[]|select(.Key=="Name")|.Value), type: (.Tags[]|select(.Key=="Type")|.Value) } ]'

The AND behavior is documented and the reference to multiple filters makes sense in the context of a list:

If you specify multiple filters, the filters are joined with an AND , and the request returns only results that match all of the specified filters.

What seems to be undocumented is the OR with multiple --filters.

profile pictureAWS
专家
kentrad
已回答 1 年前
  • Thanks! That's not at all clear from the documentation. To my mind, --filter <filter1> --filter <filter2> should either give an error or should work exactly the same as --filter <filter1> <filter2>. Most shell commands I'm used to take the former approach (e.g., sed -e 'script1' -e 'script2', not sed -e 'script1' 'script2'), so it actually never occurred to me to just put multiple filters after one --filter.

0

I think the last filter takes precedence, out of multiple --filter options. Instead of

--filter Name=vpc-id,Values=vpc-1 --filter Name=tag:Type,Values=private

Try

--filter Name=vpc-id,Values=vpc-1 Name=tag:Type,Values=private
已回答 2 个月前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则