Chris Kiick
Chris Kiick

Reputation: 71

ansible: how to use selectattr with ipaddr filter

Using ansible 2.7.1, with netaddr installed, on MacOS, python 3.7.3.

For some reason, I can't seem to get selectattr and ipaddr to work together in ansible.

---
# simple test of ipaddr with selectattr
- hosts: localhost
  vars:
    x:
      - i: 'a'
        a: '1.2.3.4'
      - i: 'b'
        a: '192.168.3.23'
      - i: 'c'
        a: '0.0.0.0'
  tasks:
  - debug: var="x|selectattr('a', 'ipaddr','192.168.3.0/24')|list"

output:

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

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

TASK [debug] *******************************************************************
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution."}
    to retry, use: --limit @/Users/chris.kiick/IIQ/services-performance-lab/scripts/ansible/tp2.retry

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

Why doesn't this work? I can use ipaddr directly and it works with map(). Selectattr() works fine with other filters. Running with debug (-vvv) does not give any useful information. Using other host types (centos, ubuntu) doesn't make a difference.

Any ideas?

Upvotes: 3

Views: 1076

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67984

x is a list. A list has items, no attributes. An item, for example, x.1 could be tested

"{{ x.1|selectattr('a', 'ipaddr','192.168.3.0/24')|list }}"

, but selectattr does not recognize ipaddr as a test. It's a filter.

The error was: TemplateRuntimeError: no test named 'ipaddr'

There are a couple of options on how to proceed. It is possible to loop the list. The task below

- debug:
    msg: "{{ item.a|ipaddr('192.168.3.0/24') }}"
  loop: "{{ x }}"

gives

"msg": ""
"msg": "192.168.3.23"
"msg": ""

, or add the ternary filter. The task below

- debug:
    msg: "{{ item.a|ipaddr('192.168.3.0/24')|ternary( item.a, 'not in range') }}"
  loop: "{{ x }}"

gives

"msg": "not in range"
"msg": "192.168.3.23"
"msg": "not in range"

, or the tasks below

- set_fact:
    a_list: "{{ a_list|default([]) + [ item.a|ipaddr('192.168.3.0/24') ] }}"
  loop: "{{ x }}"
- debug:
    var: a_list

give a list

"a_list": [
    null, 
    "192.168.3.23", 
    null
]

Upvotes: 2

Related Questions