Reputation: 825
In an ansible playbook I want to loop a task over a set of usernames from one list only if the username or username followed by a suffix '.A' occurs in another list.
Sample playbook that fails:
---
- hosts: localhost
vars:
- users1:
- alice
- alice.A
- bob
- santa
- users2:
- alice
tasks:
- debug:
msg: "Do something for {{ item }} realname {{ item | regex_replace('^([a-z]+)\\.[aA]$', '\\1') }}"
loop: "{{ users1 }}"
when:
- "item | regex_replace('^([a-z]+)\\.[aA]$', '\\1') in users2"
This version skips alice.A
while the regex_replace
filter in the task itself returns alice
as expected.
Actual output:
TASK [debug] ***************
ok: [localhost] => (item=alice) => {}
MSG:
Do something for alice realname alice
skipping: [localhost] => (item=alice.A)
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
Desired output:
TASK [debug] ***************
ok: [localhost] => (item=alice) => {}
MSG:
Do something for alice realname alice
Do something for alice.A realname alice
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
Is it possible to apply a filter to the item to be tested?
If not is there a way to use something like map()
to duplicate the entries in the users2
list appending the '.A' suffix to each item?
When conditions I have tried that all fail:
when: ("item in users2 | flatten(1)") or
("item|regex_search('\.A$')")
when:
- "item | regex_replace('^([a-z]+\\.[a-z]+).[aA]$', '\\1') in users | flatten(1)"
when:
- "item in users | flatten(1) | map('regex_replace','^([a-z]+\\.[a-z]+)$', '\\1.A')"
when:
- "item | map('regex_replace','^([a-z]+\\.[a-z]+).[aA]$', '\\1') in users | flatten(1)"
when:
- "item|map('upper') in users | flatten(1)"
The last one just to check whether the item tested was modified by the filter or not. (It is not AFAICT.)
Upvotes: 1
Views: 1060
Reputation: 67984
Regex is not needed. Use splitext to get the realname and test its presence in the list users2
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|splitext|first }}"
gives the expected results
TASK [debug] ********************************************************
ok: [localhost] => (item=alice) =>
msg: Do something for alice realname alice.
ok: [localhost] => (item=alice.A) =>
msg: Do something for alice.A realname alice.
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
You say you
want to loop a task over a set of usernames from one list only if the username or username is followed by a suffix '.A'
The task above will accept any suffix not only '.A'. Test also the suffix to fix it. The task below gives the same result
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when:
- realname in users2
- suffix == '.A'
vars:
arr: "{{ item|splitext|list }}"
realname: "{{ arr.0 }}"
suffix: "{{ arr.1|default('.A', true) }}"
If you want to use regex change the variables below. This will give the same results.
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|regex_replace(regex, replace) }}"
regex: '^(.*?)(\.A)*$'
replace: '\1'
Update
Optionally, create the structure first and simplify the code in the tasks
users3_str: |
{% for u in users1 %}
{% set arr = u|splitext|list %}
- name: {{ u }}
realname: {{ arr.0 }}
suffix: {{ arr.1|default('.A', true) }}
{% endfor %}
users3: "{{ users3_str|from_yaml }}"
gives
users3:
- {name: alice, realname: alice, suffix: .A}
- {name: alice.A, realname: alice, suffix: .A}
- {name: bob, realname: bob, suffix: .A}
- {name: santa, realname: santa, suffix: .A}
Then, the tasks below give the same results
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2) }}"
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2)|
selectattr('suffix', '==', '.A') }}"
Example of a complete playbook for testing
- hosts: localhost
vars:
users1:
- alice
- alice.A
- bob
- santa
users2:
- alice
users3_str: |
{% for u in users1 %}
{% set arr = u|splitext|list %}
- name: {{ u }}
realname: {{ arr.0 }}
suffix: {{ arr.1|default('.A', true) }}
{% endfor %}
users3: "{{ users3_str|from_yaml }}"
tasks:
- debug:
var: users3|to_yaml
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2) }}"
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2)|
selectattr('suffix', '==', '.A') }}"
Upvotes: 2