Sharma
Sharma

Reputation: 75

Ansible playbook jinja2 logic fails when server is "unreachable"

This playbook works fine by sending the email with jinja2 logic only when all the hosts in inventory are reachable. If any one of the server is "unreachable" the "send mail" play fails with below error

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'up_time'

How can the unreachable error be skipped in the mail play. Please help

    tasks:

        - name: "check host status"
          ping:
          register: ping_result
        - name: "group by host_status"
          group_by:
             key: "host_status_{{ ping_result.ping | default('success') }}"

   - name: check uptime
     hosts: all
     gather_facts: no
     ignore_unreachable: yes
     ignore_errors: yes
     become: no

     tasks:
       - name: check uptime
         raw: uptime |awk '{print $3}'
         register: up_time

   - name: send mail
     hosts: localhost
     gather_facts: no
     ignore_unreachable: yes
     ignore_errors: yes
     become: no
     tasks:
       - name: Communication on high uptime servers
         mail:
           host: relay.cust.services
           port: 25
           from: [email protected]
           to: [email protected]
           subject: Communication on high uptime servers
           body: |-
             {% for server, servervars in hostvars.items() %}
             {% if servervars.up_time.stdout |int >= 10 %}
                {{"Consider rebooting the server ** "}} {{server}} {{" ** for better performance as it has high uptime of days : "}}{{ servervars.up_time.stdout }}
             {% endif %}
             {% endfor %}

Upvotes: 0

Views: 234

Answers (2)

Sharma
Sharma

Reputation: 75

Able to figure out the issue and fixed it with "if" condition in mail play.

{% for server, servervars in hostvars.items()  %}
**{% if servervars.up_time.stdout is defined -%}**
  {% if servervars.up_time.stdout |int >= 2 %}
   {{"Consider rebooting the server ** "}} {{server}} {{" ** for better performance as it has high uptime of days : "}}{{ servervars.up_time.stdout }}
  {% endif %}
{% endif %}
{% endfor %}

Upvotes: 0

stackprotector
stackprotector

Reputation: 13452

Instead of defining another play, you can add a conditional task to your first play and delegate it to localhost. Example:

- name: check uptime
  hosts: all
  gather_facts: no
  ignore_unreachable: yes
  ignore_errors: yes
  become: no

  tasks:
    - name: check uptime
      raw: uptime |awk '{print $3}'
      register: up_time
    - name: Communication on high uptime servers
      mail:
        host: relay.cust.services
        port: 25
        ...
      delegate_to: localhost
      when: up_time is not failed

If you want to stick to two plays, you have to set up_time as a fact to make it available in other plays.

Upvotes: 0

Related Questions