This is my code or checking wheter the website is valid and running:
- hosts: master
become: true
tasks:
- name: "Checking server availibility"
uri:
url: http://www.google.pl
timeout: 5
register: command_result
ignore_errors: yes
- debug: msg= "{{ command_result }}"
So command_result variable always returns this output regardless of the website availability:
ok: [Centos.v1] => {
"changed": false,
"msg": "Hello world!"
}
I would like to know if the first task was succesful or not but i can't do that when the output of registered variable is always the same.
How to setup my variable properly to read the return code?
and also
Is there some other way to check if an error occured in the previous task?
This has nothing to do with registering.
Remove the space character after msg=, otherwise you pass an empty string to the debug module and it prints Hello World! as a result (its default behaviour).
Better yet, use var parameter and YAML syntax:
- debug:
var: command_result
Related
I want to assert network configuration with our inventory using a single assert task.
- name: Get running class-map config
vars:
ansible_connection: network_cli
ios_command:
commands:
- 'sh run | in class-map match-any'
register: show_policy
- name: Render template to variable
set_fact:
tem_var: "{{ lookup( 'template', 'test_policy.j2' ).splitlines() }}"
- name: Validate running class-map with acl
ansible.builtin.assert:
that:
- "'{{item}}' in show_policy.stdout_lines[0]"
success_msg: "TEST: {{ UNIT_HOSTNAME }}: VALIDATE RUNNING POLICY: PASSED"
fail_msg: "TEST: {{ UNIT_HOSTNAME }}: VALIDATE RUNNING POLICY: FAILED"
loop: "{{ tem_var }}"
Above assert works fine, but the configuration on the router sometimes holds more configuration than what is expected. I would like to use the same assert task as I am already using. So above assert should be used to also compare the 2 variables
"tem_var" is a variable generated from out inventory files.
Our inventory has for example 8 configuration lines, and the router has 9.
In that case I wan't the assert to fail, if the number of lines in each variable "show_policy" and "tem_var" is not the same.
I have done it succesfully with 2 additional tasks, but it would be nice if the assert module could fail instead.
This is working, but it adds up the number of tasks running:
- name: Consistency check running
set_fact: diff_list="{{ show_policy.stdout_lines[0] | difference(tem_var) }}"
- name: CONSISTENCY CHECK FAILED !! Device has unvalidated config
ansible.builtin.fail:
msg: "CONSISTENCY FAILURE: Please remove {{ diff_list }} from {{ UNIT_HOSTNAME }}"
when: diff_list|default("")|length > 0
How to assert failure when source list holds more values than target list?
According your current question headline and current description
Our inventory has for example 8 configuration lines, and the router has 9.
In that case I wan't the assert to fail, if the number of lines in each variable show_policy and tem_var is not the same.
you would need just to compare the length of both lists.
The minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
vars:
show_policy:
stdout_lines:
- '1'
- '2'
tem_var:
stdout_lines:
- '1'
- '2'
- '3'
tasks:
- name: Assert failure
ansible.builtin.assert:
that: # the number of lines in each variable is the same
- show_policy.stdout_lines | length == tem_var.stdout_lines | length
success_msg: "VALIDATE RUNNING POLICY: PASSED"
fail_msg: "VALIDATE RUNNING POLICY: FAILED"
will result into an output of
TASK [Assert failure] **********************************************************
fatal: [localhost]: FAILED! => changed=false
assertion: show_policy.stdout_lines | length == tem_var.stdout_lines | length
evaluated_to: false
msg: 'VALIDATE RUNNING POLICY: FAILED'
TASK [Assert failure] **********************************************************
ok: [localhost] => changed=false
msg: 'VALIDATE RUNNING POLICY: PASSED'
depending on the list length.
Further Documentation
assert module – Asserts given expressions are true
Jinja2 Template Designer Documentation - List of Builtin Filters
jinja-filters.length
Follow Ups
If you are interested in the difference between the configuration (list), in example if settings are missing
Ansible: How to compare two list variables?
How to compare lists in Ansible?
Consider this playbook:
---
- name: test
hosts: localhost
gather_facts: no
tasks:
- name: foo
shell: echo foo # skipped when running in check mode
register: result
- debug: msg="foo"
when: (result is defined)
and (result.stdout == 'foo')
I thought the is defined would result in short circuit evaluation as in other languages, but it doesn't.
If this is run in check mode, I get:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'
I know I can ignore the error with ignore_errors: "{{ansible_check_mode}}", but I want to learn how to fix this problem.
How do I rewrite the when clause to prevent referencing undefined variables?
Actually, if you debug the var without a condition, you will see it is defined. It simply does not contain a stdout key since the task was skipped. The correct ways to work arround this (non exhaustive list):
- debug: msg="{{ result.stdout | default('no value') }}
when: result.stdout | default('') == 'foo'
- debug: msg="foo"
when:
- result is not skipped
- result.stdout == 'foo'
Note that since your above shell example is not changing anything on the remote target you can also decide to play it even when running in check mode:
- name: foo
shell: echo foo
check_mode: false
changed_when: false
register: result
- debug: msg="foo"
when: result.stdout == 'foo'
- name:
debug:
with_items: "{{ result.stdout }}"
TASK [pvc_precheck : check_rpm_versionlock warning message] ********************
skipping: [ip]
{
"msg": "Hello world!"
}
Somehow came across this test case. Here, when I run this code in Ansible got output but default message is also printing "Hello world!"
How can I omit this default message, I don't want any custom message as well, just executing it is enough.
Q: "Don't want any custom message as well. Just execution is enough."
A: If 'just execution is enough' use meta: noop e.g. the task below just silently does nothing
- meta: noop
Notes
1. Module debug doesn't require arguments
It's not possible to make debug display nothing. It wouldn't make sense. Why do you want to run debug when you don't want to see anything? No parameter is mandatory. msg defaults to "Hello world!" and var defaults to 0 e.g.
- debug:
gives
msg: Hello world!
2. Condition
Use a condition if you want to skip debug (eliminate message) e.g.
- debug:
msg: "{{ result.stdout }}"
when: debug_enable|default(false)|bool
3. Undefined variable
If the variable might be undefined it's possible to either skip the task e.g.
- debug:
msg: "{{ result.stdout }}"
when: result.stdout is defined
, or display a default value e.g.
- debug:
msg: "{{ result.stdout|default('NOT DEFINED') }}"
can someone explain why the following happens:
I am trying to re-use the same variable (output) in two different tasks, of which only one task will run depending on a conditional (bool). I don't understand why when the following playbook is run, the debug hi task results in an error.
The echo hello and debug hello run and work as expected and then the echo hi is skipped (which is also expected as bool == True) but I don't understand why the debug hi results in an error. The error I get is:
The conditional check output.stdout == hi failed. The error was: error while evaluating conditional: output 'dict object' has no attribute stdout
Why doesn't the the output variable persist through the debug hi task? It's almost as if it is losing its value when debug hi is skipped.
- hosts: localhost
vars:
bool: True
tasks:
- name: echo hello
shell: echo "hello"
register: output
when: bool == True
- name: debug hello
debug:
msg: "hello"
when: output.stdout == "hello"
- name: echo hi
shell: echo "hi"
register: output
when: bool != True
- name: debug hi
debug:
msg: "hi"
when: output.stdout == "hi"
You are still registering the task result to output, even though the task was skipped. Take these very simple tasks for example:
- command: echo Hello
register: result
when: false
- debug:
var: result
The variable result is still created, and has the following contents:
"result": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
This is still very useful information (i.e. to know that a task was skipped). You will need to account for this logic in your plays.
This task:
- name: echo hi
shell: echo "hi"
register: output
when: bool != True
registers output whether bool is true or not.
See the ansible documentation.
If a task fails or is skipped, the variable still is registered with a failure or skipped status, the only way to avoid registering a variable is using tags.
You can replace your latest when: condition with:
when: output.stdout is defined and output.stdout == "hi"
Im getting false positives with a when statement when searching for a not equal conditional in a output register. The reason is because part of the output contains the text that I am searching against but it is in another line. Below is a sample of my code.
tasks:
- ios_command:
commands: show run | inc logging host
provider: "{{cli}}"
register: run
- debug:
msg: "{{run.stdout_lines}}"
when: not run.stdout | join('') | search('192.168.0.60')
So what pretty much is happening is that when the return value is
"msg": [
[
"logging host 192.168.0.27",
"logging host 192.168.0.60"
]
]
because the 192.168.0.60 is in there it skips the entire task. Can someone help me with a way detect the logging host 192.168.0.27 is in a seperate line of the search?
You'll need to loop over your stdout_lines to check it line by line.
- debug:
msg: "{{ item }}"
when: not "192.168.0.60" in item
with_items: "{{ run.stdout_lines }}"