ansible output multiple variables to same line - ansible

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

Related

AWX fails to retrieve collections from Ansible Galaxy

I have a project with roles/requirements.yml and collections/requirements.yml. This - I think - per AWX / Tower guidelines.
On project update the roles/requirements.yml is picked up successfully but the collections/requirements.yml fails with a typical Ansible error message unfortunately that doesn't help me understand what is going wrong.
PLAY [Update source tree if necessary] *****************************************
TASK [delete project directory before update] **********************************
changed: [localhost]
TASK [update project using git] ************************************************
changed: [localhost]
TASK [Set the git repository version] ******************************************
ok: [localhost]
TASK [Repository Version] ******************************************************
ok: [localhost] => {
"msg": "Repository Version 812a488b0a09f7fda6a784a8247abaf6892e1f13"
}
PLAY [Install content with ansible-galaxy command if necessary] ****************
TASK [detect roles/requirements.(yml/yaml)] ************************************
ok: [localhost] => (item={'ext': '.yml'})
ok: [localhost] => (item={'ext': '.yaml'})
TASK [fetch galaxy roles from requirements.(yml/yaml)] *************************
changed: [localhost] => (item={'changed': False, 'stat': {'exists': True, 'path': '/var/lib/awx/projects/_6__c2/roles/requirements.yml', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 390, 'inode': 131356, 'dev': 64771, 'nlink': 1, 'atime': 1613038457.4215767, 'mtime': 1613038456.678576, 'ctime': 1613038456.678576, 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False, 'blocks': 8, 'block_size': 4096, 'device_type': 0, 'readable': True, 'writeable': True, 'executable': False, 'pw_name': 'root', 'gr_name': 'root', 'checksum': '29ae537db56b12b54f2eecb8668f4185b7b1e91d', 'mimetype': 'text/plain', 'charset': 'us-ascii', 'version': None, 'attributes': [], 'attr_flags': ''}, 'invocation': {'module_args': {'path': '/var/lib/awx/projects/_6__c2/roles/requirements.yml', 'follow': False, 'get_md5'…
skipping: [localhost] => (item={'changed': False, 'stat': {'exists': False}, 'invocation': {'module_args': {'path': '/var/lib/awx/projects/_6__c2/roles/requirements.yaml', 'follow': False, 'get_md5': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1'}}, 'failed': False, 'item': {'ext': '.yaml'}, 'ansible_loop_var': 'item'})
TASK [detect collections/requirements.(yml/yaml)] ******************************
ok: [localhost] => (item={'ext': '.yml'})
ok: [localhost] => (item={'ext': '.yaml'})
TASK [fetch galaxy collections from collections/requirements.(yml/yaml)] *******
failed: [localhost] (item={'changed': False, 'stat': {'exists': True, 'path': '/var/lib/awx/projects/_6__c2/collections/requirements.yml', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 183, 'inode': 131286, 'dev': 64771, 'nlink': 1, 'atime': 1613038457.4195766, 'mtime': 1613038456.673576, 'ctime': 1613038456.673576, 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False, 'blocks': 8, 'block_size': 4096, 'device_type': 0, 'readable': True, 'writeable': True, 'executable': False, 'pw_name': 'root', 'gr_name': 'root', 'checksum': '7b8e2a2b64c7d5e64917b548dc40347158f8bb1b', 'mimetype': 'text/plain', 'charset': 'us-ascii', 'version': None, 'attributes': [], 'attr_flags': ''}, 'invocation': {'module_args': {'path': '/var/lib/awx/projects/_6__c2/collections/requirements.yml', 'follow': False, '…
skipping: [localhost] => (item={'changed': False, 'stat': {'exists': False}, 'invocation': {'module_args': {'path': '/var/lib/awx/projects/_6__c2/collections/requirements.yaml', 'follow': False, 'get_md5': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1'}}, 'failed': False, 'item': {'ext': '.yaml'}, 'ansible_loop_var': 'item'})
Of course I tested the requirements locally. It works. Just not in AWX.
With the exception of one task having status failed I really don't see any difference between the error message on failure and the success logging when fetches roles.
What is wrong here?
I just came across this question since I encountered the same situation. I was able to resolve my issue and would like to share my approach. My AWX version is 17.1.0 (Docker image).
How to identify the root cause
enable the -vvv option as sadok-f suggested (see detailed instructions below)
open the job execution logs
click on the logline of the failing task (a small pop-up appears)
click the JSON tab (or Standard Error - Most details are provided in the JSON tab)
read the significantly more descriptive error message
My issue was, that I had a typo in the Ansible Galaxy credentials. Therefore my dependencies within the requirements.yml were not installable.
How to increase the verbosity for project jobs
As mentioned by sadok-f, enable the -vvv option for more verbosity. That option is a bit hidden. You can see the current configuration at Settings > Jobs settings. Now look for "Run Project Updates With Higher Verbosity" (the project update triggers the installation of requirements.yml files).
At least for AWX 17.1.0, editing the settings via the GUI is not implemented. You need to patch the settings via AWX-API to enable the project update-job verbosity. To do so, visit the AWX-API:
<your-awx-fqdn>/api/v2/settings/jobs/
At the bottom of the page, you have a small window that allows you to modify the content. Within the content box look for:
"PROJECT_UPDATE_VVV": false,
and change it to:
"PROJECT_UPDATE_VVV": true,
Click the PATCH button. That enables the -vvv option for project refresh jobs. As written, those refresh jobs install the requirements.
Synch your project and have a look at the significantly more verbose job logs (Projects > Sync Project (the tiny cycle-arrow button)).

Ansible extract sub-string from a matched element of a List variable

I have a variable, which is a list as below:
"test_list": [
"some text here",
"server1",
"command1 parameter1",
"path/to/command2 parameter2 server1_202012",
"some more text",
"New backup file is server1_202019"
]
I am trying to extract the substring server1_202019 which is at the end of the line that starts with New backup file.... There is only one line like this and I've tried below option to get the substring.
- set_fact:
test_name: "{{ test_list | select('^New backup file is (.+)$','\\1') }}"
and the output I've received is:
"test_name": "<generator object _select_or_reject at 0x3fe5b40>"
I've tried below code also, but failed.
- set_fact:
test_name: "{{ test_list | regex_search('^New backup file is (.+)$','\\1') }}"
The error is:
"msg": "Unexpected templating type error occurred on ({{ test_list | regex_search('^New backup file is (.+)$','\\\\1') }}): ..... expected string or buffer"
Could somebody please suggest how I can get the output as below:
"test_name": "server1_202019"
The ansible version I'm using is 2.9
Thanks
Select the item from the list and then use regex_replace. For example
- set_fact:
test_name: "{{ test_list|
select('regex', my_regex)|
first|
regex_replace(my_regex, my_replace) }}"
vars:
my_regex: '^New backup file is (.*)$'
my_replace: '\1'
- debug:
var: test_name
give
"test_name": "server1_202019"
Since test_list is a list, you need to loop through the items to be matched using regex. Something like below can be done.
- set_fact:
matched: "{{ item | regex_search('^New backup file is (.+)$','\\1') }}"
loop: "{{ test_list }}"
register: matching_items
- debug:
var: item.ansible_facts.matched
with_items: "{{ matching_items.results }}"
when: item.ansible_facts.matched != ""
Should output like below for debug:
TASK [debug] *******************************************************************************************************************************
skipping: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ''}, 'failed': False, 'item': 'some text here', 'ansible_loop_var': 'item'})
skipping: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ''}, 'failed': False, 'item': 'server1', 'ansible_loop_var': 'item'})
skipping: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ''}, 'failed': False, 'item': 'command1 parameter1', 'ansible_loop_var': 'item'})
skipping: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ''}, 'failed': False, 'item': 'path/to/command2 parameter2 server1_202012', 'ansible_loop_var': 'item'})
ok: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ['server1_202019']}, 'failed': False, 'item': 'New backup file is server1_202019', 'ansible_loop_var': 'item'}) => {
"ansible_loop_var": "item",
"item": {
"ansible_facts": {
"matched": [
"server1_202019"
]
},
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"item": "New backup file is server1_202019"
},
"item.ansible_facts.matched": [
"server1_202019"
]
}
skipping: [localhost] => (item={'changed': False, 'ansible_facts': {'matched': ''}, 'failed': False, 'item': 'some more text', 'ansible_loop_var': 'item'})

ansible with_sequence result message hide

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

could not find job trying to async and poll tasks

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

Ansible playbook to handle both Linux and Windows hosts

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

Resources