Registering a result when calling a role/script inside a playbook - ansible

I am working with ansible in Linux and have this playbook, which calls a role which passes the script name to run with an argument:
- hosts: localhost
gather_facts: no
ignore_errors: True
roles:
- { role: execute-my-script,
myscript_script_name: script.py,
myscript_args: "{{ my_var }}" }
- hosts: localhost
tasks:
- name: Status
ansible.builtin.debug:
msg: "WARNING: THERE IS AN ERROR!!!"
when:
- result is defined
- result.stdout is search("This resulted in error")
This is working when I run this playbook, and it will execute the script.py with arguments my_var.
This is my main.yml (execute-my-script):
---
- name: Execute script
ansible.builtin.command: "script.sh
{{ argument }}"
register: result
tags: execute-my-script
failed_when: "'This resulted in error' in result.stderr"
- set_fact: {"result": "{{ result }}"}
Note: This resulted in error comes from the script.sh.
I want to register the result of this task and then add another task which will do something if the result.stdout has this : "This resulted in error".
Although, I cannot register the result using register: result.
So I registered result inside main.yml task. But when I try to display an output in the playbook its not working.
Any ideas how to register the result of the given task in the playbook?

Related

Ansible: Output of 'loop' with 'register' module

I'm trying to get the output of my Ansible script using register module but the loop I'm using is probably causing some issue.
Whats a default way of using register module with loop?
Code:
---
- name:
hosts:
gather_facts:
tasks:
- name: Execute file
ansible.builtin.shell:
environment:
"setting environment"
register: output
loop:
"value"
- debug:
vars: output.std_lines
Whats a default way of using register module with loop?
It is just registering the result.
The only difference will be, that a single task will provide you just with an dictionary result (or output in your example) and registering in a loop will provide with a list result.results (or output.results in your example). To access the .stdout_lines you will need to loop over the result set .results too.
You may have a look into the following example playbook which will show some aspects of Registering variables, Loops, data structures, dicts and lists and type debugging.
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Create STDOUT output (single)
command: 'echo "1"'
register: result
- name: Show full result (single)
debug:
var: result
- name: Show '.stdout' (single)
debug:
msg: "The result in '.stdout': {{ result.stdout }} is of type {{ result.stdout | type_debug }}"
- name: Create STDOUT output (loop)
command: 'echo "{{ item }}"'
register: result
loop: [1, 2, 3]
loop_control:
label: "{{ item }}"
- name: Show full result (loop)
debug:
var: result
- name: Show '.stdout' (loop)
debug:
msg: "The result in '.stdout': {{ item.stdout }} is of type {{ item.stdout | type_debug }}"
loop: "{{ result.results }}"
loop_control:
label: "{{ item.item }}"
By running it and going through the output you can get familiar with the differences in your tasks.
Further Q&A
Register Variables in Loop in an Ansible Playbook
Ansible: loop, register, and stdout
Register variables in loop in Ansible playbook
... and many more here on SO.

ansible playbook: print custom message if hosts variable is not defined

The simple playbook
---
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
can be executed using
ansible-playbook -i hosts.yml -e target_hosts=<target host> <path to playbook> --ask-become-pass
This works just fine when target_hosts is set. In case target_hosts isn't set it obviously fails with
ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'target_hosts' is undefined
How do I print a custom message such as
The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
Note, I am aware that a default can be set via a hosts line like
hosts: "{{ target_hosts | default('all:!ntpserver') }}"
Add a localhost play for validating input arguments as given below. This will fail with a custom message if the 'target_hosts' var is not defined.
---
- name: Validate target_host variable
hosts: localhost
tasks:
- fail:
msg: The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
when: target_hosts is not defined
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
Use the filter mandatory. For example,
- hosts: "{{ target_hosts|mandatory('The variable target_hosts is mandatory') }}"
Example of a complete playbook
shell> cat pb.yml
- hosts: "{{ target_hosts|mandatory(err001) }}"
vars:
err001: >-
The variable 'target_hosts' is not set,
use e.g. '-e target_hosts=all:!ntpserver'
tasks:
- debug:
msg: hello
gives
shell> ansible-playbook pb.yml
ERROR! The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'

Playbook is getting hanged for some time and resuming itself after that

When i used WHEN condition for block which contains a lot of tasks the playbook is getting stuck before entering into that block and staying in the hung state for a longtime.
i have added ANSIBLE_SSH_PIPELINING=True in ansible.cfg, but it's not working.
- block:
- block:
- name: Interface Status Details
include: interface_details.yml
register: result
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout }}
- debug: var=LowerCaseResult
- block:
- name: Calling Dependency Playbook
include: one_test.yml
register: result
- debug: var=result
when: "'is up' in LowerCaseResult"
- block:
- name: Calling Dependency Playbook
include: two_test.yml
register: cmd_result
- debug: var= cmd_result
when: "'is up' not in LowerCaseResult"
when: true
Debug is not printing the playbook is getting stuck for a long time no error message is produced.
(ansible 2.7.9)
ansible-lint does not complain about nested block (interesting!) See nested blocks lose conditions on parent blocks #12395 (ansible locked and limited conversation to collaborators on Apr 25) This might cause problems until resolved.
Problems in the code
1) Nothing is registered by include use include_tasks
- name: Interface Status Details
include_tasks: interface_details.yml
register: result
2) The closing quotation is missing; If there is no stdout in this result the task will fail
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout }}
correct, set default to 'is NOT up'
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout|default('is NOT up') }}"
3) Extra space after var=
- debug: var= cmd_result
correct
- debug: var=cmd_result
The play below might be working
- hosts: localhost
tasks:
- block:
- block:
- name: Interface Status Details
include_tasks: interface_details.yml
register: result
- debug: var=result
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout|default('is NOT up') }}"
- debug: var=LowerCaseResult
- block:
- name: Calling Dependency Playbook
include_tasks: one_test.yml
register: result
- debug: var=result
when: "'is up' in LowerCaseResult"
- block:
- name: Calling Dependency Playbook
include_tasks: two_test.yml
register: cmd_result
- debug: var=cmd_result
when: "'is up' not in LowerCaseResult"
when: true

Syntax to pass dynamic variables to include_tasks along with with_item in Ansible playbook

Executing parent.yml which in turn calls child.yml playbook for execution with dynamic variables.
Variables from parent.yml aren`t interpolated inside child.yml playbook. Correct me if I am using correct syntax?
Parent.yml
- name: Main playbook to call MySQL backup
hosts: localhost
gather_facts: no
tasks:
- include_task: child.yml
vars:
var1: "{{ item.name }}"
var2: "{{ item.db_name }}"
with_items:
- { name: '10.10.10.01', db_name: 'prod1' }
- { name: '10.10.10.02', db_name: 'prod2' }
child.yml (Takes mysqldump from managed DB)
- name: MySQL dump
hosts: localhost
#gather_facts: no
#vars:
# v1: "{{ var1 }}"
# v2: "{{ var2 }}"
tasks:
- name: Executing the shell script
shell: 'mysqldump -h "{{ var1 }}" -u"ansi" -p"*****" "{{ var2 }}"| gzip > /tmp/mysql_dump/"{{ var2 }}"_`date +%Y%m%d-%H%M`.gz'
fatal: [127.0.0.1]: FAILED! => {"reason": "no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n\nThe error appears to be in '/home/ansible/playbooks/DBpatch/Linux/child.yml': line 1, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: MySQL dump\n ^ here\n"}
include_task expects a list of tasks but you give it a complete playbook.
Child.yml should only contain what is currently below the line "tasks:".
See also https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_includes.html

Return Variable from Included Ansible Playbook

I have seen how to register variables within tasks in an ansible playbook and then use those variables elsewhere in the same playbook, but can you register a variable in an included playbook and then access those variables back in the original playbook?
Here is what I am trying to accomplish:
This is my main playbook:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
roles:
- some_role
sub-playbook.yml:
---
- hosts: localhost
tasks:
- name: Collect info from Jenkins Job
script: whatever.py --url "{{ job_url }}"
register: jenkins_artifacts
I'd like to be able to access the jenkins_artifacts results back in main_playbook if possible. I know you can access it from other hosts in the same playbook like this: "{{ hostvars['localhost']['jenkins_artifacts'].stdout_lines }}"
Is it the same idea for sharing across playbooks?
I'm confused what this question is about. Just use the variable name jenkins_artifacts:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
debug:
var: jenkins_artifacts
This might seem complicated but I love doing this in my Playbooks:
rc defines the name of the variable which contains the return value
ar gives the arguments to the include tasks
master.yml:
- name: verify_os
include_tasks: "verify_os/main.yml"
vars:
verify_os:
rc: "isos_present"
ar:
image: "{{ os.ar.to_os }}"
verify_os/main.yml:
---
- name: check image on device
ios_command:
commands:
- "sh bootflash: | inc {{ verify_os.ar.image }}"
register: image_check
- name: check if available
shell: "printf '{{ image_check.stdout_lines[0][0] }}\n' | grep {{ verify_os.ar.image }} | wc -l"
register: image_available
delegate_to: localhost
- set_fact: { "{{ verify_os.rc }}": "{{ true if image_available.stdout == '1' else false }}" }
...
I can now use the isos_present variable anywhere in the master.yml to access the returned value.

Resources