shawnjohnson
shawnjohnson

Reputation: 405

Conditional set_fact only with selectattr?

I am trying to use set_fact, but only when an item is defined. I'm having trouble figuring out how to do this.

Playbook:

---
  - hosts: localhost

    vars:
      apps:
        - name: app1
          role: "app1-role"
        - name: app2
          role: "app2-role"
        - name: app4
          role: "app4-role"

    tasks:
    - name: "Find a matching app, and print the values"
      set_fact:
        app: "{{ apps | selectattr('name', 'match', app_name) | first }}"

The task fails when there is no match, for example: app_name=app3, with this message:

FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: No first item, sequence was empty.

I have tried a few different conditionals, but I'm not quite sure how to structure this.

      when: (apps | selectattr('name', 'match', app_name)) is undefined

This condition always evaluates as False - skipping: [localhost] => {"changed": false, "skip_reason": "Conditional result was False"}.

Upvotes: 1

Views: 2129

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68044

Try

      - set_fact:
          app: "{{ mylist|first }}"
        vars:
          mylist: "{{ apps|selectattr('name', 'match', app_name)|list }}"
        when: mylist|length > 0

Next option is json_query instead of selectattr

      - set_fact:
          app: "{{ mylist|first }}"
        vars:
          query: "[?name=='{{ app_name }}']"
          mylist: "{{ apps|json_query(query) }}"
        when: mylist|length > 0

Upvotes: 0

rolf82
rolf82

Reputation: 1581

I tried this :

when: "{{ apps | selectattr('name', 'match', app_name) | list }}"

It seems that without the list filter, selectattr returning a generator object does not seem to allow converting to a boolean for the test evaluation. I'm not 100% sure about this interpretation though.

Note that having is defined or not would not change anything, it would be totally equivalent.

Upvotes: 1

Related Questions