Related
Trying to get a variable defined when the task is partially failed/ignored. When a VM is not found in Vsphere it throws an error: "msg": "Unable to gather information for non-existing VM vm2"
I tried with and without ignore_errors: True and failed_when: 0 > 1 but no change.
I need the variable vm_fact to be defined even when a non-existing VM is in the decom_list. The plan is to change the list after i have identified which VM's are non-existing.
Please note: this task does work when all vm's are present in the system. When one is missing the task fails. I need the task not to fail so that i can clean the decom_list and then run it again.
- name: check/power(on/off) hosts on vsphere
hosts: localhost
ignore_errors: True
vars:
decom_list:
- vm1
- vm2
- vm3
tasks:
- name: check hosts on vsphere
vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
name: "{{ item }}"
schema: vsphere
datacenter: DC1
loop: "{{ decom_list }}"
register: vm_fact
ignore_errors: True
failed_when: 0 > 1
Whatever i try does not work because my vm_fact is not defined.
- debug:
var: "{{ vm_fact }}"
error:
TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
"<class 'dict'>": "VARIABLE IS NOT DEFINED!"
}
Just to confirm i did try all i know.
When i try it with a loop:
- debug:
var: "{{ item['item'] }}"
loop: "{{ vm_fact['results'] }}"
when: '"Unable to gather information for non-existing VM" in item.msg'
I get error:
ok: [localhost] => (item={'failed': False, 'msg': 'Unable to gather information for non-existing VM vm2', 'invocation': {'module_args': {'hostname': 'hostname.domain', 'username': 'username', 'password': 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER', 'name': 'vm2', 'schema': 'vsphere', 'datacenter': 'DC1', 'port': 443, 'validate_certs': True, 'name_match': 'first', 'use_instance_uuid': False, 'tags': False, 'tag_details': False, 'proxy_host': None, 'proxy_port': None, 'uuid': None, 'moid': None, 'folder': None, 'properties': None}}, 'changed': False, 'failed_when_result': False, 'item': 'vm2', 'ansible_loop_var': 'item'}) => {
"ansible_loop_var": "item",
"item": {
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"datacenter": "DC1",
"folder": null,
"hostname": "hostname.domain",
"moid": null,
"name": "vm2",
"name_match": "first",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"properties": null,
"proxy_host": null,
"proxy_port": null,
"schema": "vsphere",
"tag_details": false,
"tags": false,
"use_instance_uuid": false,
"username": "username",
"uuid": null,
"validate_certs": true
}
},
"item": "vm2",
"msg": "Unable to gather information for non-existing VM vm2"
},
"vm2": "VARIABLE IS NOT DEFINED!"
}
ok: [localhost] => (item={'failed': False, 'msg': 'Unable to gather information for non-existing VM vm3', 'invocation': {'module_args': {'hostname': 'hostname.domain', 'username': 'username', 'password': 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER', 'name': 'vm3', 'schema': 'vsphere', 'datacenter': 'DC1', 'port': 443, 'validate_certs': True, 'name_match': 'first', 'use_instance_uuid': False, 'tags': False, 'tag_details': False, 'proxy_host': None, 'proxy_port': None, 'uuid': None, 'moid': None, 'folder': None, 'properties': None}}, 'changed': False, 'failed_when_result': False, 'item': 'vm3', 'ansible_loop_var': 'item'}) => {
"ansible_loop_var": "item",
"item": {
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"datacenter": "DC1",
"folder": null,
"hostname": "hostname.domain",
"moid": null,
"name": "vm3",
"name_match": "first",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"properties": null,
"proxy_host": null,
"proxy_port": null,
"schema": "vsphere",
"tag_details": false,
"tags": false,
"use_instance_uuid": false,
"username": "username",
"uuid": null,
"validate_certs": true
}
},
"item": "vm3",
"msg": "Unable to gather information for non-existing VM vm3"
},
"vm3": "VARIABLE IS NOT DEFINED!"
}
fatal: [localhost]: FAILED! => {"msg": "The conditional check '\"Unable to gather information for non-existing VM\" in item.msg' failed. The error was: error while evaluating conditional (\"Unable to gather information for non-existing VM\" in item.msg): 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 33, column 24, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n # - debug: var=vm_fact\n ^ here\n\nThere appears to be both 'k=v' shorthand syntax and YAML in this task. Only one syntax may be used.\n"}
Tried:
- debug:
msg: "{{ vm_fact['results']|json_query('msg') }}"
- debug:
msg: "{{ vm_fact['results']|to_json|from_json|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|dict2items|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|flatten|map(attribute='msg') }}"
error:
TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
"msg": ""
}
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 42, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 45, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{ vm_fact['results']|dict2items|map(attribute='msg') }}): dict2items requires a dictionary, got <class 'list'> instead."}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'lcoation': line 51, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
...ignoring
You are, frankly, making things very difficult for yourself. Ansible loops through hosts, use it.
decom.inv:
[decom]
vm1
vm2
vm3
decom.yml:
- name: check/power(on/off) hosts on vsphere
hosts: decom
gather_facts: no
tasks:
- name: check hosts on vsphere
vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
name: "{{ ansible_hostname }}"
schema: vsphere
datacenter: DC1
register: vm_fact
ignore_errors: True
failed_when: false
delegate_to: localhost
- name: Show results
debug:
var: vm_fact
I want to hide the result message of with_sequence:
My task playbook :
- name: Alarm check
debug: msg="Alarm check"
when: '"{{ item }} alarms currently active" in HOST_MGMT1.stdout'
register: result_alarm
with_sequence: start=0 end=10
result output message:
##########_QFX10K_##########
Current time: 2020-03-13 11:34:58 KST
{All items completed', 'changed': False, 'results': [{'item': u'0', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'1', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'2', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {Alarm check', 'item': u'3', 'ansible_loop_var': u'item', 'changed': False, 'failed': False}, {'item': u'4', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'5', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'6', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'7', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'8', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'9', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}, {'item': u'10', 'skipped': True, 'ansible_loop_var': u'item', 'changed': False, 'skip_reason': u'Conditional result was False'}]}
Try skippy callback plugin. For example the playbook
shell> cat playbook.yml
- hosts: localhost
vars:
HOST_MGMT1:
stdout: "3 alarms currently active"
tasks:
- name: Alarm check
debug: msg="Alarm check"
when: "my_item in HOST_MGMT1.stdout"
register: result_alarm
with_sequence: start=0 end=10
vars:
my_item: "{{ item }} alarms currently active"
gives (abbridged)
shell> export ANSIBLE_STDOUT_CALLBACK=skippy
shell> ansible-playbook playbook.yml
PLAY [localhost] ***
TASK [Alarm check] ***
ok: [localhost] => (item=3) => {
"msg": "Alarm check"
}
PLAY RECAP ***
localhost: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I try to do :
Get a list of docker containers
Shutdown this list (with async values to go to next task without waiting for the end).
Waiting for shutdown
I did this :
- name: "get containers"
become: yes
shell: docker ps -a | grep -v NAMES | awk '{print $NF}'
register: efluidnet_tp_containers_list
delegate_to: myserver
- name: "shutdown containers"
async: 3600
poll: 0
become: yes
docker_container:
name: "{{ item }}"
state: stopped
with_items:
- "{{ efluidnet_tp_containers_list.stdout_lines }}"
register: restart_aelnet
delegate_to: myserver
- debug:
msg: "{{ item['ansible_job_id'] }}"
with_items: "{{ restart_aelnet['results'] }}"
- name: 'waiting for shutdown'
async_status:
jid: "{{ item['ansible_job_id'] }}"
register: job_result
until: job_result.finished
retries: 30
with_items: "{{ restart_aelnet['results'] }}"
delegate_to: myserver
But my waiting task is unable to find the ansible_jod id :
TASK [get containers] *******************************************************************************************************************************************
Thursday 05 December 2019 08:17:55 +0100 (0:00:00.285) 0:00:00.366 *****
changed: [localhost -> None]
TASK [shutdown containers] **************************************************************************************************************************************
Thursday 05 December 2019 08:17:56 +0100 (0:00:00.937) 0:00:01.303 *****
changed: [localhost -> None] => (item=ael-13.20.200-PREPRO-AMN_V13)
changed: [localhost -> None] => (item=ael-13.20.200-PREPRO-SCH_V13)
changed: [localhost -> None] => (item=ael-13.20.200-PREPRO-SAR_V13)
changed: [localhost -> None] => (item=ael-13.20.200-PREPRO-ROM_V13)
changed: [localhost -> None] => (item=ael-13.20.200-PREPRO-SAL_V13)
TASK [debug] *****************************************************************************************************************************************************
Thursday 05 December 2019 08:18:00 +0100 (0:00:03.320) 0:00:04.624 *****
ok: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'264488569945.120415', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-AMN_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/264488569945.120415'}) => {
"msg": "264488569945.120415"
}
ok: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'828045810515.120527', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SCH_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/828045810515.120527'}) => {
"msg": "828045810515.120527"
}
ok: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'406259878781.120644', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SAR_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/406259878781.120644'}) => {
"msg": "406259878781.120644"
}
ok: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'803234566504.120755', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-ROM_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/803234566504.120755'}) => {
"msg": "803234566504.120755"
}
ok: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'966123972732.120860', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SAL_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/966123972732.120860'}) => {
"msg": "966123972732.120860"
}
TASK [waiting for shutdown] **************************************************************************************************************************************
Thursday 05 December 2019 08:18:00 +0100 (0:00:00.085) 0:00:04.710 *****
failed: [localhost -> None] (item={'ansible_loop_var': u'item', u'ansible_job_id': u'264488569945.120415', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-AMN_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/264488569945.120415'}) => {"ansible_job_id": "264488569945.120415", "ansible_loop_var": "item", "attempts": 1, "changed": false, "finished": 1, "item": {"ansible_job_id": "264488569945.120415", "ansible_loop_var": "item", "changed": true, "failed": false, "finished": 0, "item": "ael-13.20.200-PREPRO-AMN_V13", "results_file": "/root/.ansible_async/264488569945.120415", "started": 1}, "msg": "could not find job", "started": 1}
failed: [localhost -> None] (item={'ansible_loop_var': u'item', u'ansible_job_id': u'828045810515.120527', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SCH_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/828045810515.120527'}) => {"ansible_job_id": "828045810515.120527", "ansible_loop_var": "item", "attempts": 1, "changed": false, "finished": 1, "item": {"ansible_job_id": "828045810515.120527", "ansible_loop_var": "item", "changed": true, "failed": false, "finished": 0, "item": "ael-13.20.200-PREPRO-SCH_V13", "results_file": "/root/.ansible_async/828045810515.120527", "started": 1}, "msg": "could not find job", "started": 1}
failed: [localhost -> None] (item={'ansible_loop_var': u'item', u'ansible_job_id': u'406259878781.120644', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SAR_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/406259878781.120644'}) => {"ansible_job_id": "406259878781.120644", "ansible_loop_var": "item", "attempts": 1, "changed": false, "finished": 1, "item": {"ansible_job_id": "406259878781.120644", "ansible_loop_var": "item", "changed": true, "failed": false, "finished": 0, "item": "ael-13.20.200-PREPRO-SAR_V13", "results_file": "/root/.ansible_async/406259878781.120644", "started": 1}, "msg": "could not find job", "started": 1}
failed: [localhost -> None] (item={'ansible_loop_var': u'item', u'ansible_job_id': u'803234566504.120755', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-ROM_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/803234566504.120755'}) => {"ansible_job_id": "803234566504.120755", "ansible_loop_var": "item", "attempts": 1, "changed": false, "finished": 1, "item": {"ansible_job_id": "803234566504.120755", "ansible_loop_var": "item", "changed": true, "failed": false, "finished": 0, "item": "ael-13.20.200-PREPRO-ROM_V13", "results_file": "/root/.ansible_async/803234566504.120755", "started": 1}, "msg": "could not find job", "started": 1}
failed: [localhost -> None] (item={'ansible_loop_var': u'item', u'ansible_job_id': u'966123972732.120860', 'failed': False, u'started': 1, 'changed': True, 'item': u'ael-13.20.200-PREPRO-SAL_V13', u'finished': 0, u'results_file': u'/root/.ansible_async/966123972732.120860'}) => {"ansible_job_id": "966123972732.120860", "ansible_loop_var": "item", "attempts": 1, "changed": false, "finished": 1, "item": {"ansible_job_id": "966123972732.120860", "ansible_loop_var": "item", "changed": true, "failed": false, "finished": 0, "item": "ael-13.20.200-PREPRO-SAL_V13", "results_file": "/root/.ansible_async/966123972732.120860", "started": 1}, "msg": "could not find job", "started": 1}
PLAY RECAP *******************************************************************************************************************************************************
localhost : ok=4 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
I managed to run this mechanism with a simple example like this:
- name: 'waiting for a long tasks'
shell: /bin/sleep 15
async: 1000
poll: 0
register: yum_sleeper
delegate_to: myserver
- debug:
msg: "{{ yum_sleeper }}"
delegate_to: myserver
- name: 'get results'
async_status:
jid: "{{ yum_sleeper.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30
delegate_to: myserver
But in my real use case i have a "results" properties that can be problematic ...
Can somebody help me ?
Thanks you
I think the issue is on become. To check the async_status the user needs to be the same as the one who ran the async job.
- name: 'waiting for shutdown'
become: yes
async_status:
jid: "{{ item['ansible_job_id'] }}"
register: job_result
until: job_result.finished
retries: 30
with_items: "{{ restart_aelnet['results'] }}"
delegate_to: myserver
I'm collecting the SQL version and edition found in registry using win_reg_stat, registering these into a variable, and writing them to a file.
Is it possible to write the values to the same line instead of separate lines?
- name: get sql version
win_reg_stat:
path: HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\{{ item }}\Setup
name: Version
with_items: "{{ sql_versions }}"
register: sql_version
- name: get sql edition
win_reg_stat:
path: HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\{{ item }}\Setup
name: Edition
with_items: "{{ sql_versions }}"
register: sql_edition
- lineinfile:
dest: /tmp/sql
line: "{{ inventory_hostname }};{{ item.value }}"
when: item.exists
with_items:
- "{{ sql_version.results }}"
delegate_to: localhost
- lineinfile:
dest: /tmp/sql
line: "{{ inventory_hostname }};{{ item.value }}"
when: item.exists
with_items:
- "{{ sql_edition.results }}"
delegate_to: localhost
The sql_versions variable contains multiple items:
sql_versions:
- MSSQL15.MSSQLSERVER
- MSSQL14.MSSQLSERVER
- MSSQL13.MSSQLSERVER
- MSSQL12.MSSQLSERVER
- MSSQL11.MSSQLSERVER
- MSSQL10_50.MSSQLSERVER
- MSSQL10.MSSQLSERVER
- MSSQL.1
Output example:
TASK [licensing : register sql version] *****************************************************************************************************************************************************************************************************
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL15.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL14.MSSQLSERVER', 'ansible_loop_var': 'item'})
ok: [win2019] => (item={'changed': False, 'type': 'REG_SZ', 'raw_value': '13.2.5026.0', 'value': '13.2.5026.0', 'exists': True, 'failed': False, 'item': 'MSSQL13.MSSQLSERVER', 'ansible_loop_var': 'item'}) => {
"msg": "13.2.5026.0"
}
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL12.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL11.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL10_50.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL10.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL.1', 'ansible_loop_var': 'item'})
TASK [licensing : register sql edition] *****************************************************************************************************************************************************************************************************
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL15.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL14.MSSQLSERVER', 'ansible_loop_var': 'item'})
ok: [win2019] => (item={'changed': False, 'type': 'REG_SZ', 'raw_value': 'Web Edition', 'value': 'Web Edition', 'exists': True, 'failed': False, 'item': 'MSSQL13.MSSQLSERVER', 'ansible_loop_var': 'item'}) => {
"msg": "Web Edition"
}
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL12.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL11.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL10_50.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL10.MSSQLSERVER', 'ansible_loop_var': 'item'})
skipping: [win2019] => (item={'changed': False, 'exists': False, 'failed': False, 'item': 'MSSQL.1', 'ansible_loop_var': 'item'})
did you tried this..
- lineinfile:
dest: /tmp/sql
line: "{{ inventory_hostname }};{{ item.value }}"
when: item.exists
with_items:
- "{{ sql_version.results }}"
- "{{ sql_edition.results }}"
delegate_to: localhost
Please try as below (not tested)
- lineinfile:
dest: /tmp/sql
line: "{{ inventory_hostname }};{{ item.version.value }};{{ item.edition.value }}"
when: item.exists
with_items:
- "{ version: {{sql_version.results}}, edition: {{sql_edition.results}} }"
delegate_to: localhost
Trying to write one playbook that checks whether a set of files exist on a set of servers (both Linux and Windows hosts), and if they do, then to replace the files.
Here is what i have so far:
---
- hosts: "{{hosts}}"
vars:
scripts:
- check_blackout.pl
- check_empty.pl
tasks:
- name: windows stat
with_items: "{{scripts}}"
win_stat: path=D:\scripts\{{item}}
register: windows_stat
when: "'windows' in group_names"
- name: other stat
with_items: "{{scripts}}"
stat: path=/usr/local/bin/{{item}}
register: other_stat
remote_user: "{{script_owner | default(ansible_user)}}"
when: "'windows' not in group_names"
- name: windows debug
with_items: "{{windows_stat.results}}"
debug: var={{item.item}}
when: "{{item.stat.exists}}"
- name: other debug
with_items: "{{other_stat.results}}"
debug: var={{item.item}}
when: "{{item.stat.exists}}"
...
When I run this against a Windows and Linux host for testing, I get the following:
[ansible#vmhklftpscdv1 ~]$ ansible-playbook test.yml -e "hosts=vmhkge1jasdev01,jdeesbkup" --ask-vault-pass
Vault password:
PLAY [vmhkge1jasdev01,jdeesbkup] ************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************
ok: [vmhkge1jasdev01]
ok: [jdeesbkup]
TASK [windows stat] *************************************************************************************************************************************************************
skipping: [jdeesbkup] => (item=check_blackout.pl)
skipping: [jdeesbkup] => (item=check_empty.pl)
ok: [vmhkge1jasdev01] => (item=check_blackout.pl)
ok: [vmhkge1jasdev01] => (item=check_empty.pl)
TASK [other stat] ***************************************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item=check_empty.pl)
skipping: [vmhkge1jasdev01] => (item=check_blackout.pl)
ok: [jdeesbkup] => (item=check_blackout.pl)
ok: [jdeesbkup] => (item=check_empty.pl)
TASK [windows debug] ************************************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'check_empty.pl', 'invocation': {'module_name': u'win_stat'}})
skipping: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'check_blackout.pl', 'invocation': {'module_name': u'win_stat'}})
fatal: [jdeesbkup]: FAILED! => {"failed": true, "msg": "The conditional check '{{item.stat.exists}}' failed. The error was: error while evaluating conditional ({{item.stat.exists}}): 'dict object' has no attribute 'stat'\n\nThe error appears to have been in '/home/ansible/test.yml': line 19, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n when: \"'windows' not in group_names\"\n - name: windows debug\n ^ here\n"}
TASK [other debug] **************************************************************************************************************************************************************
fatal: [vmhkge1jasdev01]: FAILED! => {"failed": true, "msg": "The conditional check '{{item.stat.exists}}' failed. The error was: error while evaluating conditional ({{item.stat.exists}}): 'dict object' has no attribute 'stat'\n\nThe error appears to have been in '/home/ansible/test.yml': line 23, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n when: \"{{item.stat.exists}}\"\n - name: other debug\n ^ here\n"}
to retry, use: --limit #/home/ansible/test.retry
PLAY RECAP **********************************************************************************************************************************************************************
jdeesbkup : ok=2 changed=0 unreachable=0 failed=1
vmhkge1jasdev01 : ok=2 changed=0 unreachable=0 failed=1
[ansible#vmhklftpscdv1 ~]$
Any ideas how I can get this working?
I've tried various combinations including checking the group membership before checking the results:
when: "'windows' in group_names and {{item.stat.exists}}"
However Ansible still seems to check the item.stat field even when the first part of the condition is false.
Or is my fundamental approach wrong, should I be splitting these tasks up into different playbooks?
Yes, you are right. with_items is evaluated before when. You can add a default empty list to avoid the error:
- name: other debug
with_items: "{{other_stat.results | default([]) }}"
debug: var={{item}}
when: "{{item.stat.exists | default(false)}}"
Got it working, here is successful playbook and output:
---
- hosts: "{{hosts}}"
vars:
scripts:
- run.pl
tasks:
- name: win_stat
with_items: scripts
win_stat: path="D:\scripts\{{item}}"
register: "win_result"
when: "'windows' in group_names"
- name: other_stat
with_items: scripts
stat: path="/usr/local/bin/{{item}}"
register: "other_result"
when: "'windows' not in group_names"
- debug: var=win_result
- debug: var=other_result
- with_items: "{{ win_result.results }}"
debug: msg="{{item.item}}"
when: "not (item.skipped | default(false))"
- with_items: "{{ other_result.results}}"
debug: msg="{{item.item}}"
when: "not (item.skipped | default(false))"
...
[ansible#vmhklftpscdv1 ~]$ ansible-playbook debug.yml -e "hosts=jdeesbkup,vmhkge1jasdev01" --ask-vault-pass
Vault password:
PLAY [jdeesbkup,vmhkge1jasdev01] **************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************
ok: [jdeesbkup]
ok: [vmhkge1jasdev01]
TASK [win_stat] *******************************************************************************************************************************************
skipping: [jdeesbkup] => (item=scripts)
ok: [vmhkge1jasdev01] => (item=scripts)
TASK [other_stat] *****************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item=scripts)
ok: [jdeesbkup] => (item=scripts)
TASK [debug] **********************************************************************************************************************************************
ok: [jdeesbkup] => {
"win_result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"item": "scripts",
"skip_reason": "Conditional check failed",
"skipped": true
}
]
}
}
ok: [vmhkge1jasdev01] => {
"win_result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"invocation": {
"module_name": "win_stat"
},
"item": "scripts",
"stat": {
"exists": false
}
}
]
}
}
TASK [debug] **********************************************************************************************************************************************
ok: [jdeesbkup] => {
"other_result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": true,
"get_mime": true,
"path": "/usr/local/bin/scripts"
},
"module_name": "stat"
},
"item": "scripts",
"stat": {
"exists": false
}
}
]
}
}
ok: [vmhkge1jasdev01] => {
"other_result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"item": "scripts",
"skip_reason": "Conditional check failed",
"skipped": true
}
]
}
}
TASK [debug] **********************************************************************************************************************************************
skipping: [jdeesbkup] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': u'scripts', 'changed': False})
ok: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'scripts', 'invocation': {'module_name': u'win_stat'}}) => {
"item": {
"changed": false,
"invocation": {
"module_name": "win_stat"
},
"item": "scripts",
"stat": {
"exists": false
}
},
"msg": "scripts"
}
TASK [debug] **********************************************************************************************************************************************
---
- hosts: "{{hosts}}"
vars:
scripts:
- run.pl
tasks:
- name: win_stat
with_items: scripts
win_stat: path="D:\scripts\{{item}}"
register: "win_result"
when: "'windows' in group_names"
- name: other_stat
with_items: scripts
stat: path="/usr/local/bin/{{item}}"
register: "other_result"
when: "'windows' not in group_names"
- debug: var=win_result
- debug: var=other_result
- with_items: "{{ win_result.results }}"
debug: msg="{{item.item}}"
when: "not (item.skipped | default(false))"
- with_items: "{{ other_result.results}}"
debug: msg="{{item.item}}"
when: "not (item.skipped | default(false))"
# when: "'windows' in group_names and {{item.stat.exists}}"
# - name: win_test
# with_items: {{win_result.results}}
# debug: var="{{item}}"
# when: "'windows' in group_names and {{item.stat.exists}}"
~
~
~
skipping: [vmhkge1jasdev01] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': u'scripts', 'changed': False})
ok: [jdeesbkup] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'scripts', 'invocation': {'module_name': u'stat', u'module_args': {u'checksum_algorithm': u'sha1', u'get_checksum': True, u'follow': False, u'path': u'/usr/local/bin/scripts', u'get_md5': True, u'get_mime': True, u'get_attributes': True}}}) => {
"item": {
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": true,
"get_mime": true,
"path": "/usr/local/bin/scripts"
},
"module_name": "stat"
},
"item": "scripts",
"stat": {
"exists": false
}
},
"msg": "scripts"
}
PLAY RECAP ************************************************************************************************************************************************
jdeesbkup : ok=5 changed=0 unreachable=0 failed=0
vmhkge1jasdev01 : ok=5 changed=0 unreachable=0 failed=0