d1530
d1530

Reputation: 171

Ansible Looping with conditional

I'm attempting to loop over a list ( I think) with a conditional which also is a list. According to the documentation the conditional should be re-evaluated with each loop. However, I'm finding this not the case.

Here are my two lists which are being set via a set_fact task:

  image_id:
  - 4bc0467496b6c7a60543069c570ef0e1be4565d25cb2bc7d524600a5fe0d3b8f
  - dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6
  - e911c149c0ca46a11a8b6eb604439e972685ec25abfde07eb1cdb272a9c0d1a9
  - eb40451959b6c5f4aebb2b687a589a58370faab9b15faa43c0aea8d711155b9e

  container_id:
  - dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6

Then, I'm attempting to loop through the image_id list and remove any images. However, don't remove the items listed in the container_id list.

- name: remove images no longer used
  containers.podman.podman_image:
    name: "{{ item }}"
    state: absent
  loop: "{{ image_id }}"
  when: container_id != image_id

I'm expecting all images to be remove except for the one listed in the container_id variable. Here is my output from the task above:

TASK [docker-host : remove images no longer used] *********************************************************************************************************************************************************
changed: [dtest05] => (item=4bc0467496b6c7a60543069c570ef0e1be4565d25cb2bc7d524600a5fe0d3b8f)
failed: [dtest05] (item=dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6) => changed=false
  ansible_loop_var: item
  item: dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6
  msg: |-
    Failed to remove image with id dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6. Error: Image used by 099e729245fb339753cc7ad5e86480965faf2f638dbeb7f535336a532af34de0: image is in use by a container
changed: [dtest05] => (item=e911c149c0ca46a11a8b6eb604439e972685ec25abfde07eb1cdb272a9c0d1a9)
changed: [dtest05] => (item=eb40451959b6c5f4aebb2b687a589a58370faab9b15faa43c0aea8d711155b9e)

I was expecting the failed task to be skipped. If I re-run the task, I do see the task being skipped.

TASK [docker-host : Setting Facts for Image IDs] **********************************************************************************************************************************************************
ok: [dtest05]

TASK [docker-host : debug image_id] ***********************************************************************************************************************************************************************
ok: [dtest05] =>
  image_id:
  - dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6

TASK [docker-host : debug container_id] *******************************************************************************************************************************************************************
ok: [dtest05] =>
  container_id:
  - dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6

TASK [docker-host : remove images no longer used] *********************************************************************************************************************************************************
skipping: [dtest05] => (item=dbcefaa52e7009f5d9b6179a256e70890d29148add0f77741ca4550ba2e2ffa6)

Am I not understanding the documentation correctly? I'm thinking that my first run should not fail but have an skipped item.

Upvotes: 0

Views: 114

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68004

Use the filter difference. For example, the playbook below

- hosts: localhost
  
  vars:

    image_id:
      - 4bc046
      - dbcefa
      - e911c1
      - eb4045

    container_id:
      - dbcefa

  tasks:

    - debug:
        msg: "{{ item }}"
      loop: "{{ image_id|difference(container_id) }}"

gives (abridged)

  msg: 4bc046
  msg: e911c1
  msg: eb4045

Upvotes: 1

larsks
larsks

Reputation: 311416

The expression container_id != image_id doesn't make any sense. You're comparing the same two things for every iteration of the loop, and because the two variables are two unequal lists the comparison will always be false.

It looks like you're trying to check if item is contained in the container_id list, which would look something like:

    - name: remove images no longer used
      containers.podman.podman_image:
        name: "{{ item }}"
        state: absent
      loop: "{{ image_id }}"
      when: item not in container_id

Note that you can achieve the same thing with less work by running podman image prune -af (perhaps via command task).

Upvotes: 2

Related Questions