skip to Main Content

I am trying to write a playbook that runs across multiple OS’s. The goal of this snippet is to display the date of the last update.

Note: This is not about the shell lines, I know they are exceedingly rudimentary, this is about the debug section. How can I retrieve the dates from multiple servers running different operating systems?

Here’s my attempt:


---
- hosts: mysystems

  tasks:

  - name: Get last update run - Ubuntu
    register: lastupdate_u
    shell: echo "Last apt activity is $(grep Start-Date /var/log/apt/history.log | tail -n 1 | awk '{print $2}')"
    when: ansible_distribution == 'Ubuntu'


  - name: Get last update run - RHEL
    register: lastupdate_r
    shell: echo "Last dnf activity is $(grep 'logging initialized' /var/log/dnf.log | tail -n 1 | awk '{print $1}')"
    when: ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat'

  - debug:
      var: lastupdate_u.stdout_lines, lastupdate_r.stdout_lines

Here’s the output:


TASK [Get last update run - Ubuntu] ***********************************************************************************************************
skipping: [ANSIBLE]
changed: [MWEBER]

TASK [Get last update run - RHEL] *************************************************************************************************************
skipping: [MWEBER]
changed: [ANSIBLE]

TASK [debug] **********************************************************************************************************************************
ok: [ANSIBLE] => {
    "lastupdate_u.stdout_lines, lastupdate_r.stdout_lines": "VARIABLE IS NOT DEFINED!"
}
ok: [MWEBER] => {
    "lastupdate_u.stdout_lines, lastupdate_r.stdout_lines": "VARIABLE IS NOT DEFINED!"
}

If I change the script to run only one OS at a time, all runs fine.

What am I doing wrong?

2

Answers


  1. I would register all dates in a single variable lastupdate instead of lastupdate_u and lastupdate_r. Then run the first play that includes only running the command and registering the value of lastupdate separately. In the same playbook add a second play that only runs on localhost where you iterate over hosts from hostvars and aquire the lastupdate variable.

    ---
    - hosts: mysystems
      tasks:
      - name: Get last update run - Ubuntu
        register: lastupdate_u
        shell: echo "Last apt activity is $(grep Start-Date /var/log/apt/history.log | tail -n 1 | awk '{print $2}')"
        when: ansible_distribution == 'Ubuntu'
      - name: Get last update run - RHEL
        register: lastupdate_r
        shell: echo "Last dnf activity is $(grep 'logging initialized' /var/log/dnf.log | tail -n 1 | awk '{print $1}')"
        when: ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat'
    
    - hosts: localhost
      connection: local
      - debug:
          var: item.lastupdate.stdout_lines
        with_items: hostvars
    ...
    

    I didn’t test the code, but I think that it shows the general logic.
    More info on hostvars here.

    Login or Signup to reply.
  2. The reason you’re seeing this error is because you’re passing the wrong data type.

    var should be a string.

    Notice the keys in the dictionary below:

    TASK [debug] **********************************************************************************************************************************
    ok: [ANSIBLE] => {
        "lastupdate_u.stdout_lines, lastupdate_r.stdout_lines": "VARIABLE IS NOT DEFINED!"
    }
    ok: [MWEBER] => {
        "lastupdate_u.stdout_lines, lastupdate_r.stdout_lines": "VARIABLE IS NOT DEFINED!"
    }
    

    Do this instead to explicitly construct your own Jinja2 expressions:

      - ansible.builtin.debug:
          msg:
            - "{{ lastupdate_u.stdout_line }}"
            - "{{ lastupdate_r.stdout_lines }}"
    
    

    The error you’re seeing is because the string you put for var is implicitly interpreted as a Jinja2 expression.

    i.e. it’s as if you wrote this:

    - hosts: localhost
      gather_facts: false
      ignore_errors: true
      tasks:
        - name: Debugger
          ansible.builtin.debug:
            var: "{{ lastupdate_u.stdout_lines, lastupdate_r.stdout_lines }}"
    

    …and because of that comma, it’ll be interpreted as a tuple!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search