Search code examples
ansiblejinja2report

Create a report of installed packages in Ansible


I'm trying to make a report with installed packages and their version from a couple of machines.

The report must be created on the machine from where the playbook is executed.

Here is my current playbook


---
- name: main
  hosts: all
  gather_facts: no
  become: true
  tasks:
  - setup:
        gather_subset:
         - '!all'

  - name: Gather rpm packages
    package_facts:
          manager: auto
    ignore_errors: true

  - name: Create the result file
    local_action:
     module: copy
     content: |
          {% for h in groups.all %}
          {{h}}; OS: {{hostvars[h]['ansible_distribution']|default('N/A')}}; Release: {{hostvars[h]['ansible_distribution_version']|default('N/A')}}

          List of instaled packages:.......
          #==============================================
          {% for k,v  in  hostvars[h].ansible_facts.packages.iteritems() %}
          package {{ k.rjust(24) }}      version {{ v[0].version }}
          {%endfor%}
          #==============================================
          {%endfor%}
     dest: '/reports/OS_info.txt'

Which is run with

ansible-playbook -i rh_inventory  -u ansuser02  os_extract_info.yml

Now, if all hosts are reachable, the report is created, however, if one or more hosts are unreachable the playbook execution fails with:

fatal: [INFRA-116]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'packages'

And I can't figure out what could be the best approach to overcome this issue.


Solution

  • You have to apply a default filter to that fact, as you did for the other information:

    hostvars[h].ansible_distribution | default('N/A')
    

    In this case, since you want to loop over the key / value pair of a dictionary, you can default the packages fact to any empty one:

    {% for k, v in (hostvars[h].packages | default({})).items() %}