From 65768b996d8580ec8bb1188ed98471a4456f8938 Mon Sep 17 00:00:00 2001
From: Felix Fontein <felix@fontein.de>
Date: Thu, 1 Nov 2018 09:08:43 +0100
Subject: [PATCH] docker_container: fix paused and add some tests (#47900)

* cleanup is already tested.

* Add test for paused.

* Add recreate and restart tests.

* timeout is a common docker option

* Implement paused and fix paused test.

* Add changelog.

* Improve paused test.
---
 .../47900-docker_container-paused.yml         |   2 +
 .../modules/cloud/docker/docker_container.py  |  20 ++
 .../docker_container/tasks/tests/options.yml  | 171 ++++++++++++++++--
 3 files changed, 177 insertions(+), 16 deletions(-)
 create mode 100644 changelogs/fragments/47900-docker_container-paused.yml

diff --git a/changelogs/fragments/47900-docker_container-paused.yml b/changelogs/fragments/47900-docker_container-paused.yml
new file mode 100644
index 00000000000..ae19f6ed859
--- /dev/null
+++ b/changelogs/fragments/47900-docker_container-paused.yml
@@ -0,0 +1,2 @@
+bugfixes:
+- "docker_container - fix ``paused`` option (which never worked)."
diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py
index 573c28228d9..507900eeaea 100644
--- a/lib/ansible/modules/cloud/docker/docker_container.py
+++ b/lib/ansible/modules/cloud/docker/docker_container.py
@@ -1538,6 +1538,12 @@ class Container(DockerBaseClass):
                 return True
         return False
 
+    @property
+    def paused(self):
+        if self.container and self.container.get('State'):
+            return self.container['State'].get('Paused', False)
+        return False
+
     def _compare(self, a, b, compare):
         '''
         Compare values a and b as described in compare.
@@ -2122,6 +2128,20 @@ class ContainerManager(DockerBaseClass):
                 self.container_stop(container.Id)
                 container = self._get_container(container.Id)
 
+            if state == 'started' and container.paused != self.parameters.paused:
+                if not self.check_mode:
+                    try:
+                        if self.parameters.paused:
+                            self.client.pause(container=container.Id)
+                        else:
+                            self.client.unpause(container=container.Id)
+                    except Exception as exc:
+                        self.fail("Error %s container %s: %s" % (
+                            "pausing" if self.parameters.paused else "unpausing", container.Id, str(exc)
+                        ))
+                self.results['changed'] = True
+                self.results['actions'].append(dict(set_paused=self.parameters.paused))
+
         self.facts = container.raw
 
     def absent(self):
diff --git a/test/integration/targets/docker_container/tasks/tests/options.yml b/test/integration/targets/docker_container/tasks/tests/options.yml
index 5fc7d2a272b..a06ce32d9a9 100644
--- a/test/integration/targets/docker_container/tasks/tests/options.yml
+++ b/test/integration/targets/docker_container/tasks/tests/options.yml
@@ -159,12 +159,6 @@
     - capabilities_3 is not changed
     - capabilities_4 is changed
 
-####################################################################
-## cleanup #########################################################
-####################################################################
-
-# TODO: - cleanup
-
 ####################################################################
 ## command #########################################################
 ####################################################################
@@ -477,7 +471,7 @@
     - debug_4 is changed
 
 ####################################################################
-## detach ##########################################################
+## detach, cleanup #################################################
 ####################################################################
 
 - name: detach without cleanup
@@ -2316,7 +2310,69 @@
 ## paused ##########################################################
 ####################################################################
 
-# TODO: - paused
+- name: paused
+  docker_container:
+    image: alpine:3.8
+    command: "/bin/sh -c 'sleep 1s ; yes'"
+    name: "{{ cname }}"
+    state: started
+    paused: yes
+    stop_timeout: 1
+  register: paused_1
+
+- pause:
+    seconds: 2
+
+- name: paused (logs)
+  command: docker logs --tail=20 "{{ cname }}"
+  register: paused_2
+
+- name: paused (idempotent)
+  docker_container:
+    image: alpine:3.8
+    command: "/bin/sh -c 'sleep 1s ; yes'"
+    name: "{{ cname }}"
+    state: started
+    paused: yes
+    stop_timeout: 1
+  register: paused_3
+
+- name: paused (continue)
+  docker_container:
+    image: alpine:3.8
+    command: "/bin/sh -c 'sleep 1s ; yes'"
+    name: "{{ cname }}"
+    state: started
+    paused: no
+    stop_timeout: 1
+  register: paused_4
+
+- pause:
+    seconds: 2
+
+- name: paused (stop)
+  docker_container:
+    name: "{{ cname }}"
+    state: stopped
+    stop_timeout: 1
+
+- name: paused (logs)
+  command: docker logs --tail=20 "{{ cname }}"
+  register: paused_5
+
+- name: cleanup
+  docker_container:
+    name: "{{ cname }}"
+    state: absent
+    stop_timeout: 1
+
+- assert:
+    that:
+    - paused_1 is changed
+    - paused_2.stdout_lines | length == 0
+    - paused_3 is not changed
+    - paused_4 is changed
+    - paused_5.stdout_lines | length > 0
 
 ####################################################################
 ## pid_mode ########################################################
@@ -2534,13 +2590,102 @@
 ## recreate ########################################################
 ####################################################################
 
-# TODO: - recreate
+- name: recreate (created)
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    state: present
+    stop_timeout: 1
+  register: recreate_1
+
+- name: recreate (created, recreate)
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    recreate: yes
+    state: present
+    stop_timeout: 1
+  register: recreate_2
+
+- name: recreate (started)
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    state: started
+    stop_timeout: 1
+  register: recreate_3
+
+- name: recreate (started, recreate)
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    recreate: yes
+    state: started
+    stop_timeout: 1
+  register: recreate_4
+
+- name: cleanup
+  docker_container:
+    name: "{{ cname }}"
+    state: absent
+    stop_timeout: 1
+
+- debug: var=recreate_1
+- debug: var=recreate_2
+- debug: var=recreate_3
+- debug: var=recreate_4
+
+- assert:
+    that:
+    - recreate_1 is changed
+    - recreate_2 is changed
+    - recreate_3 is changed
+    - recreate_4 is changed
+    - recreate_1.ansible_facts.docker_container.Id != recreate_2.ansible_facts.docker_container.Id
+    - recreate_2.ansible_facts.docker_container.Id == recreate_3.ansible_facts.docker_container.Id
+    - recreate_3.ansible_facts.docker_container.Id != recreate_4.ansible_facts.docker_container.Id
 
 ####################################################################
 ## restart #########################################################
 ####################################################################
 
-# TODO: - restart
+- name: restart
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    state: started
+    stop_timeout: 1
+  register: restart_1
+
+- name: restart (restart)
+  docker_container:
+    image: alpine:3.8
+    command: '/bin/sh -v -c "sleep 10m"'
+    name: "{{ cname }}"
+    restart: yes
+    state: started
+    stop_timeout: 1
+  register: restart_2
+
+- name: cleanup
+  docker_container:
+    name: "{{ cname }}"
+    state: absent
+    stop_timeout: 1
+
+- debug: var=restart_1
+- debug: var=restart_2
+
+- assert:
+    that:
+    - restart_1 is changed
+    - restart_2 is changed
+    - restart_1.ansible_facts.docker_container.Id == restart_2.ansible_facts.docker_container.Id
 
 ####################################################################
 ## restart_policy ##################################################
@@ -2946,12 +3091,6 @@
     - sysctls_3 is not changed
     - sysctls_4 is changed
 
-####################################################################
-## timeout #########################################################
-####################################################################
-
-# TODO: - timeout
-
 ####################################################################
 ## tmpfs ###########################################################
 ####################################################################