Malte Krupa


Ansible Loop With Conditions - 2022-09-09

Update

Wow, a couple days later I see this option on the unarchive module. m(

Original post

While writing an ansible role (source) that would create and setup FreeBSD jails, I needed to find a way to only extract the base.txz file (containing the base operating system) to a directory when it hasn’t been done before.

This should only be done once to prevent overwritten files and save time.

My first attempt was a naive check if the directory or a file in the directory already exist.

- name: Check jails for extracted base.txz
    ansible.builtin.stat:
      path: "/usr/local/jails/{{ item }}/root/etc/passwd"
    loop:
      "{{ jails_create.keys() | flatten(levels=1) }}"
    register: jails_stat

This works quite nice. The next step would be to extract the base.txz file under certain conditions.

- name: Extract base.txz
  ansible.builtin.unarchive:
    src: /tmp/base.txz
    dest: "/usr/local/jails/{{ item.item }}/root"
    remote_src: yes
  loop: "{{ jails_stat.results }}"
  when:
    - item is not skipped
    - not item.stat.exists

Instead of looping over the jails_create list, we iterate over the results of the previous check. This allows us to access the required information for the conditions more easily.

Both of these took me about an hour to figure out (of course with the help of stackoverflow and the ansible documentation). And when I finally ran both of these without --check --diff, to actually get a result, I ran into the following error:

Failed to find handler for "/tmp/base.txz".
Make sure the required command to extract the file is installed.

Command "/usr/bin/tar" detected as tar type bsd. GNU tar required.

Unable to find required 'zipinfo' binary in the path.

🧘

So, finally, I replaced both of these with something that is way shorter, easier to read and less complicated:

- name: Extract base.txz to jails
  ansible.builtin.command: "tar -xvf /tmp/base.txz -C /usr/local/jails/{{ item }}/root"
    args:
      creates: "/usr/local/jails/{{ item }}/root/etc/passwd"
    loop:
      "{{ jails_create.keys() | flatten(levels=1) }}"

That’s it. Took me less than five minutes and makes me way more happy.

And of course, there are better solutions to managing jails. But I’ll take one step after another.


Privacy Policy | Imprint