0

I'm using to fetch the status of the few services using ansible and generating the HTML output using ansible jinja template, I'm getting variable undefined or some other error,

Here I'm storing the values in the register module and then fetching those values in template, but it's not working

Jinja Template:

{% for network_switch in ['client'] %}
        <tr>
            <td>{{ hostvars[network_switch]['ansible_hostname'] }}</td>
            <td>{{ hostvars[network_switch]['kernel.stdout'] }}</td>
            <td>{{ hostvars[network_switch]['httpd.stdout'] }}</td>
        </tr>
{% endfor %}

Playbook Details:

- name: Getting the OS Information
      command: 'uname -r'
      register: kernel

    - name: Getting the OS Information
      shell: "systemctl status sshd | grep -i active | awk '{print$3}'"
      register: httpd

    - name: create HTML report
      template:
        src: report.j2
        dest: "{{ file_path }}"
      delegate_to: localhost
      run_once: true

Error:

FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: \"hostvars['client']\" is undefined"}

2 Answers 2

0

Use ansible_play_batch "List of active hosts in the current play run limited by the serial, aka ‘batch’. Failed/Unreachable hosts are not considered ‘active’."

{% for network_switch in ansible_play_batch %}
...

If there are more batches the file will be overwritten. See Controlling playbook execution: strategies and more. See Ansible date variable how to use date and create a unique filenames. For example

dest: "{{ file_path ~ '-' ~
          ansible_date_time.date ~ '-' ~
          ansible_date_time.hour ~ '-' ~
          ansible_date_time.minute ~ '-' ~
          ansible_date_time.second }}"

Create a single file

The next option would be to create a list with all items in the first play and write the file in the second play (change the template and use my_list). For example

- hosts: all
  tasks:
    - name: Getting the OS Information
      ...
    - name: Collect the list
      set_fact:
        my_list: "{{ my_list|default([]) +
                     [hostvars[item]['ansible_hostname'],
                      hostvars[item]['kernel.stdout'],
                      hostvars[item]['httpd.stdout']] }}"
       loop: "{{ ansible_play_batch }}"
       run_once: true

- hosts: all
  tasks:
    - name: Take a look at what was collected
      debug:
        var: my_list
      run_once: true
    - name: create HTML report
      template:
        src: report.j2
        dest: "{{ file_path }}"
      delegate_to: localhost
      run_once: true

(not tested)

3
  • I followed ur steps again it's giving the same error
    – Prabahar S
    May 3, 2020 at 14:47
  • It's difficult to believe it. There is no 'client' variable in my code. How did you manage and get the same error? Wouldn't you mind to update the question with current status? May 3, 2020 at 14:50
  • {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'kernel.stdout'"}
    – Prabahar S
    May 3, 2020 at 14:50
0

Playbook:

---
- name: build Centos inventory report
  hosts: client

  vars:
    file_path: /var/www/html/generated_report.html

  tasks:
    #- name: Getting the OS Information
    #  command: 'cat /etc/redhat-release'
    #  register: os_release

    - name: Getting the OS Information
      command: 'uname -r'
      register: kernel

    - name: Getting the OS Information
      shell: "systemctl status sshd | grep -i active | awk '{print$3}'"
      register: httpd

    - name: Collect the list
      set_fact:
        my_list: "{{ my_list|default([]) +
                     [hostvars[item]['ansible_hostname'],
                      hostvars[item]['kernel.stdout'],
                      hostvars[item]['httpd.stdout']] }}"
      loop: "{{ ansible_play_batch }}"
      run_once: true

- name: Collecting all information
  hosts: client
  vars:
    file_path: /var/www/html/generated_report.html
  tasks:
    - name: Take a look at what was collected
      debug:
        var: my_list
      run_once: true

    - name: create HTML report
      template:
        src: report.j2
        dest: "{{ file_path }}"
      delegate_to: localhost
      run_once: true

Jinja Template:

{% for network_switch in ansible_play_batch %}
        <tr>
            <td>{{ hostvars[network_switch]['ansible_hostname'] }}</td>
            <td>{{ hostvars[network_switch]['kernel.stdout'] }}</td>
            <td>{{ hostvars[network_switch]['httpd.stdout'] }}</td>
        </tr>
{% endfor %}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .