---
# 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

- name: Registering image name
  set_fact:
    iname: "{{ name_prefix ~ '-options' }}"

- name: Determining pushed image names
  set_fact:
    hello_world_image_base: "{{ registry_address | default('localhost') }}/test/hello-world"
    test_image_base: "{{ registry_address | default('localhost') }}/test/{{ iname }}"

- name: Registering image name
  set_fact:
    inames: "{{ inames + [iname, test_image_base ~ ':latest', test_image_base ~ ':other', hello_world_image_base ~ ':latest', hello_world_image_base ~ ':newtag', hello_world_image_base ~ ':newtag2'] }}"

####################################################################
## interact with test registry #####################################
####################################################################

- name: Run registry tests only when registry is present
  when: registry_address is defined
  block:
    - name: Make sure image is not there
      docker_image:
        name: "{{ hello_world_image_base }}:latest"
        state: absent
        force_absent: true

    - name: Make sure we have {{ docker_test_image_hello_world }}
      docker_image:
        name: "{{ docker_test_image_hello_world }}"
        source: pull

    - name: Push image to test registry
      docker_image:
        name: "{{ docker_test_image_hello_world }}"
        repository: "{{ hello_world_image_base }}:latest"
        push: true
        source: local
      register: push_1

    - name: Push image to test registry (idempotent)
      docker_image:
        name: "{{ docker_test_image_hello_world }}"
        repository: "{{ hello_world_image_base }}:latest"
        push: true
        source: local
      register: push_2

    - name: Push image to test registry (force, still idempotent)
      docker_image:
        name: "{{ docker_test_image_hello_world }}"
        repository: "{{ hello_world_image_base }}:latest"
        push: true
        source: local
        force_tag: true
      register: push_3

    - assert:
        that:
        - push_1 is changed
        - push_2 is not changed
        - push_3 is not changed

    - name: Get facts of local image
      docker_image_info:
        name: "{{ hello_world_image_base }}:latest"
      register: facts_1

    - name: Make sure image is not there
      docker_image:
        name: "{{ hello_world_image_base }}:latest"
        state: absent
        force_absent: true

    - name: Get facts of local image (absent)
      docker_image_info:
        name: "{{ hello_world_image_base }}:latest"
      register: facts_2

    - name: Pull image from test registry
      docker_image:
        name: "{{ hello_world_image_base }}:latest"
        state: present
        source: pull
      register: pull_1

    - name: Pull image from test registry (idempotency)
      docker_image:
        name: "{{ hello_world_image_base }}:latest"
        state: present
        source: pull
      register: pull_2

    - name: Get facts of local image (present)
      docker_image_info:
        name: "{{ hello_world_image_base }}:latest"
      register: facts_3

    - assert:
        that:
        - pull_1 is changed
        - pull_2 is not changed
        - facts_1.images | length == 1
        - facts_2.images | length == 0
        - facts_3.images | length == 1

    - name: Pull image from test registry (with digest)
      docker_image:
        name: "{{ hello_world_image_base }}@{{ facts_3.images[0].RepoDigests[0] | regex_replace('.*@', '') }}"
        state: present
        source: pull
        force_source: true
      register: pull_digest

    - name: Make sure that changed is still false
      assert:
        that:
          - pull_digest is not changed

    - name: Tag different image with new tag
      docker_image:
        name: "{{ docker_test_image_alpine_different }}"
        repository: "{{ hello_world_image_base }}:newtag"
        push: false
        source: pull

    - name: Push different image with new tag
      docker_image:
        name: "{{ hello_world_image_base }}"
        repository: "{{ hello_world_image_base }}"
        tag: newtag
        push: true
        source: local
      register: push_1_different

    - name: Push different image with new tag (idempotent)
      docker_image:
        name: "{{ hello_world_image_base }}"
        repository: "{{ hello_world_image_base }}"
        tag: newtag
        push: true
        source: local
      register: push_2_different

    - assert:
        that:
        - push_1_different is changed
        - push_2_different is not changed

    - name: Tag same image with new tag
      docker_image:
        name: "{{ docker_test_image_alpine_different }}"
        repository: "{{ hello_world_image_base }}:newtag2"
        push: false
        source: pull

    - name: Push same image with new tag
      docker_image:
        name: "{{ hello_world_image_base }}"
        repository: "{{ hello_world_image_base }}"
        tag: newtag2
        push: true
        source: local
      register: push_1_same

    - name: Push same image with new tag (idempotent)
      docker_image:
        name: "{{ hello_world_image_base }}"
        repository: "{{ hello_world_image_base }}"
        tag: newtag2
        push: true
        source: local
      register: push_2_same

    - assert:
        that:
        # NOTE: This should be:
        #   - push_1_same is changed
        # Unfortunately docker does *NOT* report whether the tag already existed or not.
        # Here are the logs returned by client.push() for both tasks (which are exactly the same):
        #   push_1_same:
        #     {"status": "The push refers to repository [localhost:32796/test/hello-world]"},
        #     {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Preparing"},
        #     {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Layer already exists"},
        #     {"status": "newtag2: digest: sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b size: 528"},
        #     {"aux": {"Digest": "sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b", "Size": 528, "Tag": "newtag2"}, "progressDetail": {}}
        #   push_2_same:
        #     {"status": "The push refers to repository [localhost:32796/test/hello-world]"},
        #     {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Preparing"},
        #     {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Layer already exists"},
        #     {"status": "newtag2: digest: sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b size: 528"},
        #     {"aux": {"Digest": "sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b", "Size": 528, "Tag": "newtag2"}, "progressDetail": {}}
        - push_1_same is not changed
        - push_2_same is not changed

####################################################################
## repository ######################################################
####################################################################

- name: Make sure image is not there
  docker_image:
    name: "{{ test_image_base }}:latest"
    state: absent
    force_absent: true

- name: repository
  docker_image:
    name: "{{ iname }}"
    build:
      path: "{{ remote_tmp_dir }}/files"
      pull: false
    repository: "{{ test_image_base }}"
    source: build
  register: repository_1

- name: repository (idempotent)
  docker_image:
    name: "{{ iname }}"
    repository: "{{ test_image_base }}"
    source: local
  register: repository_2

- name: repository, tag with ID
  docker_image:
    name: "{{ repository_1.image.Id }}"
    repository: "{{ test_image_base }}:other"
    source: local
  register: repository_3

- name: repository, tag with ID (idempotent)
  docker_image:
    name: "{{ repository_1.image.Id }}"
    repository: "{{ test_image_base }}:other"
    source: local
    force_tag: true
  register: repository_4

- assert:
    that:
    - repository_1 is changed
    - repository_2 is not changed
    - repository_3 is changed
    - repository_4 is not changed

- name: Get facts of image
  docker_image_info:
    name: "{{ test_image_base }}:latest"
  register: facts_1

- name: cleanup
  docker_image:
    name: "{{ test_image_base }}:latest"
    state: absent
    force_absent: true

- assert:
    that:
    - facts_1.images | length == 1
