When I execute ansible playbook with this command and extra vars as
ansible-playbook controller_config/windows_domain_names.yml -e "target_win_host=testserver.testdomain.com"
with one task inside it
- name: Find if the variable target_win_host is a list
debug:
msg: "{{ item }} is list data type"
loop: "{{ target_win_host}}"
when: target_win_host | type_debug == 'list'
I got the error as
"Invalid data passed to 'loop', it requires a list, got this instead: testserver.testdomain.com. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
I expect the above block should be skipped as this does not meet the condition that variable is a list and that its a scalar (string).
I tried with different condition as below
- name: Find if the variable target_win_host is a list
debug:
msg: "{{ item }} is list data type"
loop: "{{ target_win_host}}"
when: target_win_host is not string and target_win_host is iterable and target_win_host is sequence
but same error as above.
You approach won't work because for the given task, the loop
expression is first evaluated, the first item is extracted and only then the when:
condition is evaluated (once for each loop iteration).
In other words, for your approach to work, you need to somehow embed the condition in the loop:
expression and make it result to a zero length list.
The following task achieves that goal:
- name: Loop over target_win_host if it is a list
debug:
msg: "{{ item }} is part of a list of hosts"
loop: "{{ target_win_host if target_win_host | type_debug == 'list' else [] }}"
Meanwhile if you'd rather play the same task for all hosts whether they are given as a list or as a single host string, this is probably better:
- name: Loop over hosts in target_win_host whether it is a list or a single host string
debug:
msg: "{{ item }} was given as one the hosts"
loop: "{{ [target_win_host] | flatten }}"
This is a full playbook to test both options:
---
- name: Conditional and loops
hosts: localhost
gather_facts: false
vars:
# default value as a list. Override with extra vars
target_win_host:
- host1.example.com
- host2.example.com
tasks:
- name: Loop over target_win_host if it is a list
debug:
msg: "{{ item }} is part of a list of hosts"
loop: "{{ target_win_host if target_win_host | type_debug == 'list' else [] }}"
- name: Loop over hosts in target_win_host whether it is a list or a single host string
debug:
msg: "{{ item }} was given as one of the hosts"
loop: "{{ [target_win_host] | flatten }}"
Which gives:
$ ansible-playbook test.yml
PLAY [Conditional and loops] *************************************************************************************************************************************************************************************
TASK [Loop over target_win_host if it is a list] *********************************************************************************************************************************************************************
ok: [localhost] => (item=host1.example.com) => {
"msg": "host1.example.com is part of a list of hosts"
}
ok: [localhost] => (item=host2.example.com) => {
"msg": "host2.example.com is part of a list of hosts"
}
TASK [Loop over hosts in target_win_host whether it is a list or a single host string] *****************************************************************************************************************************
ok: [localhost] => (item=host1.example.com) => {
"msg": "host1.example.com was given as one of the hosts"
}
ok: [localhost] => (item=host2.example.com) => {
"msg": "host2.example.com was given as one of the hosts"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook test.yml -e target_win_host=a.single.host
PLAY [Conditional and loops] *************************************************************************************************************************************************************************************
TASK [Loop over target_win_host if it is a list] *********************************************************************************************************************************************************************
skipping: [localhost]
TASK [Loop over hosts in target_win_host whether it is a list or a single host string] *****************************************************************************************************************************
ok: [localhost] => (item=a.single.host) => {
"msg": "a.single.host was given as one of the hosts"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0