1

Is it possible to register, set_fact, or filter the result of Ansible modules to store a single value?

In the example below, stat returns a large object containing numerous values but I only care about the checksum. I want to save just the checksum so that I do not have to index into the full stat object every time I want to access the checksum.

- name: register checksum | grub file (/etc/default/grub)
  stat:
    path: /etc/default/grub
    checksum_algorithm: sha1
  register: grub_checksum

# DESIRED
- debug:
    msg: "{{ grub_checksum }}" 
    # "checksum": "2ef73284108f87e303c56e74aa7bc14838646cf2"

# WORKS (but requires indexing into larger stat object when I only care about checksum)
- debug:
    msg: "{{ grub_checksum.stat.checksum }}" 
    # "checksum": "2ef73284108f87e303c56e74aa7bc14838646cf2"

How can this be accomplished?

U880D
  • 8,601
  • 6
  • 24
  • 40
user2514157
  • 545
  • 6
  • 24

2 Answers2

1

You should be able to use ansible "set_fact" with a Jinja expression for the fact to extract that part in a separate task.

Something like:

- name: Extract interesting part
  set_fact:
    name_for_interesting_part: "{{ the_registered_result.interesting.part }}"
Samuel Åslund
  • 2,814
  • 2
  • 18
  • 23
  • 1
    The issue isn't so much extracting the value from stat, it is not saving the full stat object in the first place. I.e., something like <> register: grub_checksum = grub_checksum.stat.checksum – user2514157 Mar 03 '22 at 19:46
  • @user2514157 I have not seen any way to do that. Setting a fact with the extracted useful part is the way I found when needing it myself. Have you got any good reason that is not premature optimization for not registering the whole result? It's not like Ansible is fast or lean to start with ;-) – Samuel Åslund Mar 03 '22 at 20:58
  • It strikes me as a lot of overhead for a basic variable assignment compared to other languages. When I find myself wondering if there is a better way, there usually is. I wanted a sanity check to make sure I am not making things more difficult than they have to be. – user2514157 Mar 03 '22 at 23:37
  • @user2514157, regarding "_... for a basic variable assignment compared to other languages._", [Ansible is a Configuration Management Tool](https://www.ansible.com/use-cases/configuration-management) with which you [declare a state](https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html), ideally [idempotent](https://docs.ansible.com/ansible/latest/reference_appendices/glossary.html#term-Idempotency). – U880D Mar 04 '22 at 10:02
1

According the module documentation, the Return Values are a

Dictionary containing all the stat data, some platforms might add additional fields.

According the module Parameters it is possible to control parts of the gathering and output. One could try to set additionally

- name: register checksum | grub file (/etc/default/grub)
  stat:
    path: /etc/default/grub
    checksum_algorithm: sha1
    get_attributes: false
    get_mime: false
  register: grub_checksum

however, this might be still more data and information than the request for a single value checksum.

In respect of your initial request

... stat returns a large object containing numerous values but I only care about the checksum. I want to save just the checksum ...

and since the stat module has already the ability for information gathering control, you may have a look into the source ansible/lib/ansible/modules/stat.py.

It might be possible for you to

  • either enhance, extend or customize the module with an option get_values: false or checksum_only: true,
  • or create a custom module checksum.py where you have removed all for you unnecessary code parts and only get back the checksum as single value.

To do so look at the code starting from lines with if get_* and the default output = dict(...). A (quick) stripped down version of the module with checksum option only could produce an output like

TASK [Show result] **************************************
ok: [localhost] =>
  msg:
    changed: false
    failed: false
    stat:
      block_size: 4096
      blocks: 8
      checksum: 0123456789012345678901234567890123456789
      device_type: 0
      isreg: true
      readable: true

A third option could be to use the shell module to Register the checksum as single result.

- name: register checksum | grub file (/etc/default/grub)
  shell:
    cmd: sha1sum /etc/default/grub | cut -d " " -f 1
  register: grub_checksum

However, any option will still provide some more values than the requested

TASK [Show result] **********************************
ok: [localhost] =>
  msg:
    changed: true
    cmd: sha1sum /etc/default/grub | cut -d " " -f 1
    delta: '0:00:00.183056'
    end: '2022-03-04 10:00:00.043252'
    failed: false
    rc: 0
    start: '2022-03-04 10:00:00.860196'
    stderr: ''
    stderr_lines: []
    stdout: 0123456789012345678901234567890123456789
    stdout_lines:
    - 0123456789012345678901234567890123456789

because every module has common Return Values.

Further Reading

U880D
  • 8,601
  • 6
  • 24
  • 40