---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

####################################################################
# WARNING: These are designed specifically for Ansible tests       #
# and should not be used as examples of how to write Ansible roles #
####################################################################

- block:
    - name: Pick image prefix
      set_fact:
        iname_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"

    - name: Define image names
      set_fact:
        image: "{{ docker_test_image_hello_world }}"
        image_id: "{{ docker_test_image_hello_world_image_id }}"
        image_names:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"

    - name: Remove image complete
      docker_image_remove:
        name: "{{ image_id }}"
        force: true

    - name: Remove tagged images
      docker_image_remove:
        name: "{{ item }}"
      loop: "{{ image_names }}"

    - name: Make sure image we work with is there
      docker_image_pull:
        name: "{{ image }}"
      register: pulled_image
      diff: true

    - name: Remove tagged image (not there, check mode)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_1_check
      check_mode: true
      diff: true

    - name: Remove tagged image (not there)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_1
      diff: true

    - name: Inspect image
      docker_image_info:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: info_1

    - assert:
        that:
          - remove_1_check is not changed
          - remove_1_check.diff == remove_1.diff
          - remove_1 is not changed
          - remove_1.diff.before.exists is false
          - remove_1.diff.after.exists is false
          - remove_1.deleted | length == 0
          - remove_1.untagged | length == 0
          - remove_1_check.deleted == remove_1.deleted
          - remove_1_check.untagged == remove_1.untagged
          - info_1.images | length == 0

    - name: Tag image 1
      docker_image_tag:
        name: "{{ image }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"

    - name: Remove tagged image (check mode)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_2_check
      check_mode: true
      diff: true

    - name: Remove tagged image
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_2
      diff: true

    - name: Inspect image
      docker_image_info:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: info_2

    - assert:
        that:
          - remove_2_check is changed
          - remove_2_check.diff == remove_2.diff
          - remove_2 is changed
          - remove_2.diff.before.id == pulled_image.image.Id
          - remove_2.diff.before.tags | length == 4
          - remove_2.diff.before.digests | length == 1
          - remove_2.diff.after.id == pulled_image.image.Id
          - remove_2.diff.after.tags | length == 3
          - remove_2.diff.after.digests | length == 1
          - remove_2.deleted | length == 0
          - remove_2.untagged | length == 1
          - remove_2.untagged[0] == (iname_prefix ~ '-tagged-1:latest')
          - remove_2_check.deleted == remove_2.deleted
          - remove_2_check.untagged == remove_2.untagged
          - info_2.images | length == 0

    - name: Remove tagged image (idempotent, check mode)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_3_check
      check_mode: true
      diff: true

    - name: Remove tagged image (idempotent)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:latest"
      register: remove_3
      diff: true

    - assert:
        that:
          - remove_3_check is not changed
          - remove_3_check.diff == remove_3.diff
          - remove_3 is not changed
          - remove_3.diff.before.exists is false
          - remove_3.diff.after.exists is false
          - remove_3.deleted | length == 0
          - remove_3.untagged | length == 0
          - remove_3_check.deleted == remove_3.deleted
          - remove_3_check.untagged == remove_3.untagged

    - name: Inspect image with tag foo and bar
      docker_image_info:
        name:
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: info_3

    - name: Remove tagged image (force, check mode)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:foo"
        force: true
      register: remove_4_check
      check_mode: true
      diff: true

    - name: Remove tagged image (force)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:foo"
        force: true
      register: remove_4
      diff: true

    - name: Inspect image with tag foo and bar
      docker_image_info:
        name:
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: info_4

    - assert:
        that:
          - remove_4_check is changed
          - remove_4_check.diff == remove_4.diff
          - remove_4 is changed
          - remove_4.diff.before.id == pulled_image.image.Id
          - remove_4.diff.before.tags | length == 3
          - remove_4.diff.before.digests | length == 1
          - remove_4.diff.after.id == pulled_image.image.Id
          - remove_4.diff.after.tags | length == 2
          - remove_4.diff.after.digests | length == 1
          - remove_4.deleted | length == 0
          - remove_4.untagged | length == 1
          - remove_4.untagged[0] == (iname_prefix ~ '-tagged-1:foo')
          - remove_4_check.deleted == remove_4.deleted
          - remove_4_check.untagged == remove_4.untagged
          - info_3.images | length == 2
          - info_3.images[0].Id == pulled_image.image.Id
          - info_3.images[1].Id == pulled_image.image.Id
          - info_4.images | length == 1
          - info_4.images[0].Id == pulled_image.image.Id

    - name: Remove image ID (force, idempotent, check mode)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:foo"
        force: true
      register: remove_5_check
      check_mode: true
      diff: true

    - name: Remove image ID (force, idempotent)
      docker_image_remove:
        name: "{{ iname_prefix }}-tagged-1:foo"
        force: true
      register: remove_5
      diff: true

    - assert:
        that:
          - remove_5_check is not changed
          - remove_5_check.diff == remove_5.diff
          - remove_5 is not changed
          - remove_5.diff.before.exists is false
          - remove_5.diff.after.exists is false
          - remove_5.deleted | length == 0
          - remove_5.untagged | length == 0
          - remove_5_check.deleted == remove_5.deleted
          - remove_5_check.untagged == remove_5.untagged

    - name: Remove image ID (force, check mode)
      docker_image_remove:
        name: "{{ pulled_image.image.Id }}"
        force: true
      register: remove_6_check
      check_mode: true
      diff: true

    - name: Remove image ID (force)
      docker_image_remove:
        name: "{{ pulled_image.image.Id }}"
        force: true
      register: remove_6
      diff: true

    - name: Inspect image with tag foo and bar
      docker_image_info:
        name:
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: info_5

    - assert:
        that:
          - remove_6_check is changed
          - remove_6_check.diff == remove_6.diff
          - remove_6 is changed
          - remove_6.diff.before.id == pulled_image.image.Id
          - remove_6.diff.before.tags | length == 2
          - remove_6.diff.before.digests | length == 1
          - remove_6.diff.after.exists is false
          - remove_6.deleted | length > 1
          - pulled_image.image.Id in remove_6.deleted
          - remove_6.untagged | length == 3
          - (iname_prefix ~ '-tagged-1:bar') in remove_6.untagged
          - image in remove_6.untagged
          - remove_6_check.deleted | length == 1
          - remove_6_check.deleted[0] == pulled_image.image.Id
          - remove_6_check.untagged == remove_6.untagged
          - info_5.images | length == 0

    - name: Remove image ID (force, idempotent, check mode)
      docker_image_remove:
        name: "{{ pulled_image.image.Id }}"
        force: true
      register: remove_7_check
      check_mode: true
      diff: true

    - name: Remove image ID (force, idempotent)
      docker_image_remove:
        name: "{{ pulled_image.image.Id }}"
        force: true
      register: remove_7
      diff: true

    - assert:
        that:
          - remove_7_check is not changed
          - remove_7_check.diff == remove_7.diff
          - remove_7 is not changed
          - remove_7.diff.before.exists is false
          - remove_7.diff.after.exists is false
          - remove_7.deleted | length == 0
          - remove_7.untagged | length == 0
          - remove_7_check.deleted == remove_7.deleted
          - remove_7_check.untagged == remove_7.untagged

  always:
    - name: Remove tagged images
      docker_image_remove:
        name: "{{ item }}"
      loop: "{{ image_names }}"

  when: docker_api_version is version('1.25', '>=')

- fail: msg="Too old docker / docker-py version to run docker_image_info tests!"
  when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
