Phil
Phil

Reputation: 63

AWS describe-instances filter by tag and exclude by tag

In the new AWS console I can do inverse search, i.e.: search that does not match a certain value, with a filter.

I am trying to achieve the same using the AWS cli v2. It's straight forward to filter by tag but how do I exclude a tag at the same time?

aws ec2 describe-instances \
  --query 'Reservations[].Instances[].[InstanceId]' \
  --filter "Name=tag:MYTAG,Values=MYVALUE" \
  --output text

I'm trying to get a list of instances with a certain tag but at the same time exclude some of those instances based on another tag.

For example: Lets say I have instances with the following tags:

tag: env | value: dev
tag: eks | value: true

I want to build a list of instances with the key-value pair of env/dev but want to exclude them if they also have the key-value pair of eks/true.

I can see JMESPath has a boolean for contains but I'm struggling to get anywhere with it.

Upvotes: 6

Views: 3224

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39079

Using contains will not really lead you anywhere, because, the mere fact that the Tags array contains "Key": "eks", won't tell you much without the associated value.
And if you go on dissociating the Key and Value, it will be a nightmare to find back which is what.

Here is an oversimplified example to actually do the tag filtering — in an inclusive way:

Reservations[]
.Instances[?
  Tags[?Key == `env` && Value == `dev`]
].[InstanceId]

With this, we are stating that we want all instances having a tag object that would have both its Key equal to env and its Value equal to dev.

Now, we can add an and expression and further filter it

Reservations[]
.Instances[?
  Tags[?Key == `env` && Value == `dev`]
  && Tags[?Key == `eks` && Value == `false`]
].[InstanceId]

Now, we also account for the object having the tag eks with a value of false.

You will still miss some case with this, though, because you also have to account for instances that are totally missing the eks tag. And this one is a bit trickier:

Reservations[]
.Instances[?
  Tags[?Key == `env` && Value == `dev`] 
  && (
    !not_null(Tags[?Key == `eks`]) 
    || Tags[?Key == `eks` && Value == `false`]
  )
].[InstanceId]

Ends up being the final expression you need. We added here an or expression that allows our previous query to also filter instances that do not have an eks tag, with a double negation (we do not want any object that have a non-empty array of eks tags, so we want all the one that do have an empty eks array).

So, your command line ends up being:

aws ec2 describe-instances \
  --query 'Reservations[]
    .Instances[?
      Tags[?Key == `env` && Value == `dev`] 
      && (
        !not_null(Tags[?Key == `eks`]) 
        || Tags[?Key == `eks` && Value == `false`]
      )
    ].[InstanceId]' \
  --output text

Side note: A further simplification of the above query could be

Reservations[]
.Instances[?
  Tags[?Key == `env` && Value == `dev`] 
  && (
    !not_null(Tags[?Key == `eks`]) 
    || Tags[?Key == `eks` && !Value]
  )
].[InstanceId]

As the Value field should be a boolean already, we can just negate it with a not expression.

Upvotes: 7

Related Questions