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
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.
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'
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
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
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.