---
# 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_1: "{{ docker_test_image_hello_world }}"
        image_2: "{{ docker_test_image_alpine }}"
        image_3: "{{ docker_test_image_digest_base }}@sha256:{{ docker_test_image_digest_v1 }}"
        image_names:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
          - "{{ iname_prefix }}-tagged-2:baz"

    - name: Make sure images we work with are there
      docker_image_pull:
        name: "{{ item }}"
      loop:
        - "{{ image_1 }}"
        - "{{ image_2 }}"
        - "{{ image_3 }}"
      register: pulled_images
      diff: true

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

    - name: Tag image 1 (check mode)
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
      register: tag_1_check
      diff: true
      check_mode: true

    - name: Tag image 1
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
      register: tag_1
      diff: true

    - name: Fetch image infos
      docker_image_info:
        name: "{{ image_names }}"
      register: info_1

    - assert:
        that:
          - tag_1 is changed
          - tag_1.diff.before.images | length == 2
          - tag_1.diff.before.images[0] != tag_1.diff.after.images[0]
          - tag_1.diff.before.images[1] != tag_1.diff.after.images[1]
          - tag_1.diff.before.images[0].exists is false
          - tag_1.diff.before.images[1].exists is false
          - tag_1.diff.after.images[0].id == pulled_images.results[0].image.Id
          - tag_1.diff.after.images[1].id == pulled_images.results[0].image.Id
          - info_1.images | length == 2
          - info_1.images[0].Id == pulled_images.results[0].image.Id
          - info_1.images[1].Id == pulled_images.results[0].image.Id
          - tag_1_check == tag_1

    - name: Tag image 1 (idempotent, check mode)
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
      register: tag_2_check
      diff: true
      check_mode: true

    - name: Tag image 1 (idempotent)
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
      register: tag_2
      diff: true

    - assert:
        that:
          - tag_2 is not changed
          - tag_2.diff.before == tag_2.diff.after
          - tag_2.diff.before.images | length == 2
          - tag_2_check == tag_2

    - name: Tag image 1 (idempotent, different input format, check mode)
      docker_image_tag:
        name: "{{ image_1 }}"
        tag: foo
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1"
      register: tag_3_check
      diff: true
      check_mode: true

    - name: Tag image 1 (idempotent, different input format)
      docker_image_tag:
        name: "{{ image_1 }}"
        tag: foo
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1"
      register: tag_3
      diff: true

    - assert:
        that:
          - tag_3 is not changed
          - tag_3.diff.before == tag_3.diff.after
          - tag_3.diff.before.images | length == 2
          - tag_3_check == tag_3

    - name: Tag image 1 (one more, check mode)
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-2:baz"
      register: tag_4_check
      diff: true
      check_mode: true

    - name: Tag image 1 (one more)
      docker_image_tag:
        name: "{{ image_1 }}"
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-2:baz"
      register: tag_4
      diff: true

    - name: Fetch image infos
      docker_image_info:
        name: "{{ image_names }}"
      register: info_4

    - assert:
        that:
          - tag_4 is changed
          - tag_4.diff.before.images | length == 3
          - tag_4.diff.before.images[0] == tag_4.diff.after.images[0]
          - tag_4.diff.before.images[1] == tag_4.diff.after.images[1]
          - tag_4.diff.before.images[2] != tag_4.diff.after.images[2]
          - tag_4.diff.before.images[2].exists is false
          - tag_4.diff.after.images[0].id == pulled_images.results[0].image.Id
          - tag_4.diff.after.images[1].id == pulled_images.results[0].image.Id
          - tag_4.diff.after.images[2].id == pulled_images.results[0].image.Id
          - info_4.images | length == 3
          - info_4.images[0].Id == pulled_images.results[0].image.Id
          - info_4.images[1].Id == pulled_images.results[0].image.Id
          - info_4.images[2].Id == pulled_images.results[0].image.Id
          - tag_4_check == tag_4

    - name: Tag image 2 (only change missing one, check mode)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: keep
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_5_check
      diff: true
      check_mode: true

    - name: Tag image 2 (only change missing one)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: keep
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_5
      diff: true

    - name: Fetch image infos
      docker_image_info:
        name: "{{ image_names }}"
      register: info_5

    - assert:
        that:
          - tag_5 is changed
          - tag_5.diff.before.images | length == 3
          - tag_5.diff.before.images[0] == tag_5.diff.after.images[0]
          - tag_5.diff.before.images[1] == tag_5.diff.after.images[1]
          - tag_5.diff.before.images[2] != tag_5.diff.after.images[2]
          - tag_5.diff.before.images[2].exists is false
          - tag_5.diff.after.images[0].id == pulled_images.results[0].image.Id
          - tag_5.diff.after.images[1].id == pulled_images.results[0].image.Id
          - tag_5.diff.after.images[2].id == pulled_images.results[1].image.Id
          - info_5.images | length == 4
          - info_5.images[0].Id == pulled_images.results[0].image.Id
          - info_5.images[1].Id == pulled_images.results[0].image.Id
          - info_5.images[2].Id == pulled_images.results[1].image.Id
          - info_5.images[3].Id == pulled_images.results[0].image.Id
          - tag_5_check == tag_5

    - name: Tag image 2 (idempotent, check mode)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: keep
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_6_check
      diff: true
      check_mode: true

    - name: Tag image 2 (idempotent)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: keep
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_6
      diff: true

    - assert:
        that:
          - tag_6 is not changed
          - tag_6.diff.before == tag_6.diff.after
          - tag_6.diff.before.images | length == 3
          - tag_6_check == tag_6

    - name: Tag image 2 (only change wrong ones, check mode)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_7_check
      diff: true
      check_mode: true

    - name: Tag image 2 (only change wrong ones)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_7
      diff: true

    - name: Fetch image infos
      docker_image_info:
        name: "{{ image_names }}"
      register: info_7

    - assert:
        that:
          - tag_7 is changed
          - tag_7.diff.before.images | length == 3
          - tag_7.diff.before.images[0] != tag_7.diff.after.images[0]
          - tag_7.diff.before.images[1] != tag_7.diff.after.images[1]
          - tag_7.diff.before.images[2] == tag_7.diff.after.images[2]
          - tag_7.diff.before.images[0].id == pulled_images.results[0].image.Id
          - tag_7.diff.before.images[1].id == pulled_images.results[0].image.Id
          - tag_7.diff.after.images[0].id == pulled_images.results[1].image.Id
          - tag_7.diff.after.images[1].id == pulled_images.results[1].image.Id
          - tag_7.diff.after.images[2].id == pulled_images.results[1].image.Id
          - info_7.images | length == 4
          - info_7.images[0].Id == pulled_images.results[1].image.Id
          - info_7.images[1].Id == pulled_images.results[1].image.Id
          - info_7.images[2].Id == pulled_images.results[1].image.Id
          - info_7.images[3].Id == pulled_images.results[0].image.Id
          - tag_7_check == tag_7

    - name: Tag image 2 (idempotent, check mode)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_8_check
      diff: true
      check_mode: true

    - name: Tag image 2 (idempotent)
      docker_image_tag:
        name: "{{ image_2 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-1:latest"
          - "{{ iname_prefix }}-tagged-1:foo"
          - "{{ iname_prefix }}-tagged-1:bar"
      register: tag_8
      diff: true

    - assert:
        that:
          - tag_8 is not changed
          - tag_8.diff.before == tag_8.diff.after
          - tag_8.diff.before.images | length == 3
          - tag_8_check == tag_8

    - name: Tag image 3 (source image has digest)
      docker_image_tag:
        name: "{{ image_3 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-2:baz"
      register: tag_9
      diff: true

    - assert:
        that:
          - tag_9 is changed
          - tag_9.diff.before.images | length == 1
          - tag_9.diff.before.images[0].id == pulled_images.results[0].image.Id
          - tag_9.diff.after.images[0].id == pulled_images.results[2].image.Id

    - name: Tag image 3 (source image is ID)
      docker_image_tag:
        name: "{{ pulled_images.results[2].image.Id }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-1:foo"
      register: tag_10
      diff: true

    - assert:
        that:
          - tag_10 is changed
          - tag_10.diff.before.images | length == 1
          - tag_10.diff.before.images[0].id == pulled_images.results[1].image.Id
          - tag_10.diff.after.images[0].id == pulled_images.results[2].image.Id

    - name: Tag image 3 (fail because of digest)
      docker_image_tag:
        name: "{{ image_3 }}"
        existing_images: overwrite
        repository:
          - "{{ iname_prefix }}-tagged-2@sha256:{{ docker_test_image_digest_v1 }}"
      register: tag_11
      ignore_errors: true

    - assert:
        that:
          - tag_11 is failed
          - >-
            tag_11.msg == ('repository[1] must not have a digest; got: ' ~ iname_prefix ~ '-tagged-2@sha256:' ~ docker_test_image_digest_v1)

    - name: Tag image 3 (fail because of image ID)
      docker_image_tag:
        name: "{{ image_3 }}"
        existing_images: overwrite
        repository:
          - "sha256:{{ docker_test_image_digest_v1 }}"
      register: tag_12
      ignore_errors: true

    - assert:
        that:
          - tag_12 is failed
          - >-
            tag_12.msg == ('repository[1] must not be an image ID; got: sha256:' ~ docker_test_image_digest_v1)

  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)
