Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker_container: add image_name_mismatch option #488

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/488-docker_container-image-name.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- "docker_container - added ``image_name_mismatch`` option which allows to control the behavior if the container uses the image specified, but the container's configuration uses a different name for the image than the one provided to the module (https://github.com/ansible-collections/community.docker/issues/485, https://github.com/ansible-collections/community.docker/pull/488)."
4 changes: 4 additions & 0 deletions plugins/module_utils/module_container/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ def get_container_id(self, container):
def get_image_from_container(self, container):
pass

@abc.abstractmethod
def get_image_name_from_container(self, container):
pass

@abc.abstractmethod
def is_container_removing(self, container):
pass
Expand Down
3 changes: 3 additions & 0 deletions plugins/module_utils/module_container/docker_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ def get_container_id(self, container):
def get_image_from_container(self, container):
return container['Image']

def get_image_name_from_container(self, container):
return container['Config'].get('Image')

def is_container_removing(self, container):
if container.get('State'):
return container['State'].get('Status') == 'removing'
Expand Down
7 changes: 7 additions & 0 deletions plugins/module_utils/module_container/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ def __init__(self, container, engine_driver):
self.raw = container
self.id = None
self.image = None
self.image_name = None
self.container = container
self.engine_driver = engine_driver
if container:
self.id = engine_driver.get_container_id(container)
self.image = engine_driver.get_image_from_container(container)
self.image_name = engine_driver.get_image_name_from_container(container)
self.log(self.container, pretty_print=True)

@property
Expand Down Expand Up @@ -68,6 +70,7 @@ def __init__(self, module, engine_driver, client, active_options):
self.param_image = self.module.params['image']
self.param_image_comparison = self.module.params['image_comparison']
self.param_image_label_mismatch = self.module.params['image_label_mismatch']
self.param_image_name_mismatch = self.module.params['image_name_mismatch']
self.param_keep_volumes = self.module.params['keep_volumes']
self.param_kill_signal = self.module.params['kill_signal']
self.param_name = self.module.params['name']
Expand Down Expand Up @@ -303,6 +306,9 @@ def present(self, state):
image_different = False
if self.all_options['image'].comparison == 'strict':
image_different = self._image_is_different(image, container)
if self.param_image_name_mismatch == 'recreate' and self.param_image is not None and self.param_image != container.image_name:
different = True
self.diff_tracker.add('image_name', parameter=self.param_image, active=container.image_name)
if image_different or different or self.param_recreate:
self.diff_tracker.merge(differences)
self.diff['differences'] = differences.get_legacy_docker_container_diffs()
Expand Down Expand Up @@ -803,6 +809,7 @@ def run_module(engine_driver):
image=dict(type='str'),
image_comparison=dict(type='str', choices=['desired-image', 'current-image'], default='desired-image'),
image_label_mismatch=dict(type='str', choices=['ignore', 'fail'], default='ignore'),
image_name_mismatch=dict(type='str', choices=['ignore', 'recreate'], default='ignore'),
keep_volumes=dict(type='bool', default=True),
kill_signal=dict(type='str'),
name=dict(type='str', required=True),
Expand Down
14 changes: 14 additions & 0 deletions plugins/modules/docker_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,20 @@
- 'fail'
default: ignore
version_added: 2.6.0
image_name_mismatch:
description:
- Determines what the module does if the image matches, but the image name in the container's configuration
does not match the image name provided to the module.
- "This is ignored if C(image: ignore) is set in I(comparisons)."
- If set to C(recreate) the container will be recreated.
- If set to C(ignore) the container will not be recreated because of this. It might still get recreated for other reasons.
This has been the default behavior of the module for a long time, but might not be what users expect.
type: str
choices:
- recreate
- ignore
default: ignore
version_added: 3.2.0
init:
description:
- Run an init inside the container that forwards signals and reaps processes.
Expand Down
149 changes: 149 additions & 0 deletions tests/integration/targets/docker_container/tasks/tests/options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2420,6 +2420,155 @@
- image_label_mismatch_10 is not changed
- image_label_mismatch_11 is changed

####################################################################
## image_name_mismatch #############################################
####################################################################

- name: Pull images to make sure ignore_image test succeeds
# If the image isn't there, it will pull it and return 'changed'.
docker_image:
name: "{{ item }}"
source: pull
loop:
- "{{ docker_test_image_hello_world }}"
- "{{ docker_test_image_registry_nginx }}"

- name: image
docker_container:
image: "{{ docker_test_image_alpine }}"
command: '/bin/sh -c "sleep 10m"'
name: "{{ cname }}"
state: started
register: image_1

- name: image (idempotency)
docker_container:
image: "{{ docker_test_image_alpine }}"
command: '/bin/sh -c "sleep 10m"'
name: "{{ cname }}"
state: started
register: image_2
diff: true

- name: ignore_image
docker_container:
image: "{{ docker_test_image_hello_world }}"
ignore_image: yes
name: "{{ cname }}"
state: started
register: ignore_image
diff: true

- name: ignore_image (labels and env differ in image, image_comparison=current-image)
docker_container:
image: "{{ docker_test_image_registry_nginx }}"
ignore_image: yes
image_comparison: current-image
name: "{{ cname }}"
state: started
register: ignore_image_2
diff: true

- name: ignore_image (labels and env differ in image, image_comparison=desired-image)
docker_container:
image: "{{ docker_test_image_registry_nginx }}"
ignore_image: yes
image_comparison: desired-image
name: "{{ cname }}"
state: started
force_kill: yes
register: ignore_image_3
diff: true

- name: image change
docker_container:
image: "{{ docker_test_image_hello_world }}"
name: "{{ cname }}"
state: started
force_kill: yes
register: image_change
diff: true

- name: cleanup
docker_container:
name: "{{ cname }}"
state: absent
force_kill: yes
diff: no

- assert:
that:
- image_1 is changed
- image_2 is not changed
- ignore_image is not changed
- ignore_image_2 is not changed
- ignore_image_3 is changed
- image_change is changed

####################################################################
## image_name_mismatch #############################################
####################################################################

- name: Registering image name
set_fact:
iname_name_mismatch: "{{ cname_prefix ~ '-image-name' }}"
- name: Registering image name
set_fact:
inames: "{{ inames + [iname_name_mismatch] }}"

- name: Tag hello world image (pulled earlier) with new name
docker_image:
name: "{{ docker_test_image_registry_nginx }}"
source: local
repository: "{{ iname_name_mismatch }}:latest"

- name: image_name_mismatch
docker_container:
image: "{{ docker_test_image_registry_nginx }}"
command: '/bin/sh -c "sleep 10m"'
name: "{{ cname }}"
state: started
register: image_name_mismatch_1

- name: image_name_mismatch (ignore)
docker_container:
image: "{{ iname_name_mismatch }}:latest"
command: '/bin/sh -c "sleep 10m"'
name: "{{ cname }}"
image_name_mismatch: ignore
state: started
register: image_name_mismatch_2

- name: image_name_mismatch (recreate)
docker_container:
image: "{{ iname_name_mismatch }}:latest"
command: '/bin/sh -c "sleep 10m"'
name: "{{ cname }}"
image_name_mismatch: recreate
state: started
force_kill: yes
register: image_name_mismatch_3

- name: Cleanup container
docker_container:
name: "{{ cname }}"
state: absent
force_kill: yes
diff: no

- name: Cleanup image
docker_image:
name: "{{ iname_name_mismatch }}"
state: absent
diff: no

- assert:
that:
- image_name_mismatch_1 is changed
- image_name_mismatch_2 is not changed
- image_name_mismatch_3 is changed
- image_name_mismatch_3.container.Image == image_name_mismatch_2.container.Image

####################################################################
## ipc_mode ########################################################
####################################################################
Expand Down