how to filter with variables instead of literals in ec2_instance_facts?

Trying to use ec2_instance_facts.

How do I use variables instead of literals when filtering on tags?

This works fine:

  • ec2_instance_facts:
    filters:
    “tag:Name” : “Some_name”
    register: instance_facts

But if I have the tag name and tag value in variables, I cannot get it to compile. It complains about an invalid filter.

This doesn’t work (with tag_name and tag_value assigned appropriately:

  • ec2_instance_facts:
    filters:
    “{{ tag_group }}” : “{{ tag_value }}”
    register: instance_facts

And nor does this:

  • ec2_instance_facts:
    filters:
    “{{ ‘"tag:’ + tag_name }}” : “{{ tag_value }}”
    register: instance_facts

Or a dozen other variations I’ve tried. They all just say “the filter is invalid”

How do I do this with variables?

Regards, K.

I’ve tried a LOT of things now, and have come to the conclusion that ec2_instance_facts requires a literal filter name, at least in the case of “tags:Name”.

This makes that filter essentially useless :frowning:

Please, can someone tell me I’m wrong, and how me how to filter on a tag:value pair passed in as a variable?

Thanks, K.

`

  • ec2_instance_facts:
    filters: “{{ { tag_name: tag_value } }}”

`

Thanks, flowerysong

Did you actually try that?

When I use that, I get the same error as before: An error occurred (InvalidParameterValue) when calling the DescribeInstances operation: The filter ‘GroupName’ is invalid

(“GroupName” is the value in my variable tag_name)

If you actually TRIED it and it worked, do let me know.

Here are some things that do not work:

“{{ { tag_name: tag_value } }}”

“{{ ‘"tag:’ + tag_name + ‘"’ }}” : “{{tag_value }}”

“{{ ‘tag:’ + tag_name }}” : “{{tag_value }}”

tag: “{{ tag_name + ‘:’ + tag_value }}”

tag:“{{ tag_name + ‘:’ + tag_value }}”

“{{ tag_name }}” : “{{tag_value }}”

The second last one (no space after the first colon) gives a different message: “argument filters is of type <type ‘str’> and we were unable to convert to dict: dictionary requested, could not parse JSON or key=value”}

These work - but they have a literal filter name

“tag:GroupName” : “DEMO”

“tag:GroupName” : “{{tag_value }}”

Thanks, K.

PS: There was a typo in my last message. I meant to write “… at least in the case of ‘tag:Name’”

Yes, it works. You have to construct a valid filter, and GroupName isn’t a valid filter.

`

  • hosts: localhost
    become: false
    tasks:
  • ec2_instance_facts:
    filters: “{{ { tag_name: tag_value } }}”
    vars:
    tag_name: “tag:Name”
    tag_value: “*”
  • ec2_instance_facts:
    filters: “{{ { ‘tag:’ ~ tag_name: tag_value } }}”
    vars:
    tag_name: Name
    tag_value: “*”

`

`

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [ec2_instance_facts] ******************************************************
ok: [localhost]

TASK [ec2_instance_facts] ******************************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0

`

Thank you! Those work, indeed they do. What does that “~” syntax mean?

The reason I said your earlier solution did not work one is that you did not in your first answer include the secret sauce of prefixing “tag”: to the tag name in the tag_name variable itself. When I do that, the first variant works. I should have tried that, it seems obvious in hindsight :slight_smile:

The second variant is nicer IMHO because it keeps the specifics of the filter syntax in the filter clause itself, and the actual tag name can be passed in.

Thank you so much for your assistance. The solution using ec2_instance_facts is way simpler than the solution I had working with ec2.py.

Regards, K.

http://jinja.pocoo.org/docs/2.10/templates/#other-operators
Converts all operands into strings and concatenates them.

How does “~” differ from “+”?

“{{ ‘hello’ ~ name ~ ‘there!’ }}”

vs
“{{ ‘hello’ + name + ‘there!’ }}”

?

Have you read the documentation about + ?
http://jinja.pocoo.org/docs/2.10/templates/#math

Since this is an incredibly common question, I’ve written up a short explanation with examples:
https://immensefail.tumblr.com/post/173645339395/jinja-faq-concatenation

While they’re often interchangeable, developing a habit of using the concatenation operator means that you don’t have to worry about or code around the situations where they’re not.


TASK [Addition isn't concatenation] ********************************************
ok: [localhost] => {
    "13 + 37": "50"
}

TASK [Concatenation is concatenation] ******************************************
ok: [localhost] => {
    "13 ~ 37": "1337"
}

TASK [Concatenation handles mixed types] ***************************************
ok: [localhost] => {
    "13 ~ '37'": "1337"
}

TASK [It's possible to do the coercion manually, but who wants to do that?] ****
ok: [localhost] => {
    "13 | string + '37'": "1337"
}

TASK [Addition doesn't like mixed types] ***************************************
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{13 + '37'}}): unsupported operand type(s) for +: 'int' and 'str'"}

Thank you so much! The below syntax worked for me as well.

filters: “{{ { ‘tag:’ ~ tag_name: tag_value } }}”

I had a follow up question related to this. How can I add multiple filters with one filter being “{{ { ‘tag:’ ~ tag_name: tag_value } }}”?

I am trying to add it like we do in all other cases(shown below) but it gives an error.

filters:
instance-state-name: [“running”]
“{{ { ‘tag:’ ~ tag_name: tag_value } }}”

However, I get a syntax error.

Can you please suggest what am I doing wrong?

Thanks in advance!!