Arrfab's Blog Linux tips and tricks …


Debug for the winners !

Recently I had to dive back into Ansible playbooks I wrote (quite) some time ago. I had to add some logic to generate different application templates based on facts/packages being installed on the managed nodes. Long story short (I'll not describe the use case here as it's quite complex), I decided that injecting directly some kind of logic in the Jinja2 templates was enough .. but not.

Let's take a very simplified example here (don't even look at the tasks but rather at the logic explained how to get there, once again this is a 'stupid' playbook) :

- hosts: localhost
connection: local
user: root
- myrole: httpserver

- name: registering a variable only if myrole is httpserver
command: /bin/rpm -q --qf '%{version}' httpd
register: httpd_version
when: myrole == 'httpserver'
- name: pushing the generated template
template: src=../templates/logic.txt.j2 dest=/tmp/logic.txt


Now let's have a look at the (very) simple logic.txt.j2 :

{% if httpd_version is defined -%}
You're using an Apache http server version : {{ httpd_version.stdout }}
{% else %}
You're not using an http server, or not defined in the ansible machine role
{% endif -%}

Easy, and it seems it was working when myrole was indeed httpserver :

cat /tmp/logic.txt
You're using an Apache http server version : 2.2.15

But things didn't work as expected when myrole was something else, like for example dbserver

TASK: [registering a variable only if myrole is httpserver] *******************
skipping: [localhost]

TASK: [pushing the generated template] ****************************************
fatal: [localhost] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'stdout'", 'failed': True}

hmm, as the register: task was skipped, I was wondering why it then complained about the httpd_version.stdout as I thought that httpd_version wasn't defined .. but I was wrong  : even if 'skipped' the variable exists for that host. I quickly discovered it when adding a debug task in between the other tasks in my playbook :

- debug: msg="this is http_version value {{ httpd_version }}"

Now let's see what can be wrong :

TASK: [debug msg="this is http_version value {{httpd_version}}"] **************
ok: [localhost] => {"msg": "this is http_version value {u'skipped': True, u'changed': False}"}

Very interesting : so even when skipped, the variable httpd_version is still "registered" by the register: feature but marked as skipped.

Let's so change our "logic" in the Jinja2 template then ! :

{% if httpd_version.skipped -%}
You're not using an http server, or not defined in the ansible machine role
{% else %}
You're using an Apache http server version : {{ httpd_version.stdout }}
{% endif -%}

And now it works in all cases ..

It's a (very,very,very) simplified example, but you get the idea and using the debug module (don't forget to call ansible-playbook with -vvv to see those messages too !) can quickly show you where your issue is when having to troubleshoot something. As Patrick Debois was saying : "you gotta love Ansible for its simplicity" :-)

Share and Enjoy:
  • Facebook
  • Twitter
  • Print
  • PDF
  • Google Bookmarks
  • email
Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.