I have the following variables in Ansible:
my_allowed_hosts2:
- {host: patch, address: '202.167.24.50'}
- {host:localhost, address: '::1/128', extra_field: trust}
my_ferm_groups:
- firewall_whitelist1
- firewall_whitelist2
I have a task that checks if there are valid IP addresses in my_allowed_hosts2
and if so, generate a template for it (in this case, the host I'm running the playbook against is in firewall_whitelist2
group in my inventory). This template is then used to generate ferm/iptable rules to allow the IP addresses in my_allowed_hosts2
to access the host.
However, if there is no valid address in my_allowed_hosts2
, I don't want to generate a template for it (firewall_whitelist_2
) even though myhost
is a valid member of that group - because if it has no valid IP addresses that the template will become invalid. Hope I'm making sense so far.
The relevant tasks :
- set_fact:
valid_addresses: "{{ my_allowed_hosts2|json_query('[*].address')| map('ipaddr')|reject('match','^127.0.0.1|::1/128') | list }}"
- debug:
msg: "{{ valid_addresses }}"
- name: Loop dictionary and copy group configs in place
template: src=etc/ferm/ferm.d/{{ item }}.j2 dest=/etc/ferm/ferm.d/{{ item }}.conf owner=root group=root mode=0640
when: item in my_ferm_groups
with_items: "{{ group_names | reject ('match','^firewall_whitelist2$') if valid_addresses is not any }}"
What I was trying to do above is trying to remove firewall_whitelist2
from the loop if there is no true
value tested in my_allowed_hosts2
list - thus preventing it to create that particular template.
However, I receive the following error :
fatal: [myhost]: FAILED! => { "msg": "the inline if-expression on line 1 evaluated to false and no else section was defined." }
What I am expecting (IF valid_addresses
is not empty) is something like the below. The template gets copied accordingly:
ok: [myhost] => (item=firewall_whitelist1) => {"ansible_loop_var": "item", "changed": false, "checksum": "21f42490d91da92c6f404a30df6e34373266b72f", "dest": "/etc/ferm/ferm.d/firewall_whitelist1.j2", "gid": 0, "group": "root", "item": "firewall_whitelist1", "mode": "0640", "owner": "root", "path": "/etc/ferm/ferm.d/firewall_whitelist1.conf", "secontext": "system_u:object_r:etc_t:s0", "size": 570, "state": "file", "uid": 0} changed: [myhost] => (item=firewall_whitelist2) => {"ansible_loop_var": "item", "changed": false, "checksum": "985d207faa196b285c20c7f60f6aa69b23f908b9", "dest": "/etc/ferm/ferm.d/firewall_whitelist2.j2, "gid": 0, "group": "root", "item": "firewall_whitelist2", "mode": "0640", "owner": "root", "path": "/etc/ferm/ferm.d/firewall_whitelist2.conf", "secontext": "system_u:object_r:etc_t:s0", "size": 705, "state": "file", "uid": 0}
I tried this too in an effort to add firewall_whitelist2
to the list so the template only gets generated when valid_addresses
is not empty:
- name: Loop dictionary and copy group configs in place
template: src=etc/ferm/ferm.d/{{ item }}.j2 dest=/etc/ferm/ferm.d/{{ item }}.conf owner=root group=root mode=0640
when: item in my_ferm_groups
loop: "{{ group_names + 'firewall_whitelist2' if valid_addresses|length > 0 else group_names }}"
But this errors out with
FAILED! => {"msg": "Unexpected templating type error occurred on ({{ group_names + 'firewall_whitelist2' if valid_addresses|length > 0 else group_names }}): can only concatenate list (not \"str\") to list"}`
Any idea how can I make this work?
Basically I'm trying to find a way to only generate that template for firewall_whitelist_2
ONLY IF the condition matches (valid IP addresses detected in my_allowed_hosts2
).
Any nudge in the right direction would help.
Makes me feel like you are trying to fit in the loop
what should be in the when
.
So in the ultimate end you will probably loop on an empty array, when you could as well loop on a populated list and skip all items.
When moving all those conditions in the when
, we could end up with:
- template:
src: /etc/ferm/ferm.d/{{ item }}.j2
dest: /etc/ferm/ferm.d/{{ item }}.conf
owner: root
group: root
mode: 0640
when:
- item in my_ferm_groups
- item != 'firewall_whitelist2' or valid_addresses|length > 0
loop: "{{ group_names }}"
Here is are two examples of this:
- hosts: all
gather_facts: no
tasks:
- debug:
msg: "{{ item }}"
when:
- item in my_ferm_groups
- item != 'firewall_whitelist2' or valid_addresses|length > 0
loop: "{{ group_names }}"
vars:
valid_addresses: []
group_names:
- firewall_whitelist1
- firewall_whitelist2
- firewall_whitelist3
- firewall_whitelist4
my_ferm_groups:
- firewall_whitelist1
- firewall_whitelist2
- firewall_whitelist3
This gives the recap:
PLAY [all] *******************************************************************************************************
TASK [debug] *****************************************************************************************************
ok: [localhost] => (item=firewall_whitelist1) => {
"msg": "firewall_whitelist1"
}
skipping: [localhost] => (item=firewall_whitelist2)
ok: [localhost] => (item=firewall_whitelist3) => {
"msg": "firewall_whitelist3"
}
skipping: [localhost] => (item=firewall_whitelist4)
PLAY RECAP *******************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- hosts: all
gather_facts: no
tasks:
- debug:
msg: "{{ item }}"
when:
- item in my_ferm_groups
- item != 'firewall_whitelist2' or valid_addresses|length > 0
loop: "{{ group_names }}"
vars:
valid_addresses:
- 10.1.1.1
group_names:
- firewall_whitelist1
- firewall_whitelist2
- firewall_whitelist3
- firewall_whitelist4
my_ferm_groups:
- firewall_whitelist1
- firewall_whitelist2
- firewall_whitelist3
This gives the recap:
PLAY [all] *******************************************************************************************************
TASK [debug] *****************************************************************************************************
ok: [localhost] => (item=firewall_whitelist1) => {
"msg": "firewall_whitelist1"
}
ok: [localhost] => (item=firewall_whitelist2) => {
"msg": "firewall_whitelist2"
}
ok: [localhost] => (item=firewall_whitelist3) => {
"msg": "firewall_whitelist3"
}
skipping: [localhost] => (item=firewall_whitelist4)
PLAY RECAP *******************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
With all this, the valid_addresses
you are populating stays as you have it right now.