From b775bac593591ebabadd1fb7110e7e92fb18c2e3 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 7 Jun 2021 07:01:10 +0200 Subject: [PATCH] docker_image: allow to tag images by name, improve docs (#149) * Add test to tag image with ID. * Document that source=local also works with image IDs. * Improve 'repository' documentation. * Fix typo. * Looks like a fix is needed to make this work. * ... * Avoid unnecessary re.search() calls. * Add changelog fragment. * Improve main description. * Remove import. --- .../fragments/149-docker_image-tagging.yml | 2 ++ plugins/modules/docker_image.py | 30 ++++++++++--------- .../docker_image/tasks/tests/docker_image.yml | 24 +++++++++++---- .../docker_image/tasks/tests/options.yml | 2 +- 4 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 changelogs/fragments/149-docker_image-tagging.yml diff --git a/changelogs/fragments/149-docker_image-tagging.yml b/changelogs/fragments/149-docker_image-tagging.yml new file mode 100644 index 00000000..91d2c228 --- /dev/null +++ b/changelogs/fragments/149-docker_image-tagging.yml @@ -0,0 +1,2 @@ +minor_changes: +- "docker_image - allow to tag images by ID (https://github.com/ansible-collections/community.docker/pull/149)." diff --git a/plugins/modules/docker_image.py b/plugins/modules/docker_image.py index f3bde7a5..96881d14 100644 --- a/plugins/modules/docker_image.py +++ b/plugins/modules/docker_image.py @@ -11,12 +11,12 @@ DOCUMENTATION = ''' --- module: docker_image -short_description: Manage docker images. +short_description: Manage docker images description: - - Build, load or pull an image, making the image available for creating containers. Also supports tagging an - image into a repository and archiving an image to a C(.tar) file. + - Build, load or pull an image, making the image available for creating containers. Also supports tagging + an image, pushing an image, and archiving an image to a C(.tar) file. options: source: @@ -157,7 +157,8 @@ options: description: - "Image name. Name format will be one of: C(name), C(repository/name), C(registry_server:port/name). When pushing or pulling an image the name can optionally include the tag by appending C(:tag_name)." - - Note that image IDs (hashes) are only supported for I(state=absent), and for I(state=present) with I(source=load). + - Note that image IDs (hashes) are only supported for I(state=absent), for I(state=present) with I(source=load), + and for I(state=present) with I(source=local). type: str required: yes pull: @@ -179,8 +180,10 @@ options: default: no repository: description: - - Full path to a repository. Use with state C(present) to tag the image into the repository. Expects - format I(repository:tag). If no tag is provided, will use the value of the C(tag) parameter or I(latest). + - Use with state C(present) to tag the image. + - Expects format C(repository:tag). If no tag is provided, will use the value of the I(tag) parameter or C(latest). + - If I(push=true), I(repository) must either include a registry, or will be assumed to belong to the default + registry (Docker Hub). type: str state: description: @@ -321,7 +324,6 @@ stdout: import errno import os -import re import traceback from distutils.version import LooseVersion @@ -587,8 +589,8 @@ class ImageManager(DockerBaseClass): changed = True self.results['changed'] = changed except Exception as exc: - if re.search('unauthorized', str(exc)): - if re.search('authentication required', str(exc)): + if 'unauthorized' in str(exc): + if 'authentication required' in str(exc): self.fail("Error pushing image %s/%s:%s - %s. Try logging into %s first." % (registry, repo_name, tag, to_native(exc), registry)) else: @@ -620,16 +622,16 @@ class ImageManager(DockerBaseClass): self.log("image %s was %s" % (repo, found)) if not image or self.force_tag: - self.log("tagging %s:%s to %s:%s" % (name, tag, repo, repo_tag)) + image_name = name + if not is_image_name_id(name) and tag and not name.endswith(':' + tag): + image_name = "%s:%s" % (name, tag) + self.log("tagging %s to %s:%s" % (image_name, repo, repo_tag)) self.results['changed'] = True - self.results['actions'].append("Tagged image %s:%s to %s:%s" % (name, tag, repo, repo_tag)) + self.results['actions'].append("Tagged image %s to %s:%s" % (image_name, repo, repo_tag)) if not self.check_mode: try: # Finding the image does not always work, especially running a localhost registry. In those # cases, if we don't set force=True, it errors. - image_name = name - if tag and not re.search(tag, name): - image_name = "%s:%s" % (name, tag) tag_status = self.client.tag(image_name, repo, tag=repo_tag, force=True) if not tag_status: raise Exception("Tag operation failed.") diff --git a/tests/integration/targets/docker_image/tasks/tests/docker_image.yml b/tests/integration/targets/docker_image/tasks/tests/docker_image.yml index f256f8d8..13e4abcd 100644 --- a/tests/integration/targets/docker_image/tasks/tests/docker_image.yml +++ b/tests/integration/targets/docker_image/tasks/tests/docker_image.yml @@ -10,7 +10,7 @@ - name: Registering image name set_fact: - inames: "{{ inames + [iname, test_image_base ~ ':latest', hello_world_image_base ~ ':latest', hello_world_image_base ~ ':newtag', hello_world_image_base ~ ':newtag2'] }}" + 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 ##################################### @@ -200,17 +200,31 @@ - name: repository (idempotent) docker_image: name: "{{ iname }}" - build: - path: "{{ output_dir }}/files" - pull: no repository: "{{ test_image_base }}" - source: build + 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: diff --git a/tests/integration/targets/docker_image/tasks/tests/options.yml b/tests/integration/targets/docker_image/tasks/tests/options.yml index 246f95fe..b800f8ad 100644 --- a/tests/integration/targets/docker_image/tasks/tests/options.yml +++ b/tests/integration/targets/docker_image/tasks/tests/options.yml @@ -245,7 +245,7 @@ docker_image: name: "{{ archive_image.image.Id }}" archive_path: "{{ output_dir }}/image_id.tar" - source: pull + source: local register: archive_image_id - name: Create invalid archive