Repository: ansible/ansible-modules-core

Issue:
Update docker module to support newer versions of the server (mem_limit has been moved to host_config in API version 1.19)
##### Issue Type:

Bug Report
##### Ansible Version:

ansible 1.9.2
##### Ansible Configuration:
##### Environment:

Running from: OS X 10.95
Managing: Ubuntu 15.04
##### Summary:

Starting a container results in the error "mem_limit has been moved to host_config in API version 1.19" starting container
##### Steps To Reproduce:

Using Ansible to configure starting a Jenkins container 

```
- name: Jenkins data directory
  command: "docker create -v {{HOME}}/.jenkins:/var/jenkins_home:rw -v {{HOME}}/.ssh:/.ssh:ro -v {{HOME}}/.ssl:/.ssl:ro --name jenkins_data busybox"
  sudo: yes
  when: docker_containers.stdout.find('jenkins_data') == -1


- name: Start Jenkins container
  docker: 
    name: jenkins_master
    image: mediaplayout/jenkins
    volumes_from: jenkins_data
    pull: always
    state: started
    ports: 
      - 8080:8080
      - 50000:50000
  sudo: yes  
```

I'm getting the error

```
BECOME-SUCCESS-nnwoeoumeitqznkijaqrhohdpyhijpbr
Traceback (most recent call last):
  File "/home/mediaplayout/.ansible/tmp/ansible-tmp-1436530356.59-234590896125756/docker", line 3132, in <module>
    main()
  File "/home/mediaplayout/.ansible/tmp/ansible-tmp-1436530356.59-234590896125756/docker", line 1494, in main
    started(manager, containers, count, name)
  File "/home/mediaplayout/.ansible/tmp/ansible-tmp-1436530356.59-234590896125756/docker", line 1354, in started
    created = manager.create_containers(delta)
  File "/home/mediaplayout/.ansible/tmp/ansible-tmp-1436530356.59-234590896125756/docker", line 1227, in create_containers
    containers = do_create(count, params)
  File "/home/mediaplayout/.ansible/tmp/ansible-tmp-1436530356.59-234590896125756/docker", line 1217, in do_create
    result = self.client.create_container(**params)
  File "/usr/local/lib/python2.7/dist-packages/docker/client.py", line 237, in create_container
    volume_driver
  File "/usr/local/lib/python2.7/dist-packages/docker/utils/utils.py", line 546, in create_container_config
    'mem_limit has been moved to host_config in API version 1.19'
docker.errors.InvalidVersion: mem_limit has been moved to host_config in API version 1.19
```

This task does work:

```
- name: Register running Docker containers
  register: running_docker_containers
  command: docker ps
  sudo: yes

- name: Start Jenkins container
  command: docker run -d -p 8080:8080 -p 50000:50000 --volumes-from jenkins_data --name jenkins_master mediaplayout/jenkins
  sudo: yes
  when: running_docker_containers.stdout.find('jenkins_master') == -1
```



Discussion:

Resolving patch:
diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py
--- a/cloud/docker/docker.py
+++ b/cloud/docker/docker.py
@@ -530,6 +530,7 @@ class DockerManager(object):
             'extra_hosts': ((0, 7, 0), '1.3.1'),
             'pid': ((1, 0, 0), '1.17'),
             'log_driver': ((1, 2, 0), '1.18'),
+            'host_config': ((0, 7, 0), '1.15'),
             # Clientside only
             'insecure_registry': ((0, 5, 0), '0.0')
             }
@@ -739,6 +740,52 @@ def get_exposed_ports(self, expose_list):
         else:
             return None
 
+    def get_start_params(self):
+        """
+        Create start params
+        """
+        params = {
+            'lxc_conf': self.lxc_conf,
+            'binds': self.binds,
+            'port_bindings': self.port_bindings,
+            'publish_all_ports': self.module.params.get('publish_all_ports'),
+            'privileged': self.module.params.get('privileged'),
+            'links': self.links,
+            'network_mode': self.module.params.get('net'),
+        }
+
+        optionals = {}
+        for optional_param in ('dns', 'volumes_from', 'restart_policy',
+                'restart_policy_retry', 'pid'):
+            optionals[optional_param] = self.module.params.get(optional_param)
+
+        if optionals['dns'] is not None:
+            self.ensure_capability('dns')
+            params['dns'] = optionals['dns']
+
+        if optionals['volumes_from'] is not None:
+            self.ensure_capability('volumes_from')
+            params['volumes_from'] = optionals['volumes_from']
+
+        if optionals['restart_policy'] is not None:
+            self.ensure_capability('restart_policy')
+            params['restart_policy'] = { 'Name': optionals['restart_policy'] }
+            if params['restart_policy']['Name'] == 'on-failure':
+                params['restart_policy']['MaximumRetryCount'] = optionals['restart_policy_retry']
+
+        if optionals['pid'] is not None:
+            self.ensure_capability('pid')
+            params['pid_mode'] = optionals['pid']
+
+        return params
+
+    def get_host_config(self):
+        """
+        Create HostConfig object
+        """
+        params = self.get_start_params()
+        return docker.utils.create_host_config(**params)
+
     def get_port_bindings(self, ports):
         """
         Parse the `ports` string into a port bindings dict for the `start_container` call.
@@ -1292,16 +1339,10 @@ def create_host_config(self):
         return docker.utils.create_host_config(**params)
 
     def create_containers(self, count=1):
-        try:
-            mem_limit = _human_to_bytes(self.module.params.get('memory_limit'))
-        except ValueError as e:
-            self.module.fail_json(msg=str(e))
-
         params = {'image':        self.module.params.get('image'),
                   'command':      self.module.params.get('command'),
                   'ports':        self.exposed_ports,
                   'volumes':      self.volumes,
-                  'mem_limit':    mem_limit,
                   'environment':  self.env,
                   'hostname':     self.module.params.get('hostname'),
                   'domainname':   self.module.params.get('domainname'),
@@ -1309,9 +1350,11 @@ def create_containers(self, count=1):
                   'name':         self.module.params.get('name'),
                   'stdin_open':   self.module.params.get('stdin_open'),
                   'tty':          self.module.params.get('tty'),
-                  'host_config':  self.create_host_config(),
                   }
 
+        if self.ensure_capability('host_config', fail=False):
+            params['host_config'] = self.get_host_config()
+
         def do_create(count, params):
             results = []
             for _ in range(count):
@@ -1333,6 +1376,11 @@ def do_create(count, params):
         return containers
 
     def start_containers(self, containers):
+        params = {}
+
+        if not self.ensure_capability('host_config', fail=False):
+            params = self.get_start_params()
+
         for i in containers:
             self.client.start(i)
             self.increment_counter('started')


Test patch: