Another report creation problem

446 views
Skip to first unread message

Dimitri Yioulos

unread,
Jan 15, 2024, 8:00:13 AM1/15/24
to Ansible Project
Good morning.

Let me start by saying that I hope I'm not overdoing my asks. I only do it when I've tried, but failed, at a solution. Nextly, I hope your kind answers help others, as well. That said, the following playbook returns packages that are set for update:

---

- hosts: all
  gather_facts: false

  tasks:
    - name: Check packages to upgrade
      dnf:
        list: updates
      register: packages

    - name: Show packages to upgrade
      debug:
        msg: >-
          {%- set output=[] -%}
          {%- for p in packages.results -%}
          {{ output.append((p.name ~ '-' ~ p.version ~ '-' ~ p.release)) }}
          {%- endfor -%}
          {{ output }}

    - local_action:
        module: copy
        content: |
          {% for host in ansible_play_hosts %}
          {{ host }}:
          The following packages will be updated

          {%- set output=[] -%}
          {%- for p in packages.results -%}
          {{ output.append((p.name ~ '-' ~ p.version ~ '-' ~ p.release)) }}
          {%- endfor -%}
          {{ output }}
          {% endfor -%}

        dest: "/tmp/installed.txt"
      run_once: yes
      tags:
        - report

It works fine through the debug play:

ok: [myhost] => {
    "msg": [
        "paho-c-1.3.13-2.el9",
        "cpp-11.4.1-2.1.el9",
        "glibc-headers-2.34-83.el9_3.7",
        "gnutls-dane-3.7.6-23.el9",
        "insights-client-3.2.2-1.el9_2",
        "libblockdev-2.28-7.el9",
        "libblockdev-loop-2.28-7.el9",
        "libfastjson-0.99.9-5.el9",
        ~

However, the report play does not work. I would have thought that setting it up like the debug play should do it, but no. How can I get that list of updates, along with the hostname, into a textfile report?

As ever, many thanks.

Dimitri Yioulos

unread,
Jan 15, 2024, 8:06:58 AM1/15/24
to Ansible Project
Fro what it may be worth, using the yaml  stdout_callback, the output of debug looks like this:

ok: [myhost] =>
  msg:
  - paho-c-1.3.13-2.el9
  - cpp-11.4.1-2.1.el9
  - glibc-headers-2.34-83.el9_3.7
  - gnutls-dane-3.7.6-23.el9
  - insights-client-3.2.2-1.el9_2
  - libblockdev-2.28-7.el9
  - libblockdev-loop-2.28-7.el9
  - libfastjson-0.99.9-5.el9

Todd Lewis

unread,
Jan 15, 2024, 9:21:26 AM1/15/24
to ansible...@googlegroups.com, uto...@gmail.com
You say "the report play does not work", but you don't tell us in what way it doesn't work. Is there a template error, undefined variable, or something else? Does running with -vv -D indicate anything? "Does not work" is too vague. Okay, so it didn't do what you expected, but what did it do? Show us the play log.
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/7348c423-e5f5-46d3-816c-95bb14712c0bn%40googlegroups.com.

-- 
Todd

Vladimir Botka

unread,
Jan 15, 2024, 10:03:06 AM1/15/24
to ansible...@googlegroups.com, Dimitri Yioulos
Create the variable(s) *output*

- set_fact:
output: "{{ packages.results
|json_query('[].[name, version, release]')
|map('join','-') }}"

Then, use it(them) in the *content*

- copy:
dest: /tmp/installed.txt
content: |
{% for host in ansible_play_hosts %}
{{ host }}:
The following packages will be updated
{{ hostvars[host]['output']|to_nice_yaml }}
{% endfor %}
run_once: true
delegate_to: localhost

--
Vladimir Botka

Dimitri Yioulos

unread,
Jan 15, 2024, 10:04:55 AM1/15/24
to Ansible Project
As I have written the playbook above, here's the error, which I hope is enough for troubleshooting purposes:

<localhost> ESTABLISH LOCAL CONNECTION FOR USER: deploy
<localhost> EXEC /bin/sh -c 'echo ~deploy && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/deploy/.ansible/tmp `"&& mkdir "` echo /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501 `" && echo ansible-tmp-1705330892.3380399-4159921-3325212893501="` echo /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501 `" ) && sleep 0'
Using module file /usr/local/lib/python3.9/site-packages/ansible/modules/stat.py
<localhost> PUT /home/deploy/.ansible/tmp/ansible-local-4159897gzoguc4w/tmphdv1no20 TO /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_stat.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/ /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_stat.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/env python /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_stat.py && sleep 0'
<localhost> PUT /home/deploy/.ansible/tmp/ansible-local-4159897gzoguc4w/tmpi_3sa5v9 TO /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/source
<localhost> EXEC /bin/sh -c 'chmod u+x /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/ /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/source && sleep 0'
Using module file /usr/local/lib/python3.9/site-packages/ansible/modules/copy.py
<localhost> PUT /home/deploy/.ansible/tmp/ansible-local-4159897gzoguc4w/tmpyre28n8_ TO /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_copy.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/ /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_copy.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/env python /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/AnsiballZ_copy.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_ansible.legacy.copy_payload_rmpe1ef8/ansible_ansible.legacy.copy_payload.zip/ansible/module_utils/basic.py", line 1700, in atomic_move
    os.rename(b_src, b_dest)
PermissionError: [Errno 1] Operation not permitted: b'/home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/source' -> b'/tmp/installed.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/ansible_ansible.legacy.copy_payload_rmpe1ef8/ansible_ansible.legacy.copy_payload.zip/ansible/module_utils/basic.py", line 1759, in atomic_move
    os.rename(b_tmp_dest_name, b_dest)
PermissionError: [Errno 1] Operation not permitted: b'/tmp/.ansible_tmp162o24fxinstalled.txt' -> b'/tmp/installed.txt'
fatal: [bed-test-9-dy2 -> localhost]: FAILED! => changed=false
  checksum: 590d9e59d7b819e4c8fb2068a91aec5e760afc8e
  diff: []
  invocation:
    module_args:
      _original_basename: tmpi_3sa5v9
      attributes: null
      backup: false
      checksum: 590d9e59d7b819e4c8fb2068a91aec5e760afc8e
      content: null
      dest: /tmp/installed.txt
      directory_mode: null
      follow: false
      force: true
      group: null
      local_follow: null
      mode: null
      owner: null
      remote_src: null
      selevel: null
      serole: null
      setype: null
      seuser: null
      src: /home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/source
      unsafe_writes: false
      validate: null
  msg: 'Unable to make b''/home/deploy/.ansible/tmp/ansible-tmp-1705330892.3380399-4159921-3325212893501/source'' into to /tmp/installed.txt, failed final rename from b''/tmp/.ansible_tmp162o24fxinstalled.txt'': [Errno 1] Operation not permitted: b''/tmp/.ansible_tmp162o24fxinstalled.txt'' -> b''/tmp/installed.txt'''

Dimitri Yioulos

unread,
Jan 15, 2024, 10:19:08 AM1/15/24
to Ansible Project
For Vladimir's solution, I get the following error:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: PermissionError: [Errno 1] Operation not permitted: b'/tmp/.ansible_tmpkdy1r8msinstalled.txt' -> b'/tmp/installed.txt'

fatal: [bed-test-9-dy2 -> localhost]: FAILED! => changed=false
  checksum: 543ecd635e9686d0ae4915df6ee4e9d8c13ff300
  msg: 'Unable to make b''/home/deploy/.ansible/tmp/ansible-tmp-1705331818.2910578-4160834-8270244954747/source'' into to /tmp/installed.txt, failed final rename from b''/tmp/.ansible_tmpkdy1r8msinstalled.txt'': [Errno 1] Operation not permitted: b''/tmp/.ansible_tmpkdy1r8msinstalled.txt'' -> b''/tmp/installed.txt'''

Todd Lewis

unread,
Jan 15, 2024, 10:31:16 AM1/15/24
to Ansible Project
Your 'deploy' user doesn't have permission to rename a file over '/tmp/installed.txt'. Is there an existing file with that name? Are there unusual permissions set on '/tmp' itself?

It's bad practice to omit the 'owner:', 'group:', and 'mode:' of files created with the copy or template modules. There may be issues created because you're taking the defaults. Or not. Just a thought.

Presented with those messages, the first thing I'd check is whether a file name '/tmp/installed.txt' already exists on the controller.

Dimitri Yioulos

unread,
Jan 15, 2024, 10:53:29 AM1/15/24
to Ansible Project
Ah, Todd, you were right. I changed the output path, and it worked. I'm not sure why i couldn't write to the /tmp directory, but, whatever. My last question (I hope) on this topic is how to get the output in a list format. This is what I get presently:

myhost:
The following packages will be updated['paho-c-1.3.13-2.el9', 'cpp-11.4.1-2.1.el9', 'glibc-headers-2.34-83.el9_3.7', 'gnutls-dane-3.7.6-23.el9', 'insights-client-3.2.2-1.el9_2', 'libblockdev-2.28-7.el9', 'libblockdev-loop-2.28-7.el9', 'libfastjson-0.99.9-5.el9', 'libvirt-daemon-9.5.0-7.el9_3', 'libvirt-daemon-driver-interface-9.5.0-7.el9_3', 'libvirt-daemon-driver-qemu-9.5.0-7.el9_3', 'openssl-devel-3.0.7-24.el9', 'python3-file-magic-5.39-14.el9', 'python3-pip-21.2.3-7.el9', 'python3-policycoreutils-3.5-2.el9', 'qemu-kvm-audio-pa-8.0.0-16.el9_3', 'qemu-kvm-core-8.0.0-16.el9_3', 'qemu-kvm-device-usb-host-8.0.0-16.el9_3', 'qemu-kvm-docs-8.0.0-16.el9_3', 'rpm-plugin-systemd-inhibit-4.16.1.3-25.el9', 'rsyslog-8.2102.0-117.el9', 'samba-client-4.18.6-100.el9', 'udisks2-iscsi-2.9.4-9.el9', 'fwupd-plugin-flashrom-1.8.16-1.el9', 'gcc-11.4.1-2.1.el9', 'gcc-plugin-annobin-11.4.1-2.1.el9', 'gnutls-utils-3.7.6-23.el9', 'libblockdev-fs-2.28-7.el9', 'libblockdev-lvm-2.28-7.el9', 'libblockdev-mdraid-2.28-7.el9', ~

Todd Lewis

unread,
Jan 15, 2024, 11:12:49 AM1/15/24
to Ansible Project
What kind of list? You've got a YAML list (with single- instead of double-quotes). You could get a JSON list (i.e. double-quotes) with
{{ output | to_json }}
or
{{ output | to_nice_json }}

What kind of list did you have in mind?

Todd Lewis

unread,
Jan 15, 2024, 11:24:55 AM1/15/24
to Ansible Project
> I changed the output path, and it worked. I'm not sure why i couldn't write to the /tmp directory

    ls -ld /tmp /tmp/installed.txt
would probably explain it.

Dimitri Yioulos

unread,
Jan 15, 2024, 12:00:18 PM1/15/24
to Ansible Project
Todd, just before your last posy, i tried  | to_nice_json and    | to_nice_yaml ,  both of which worked, to a point.

Here's what I'm after:

myhost:

The following packages will be updated
    
paho-c-1.3.13-2.el9
cpp-11.4.1-2.1.el9
glibc-headers-2.34-83.el9_3.7
gnutls-dane-3.7.6-23.el9
insights-client-3.2.2-1.el9_2
libblockdev-2.28-7.el9

This is what the output looks like in json format:

myhost:

The following packages will be updated[
    "paho-c-1.3.13-2.el9",
    "cpp-11.4.1-2.1.el9",
    "glibc-headers-2.34-83.el9_3.7",
    "gnutls-dane-3.7.6-23.el9",
    "insights-client-3.2.2-1.el9_2",
    "libblockdev-2.28-7.el9",
    ~
]

I would want to be rid of the square brackets at beginning and end. and be rid of the quotes and commas.

Here's what the output looks like in yaml format:

myhost:

The following packages will be updated- paho-c-1.3.13-2.el9

- cpp-11.4.1-2.1.el9
- glibc-headers-2.34-83.el9_3.7
- gnutls-dane-3.7.6-23.el9
- insights-client-3.2.2-1.el9_2
- libblockdev-2.28-7.el9

The first package (- paho-c-1.3.13-2.el9) is in the wrong position, and I would want to be rid of the dashes and spaces.

I hope I'm not being a pita.

Todd Lewis

unread,
Jan 15, 2024, 12:14:52 PM1/15/24
to Ansible Project
        content: |
          {% for host in ansible_play_hosts %}
          {{ host }}:
          The following packages will be updated
          {% for p in packages.results %}
          {{ p.name ~ '-' ~ p.version ~ '-' ~ p.release }}
          {% endfor %}

          {% endfor %}

Dick Visser

unread,
Jan 15, 2024, 12:15:53 PM1/15/24
to ansible...@googlegroups.com
I think you'd need to explicitly iterate over the list for that:

content: |
  {% for host in ansible_play_hosts %}
  {{ host }}:
  The following packages will be updated:

  {% for package in hostvars[host]['output'] %}
  {{ package }}

  {% endfor %}
  {% endfor %}

Dimitri Yioulos

unread,
Jan 26, 2024, 9:24:28 AM1/26/24
to Ansible Project
Good day, everyone. I've continued this thread because, although I'm getting a report of packages to be updated, in that report (and in debug output), there are multiple entries for every package. This, for example is the report output for a single package:

[deploy@myhost]$ grep grub2-common /home/deploy/updates.txt
grub2-common-2.06-70.el9_3.1
grub2-common-2.06-70.el9_3.2
grub2-common-2.06-70.el9_3.1
grub2-common-2.06-70.el9_3.2


and the debug output:

  - grub2-common-2.06-70.el9_3.1
  - grub2-common-2.06-70.el9_3.2


As per yum, the update package is grub2-common-2.06-70.el9_3.2:

grub2-common                          noarch    1:2.06-70.el9_3.2

Here's the playbook (and thanks responders to my post for helping me get this far):

---

- hosts: all
  gather_facts: false
  become: true


  tasks:
    - name: Check packages to upgrade
      yum:
        list: updates
        state: latest

      register: packages

    - name: Show packages to upgrade
      debug:
        msg: >-
          {%- set output=[] -%}
          {%- for p in packages.results -%}
          {{ output.append((p.name ~ '-' ~ p.version ~ '-' ~ p.release)) }}
          {%- endfor -%}
          {{ output }}

    - local_action:
        module: copy
        content: |
          {% for host in ansible_play_hosts %}
          {{ host }}:

          The following packages will be updated

          {% for p in packages.results %}
          {{ p.name ~ '-' ~ p.version ~ '-' ~ p.release }}

          {% endfor %}

          {% endfor %}
        dest: "/home/deploy/updates.txt"
      run_once: yes
      tags:
        - report


What do I have to change in the playbook to only get the latest package for update?

Thanks, as always.

Dimitri Yioulos

unread,
Feb 12, 2024, 3:06:16 PM2/12/24
to Ansible Project
I hope i don't upset the list if i give this a bump, as i'd really like to get a solution. Please see my previous post above.
Reply all
Reply to author
Forward
0 new messages