Repository: ansible/ansible

Issue:
docker_container: arguments pass to command are split on comma incorrectly

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
docker_container

##### ANSIBLE VERSION
```
ansible 2.3.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Aug  2 2016, 04:20:16) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]
```

##### CONFIGURATION
N/A

##### OS / ENVIRONMENT
RHEL7.3

##### SUMMARY
When I pass an argument to the "command" option that contains commas (that should be preserved as a single string), the argument is split on the command and passed as separate arguments.

##### STEPS TO REPRODUCE

```yaml
- name: Run etcd
  vars: 
    myip: "{{ inventory_hostname }}"
  docker_container:
    name: etcd
    image: quay.io/coreos/etcd
    state: started
    volumes:
      - /data
    published_ports:
      - 4001
      - 2380
      - 2379
    command: >
        /usr/local/bin/etcd 
        -name etcd{{ node }}
        -advertise-client-urls http://{{ myip }}:2379,http://{{ myip }}:4001
        -listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001
        -initial-advertise-peer-urls http://{{ myip }}:2380
        -listen-peer-urls http://0.0.0.0:2380
        -initial-cluster-token etcd-cluster-1
        -initial-cluster etcd0=http://{{ groups['kube-nodes'][0] }}:2380,etcd1=http://{{ groups['kube-nodes'][1] }}:2380,etcd2=http://{{ groups['kube-nodes'][2] }}:2380
        -initial-cluster-state new
```

##### EXPECTED RESULTS
In the arguments passed to etcd, I would expect the value of the argument -initial-cluster to be the string as defined, with commas.

##### ACTUAL RESULTS
The value of the "-initial-cluster" argument was split into separate arguments on comma and passed separately to the command. This can be easily seen in the debug output:

"Args": ["-name", "etcd3", "-advertise-client-urls", "http://10.1.1.187:2379", "http://10.1.1.187:4001", "-listen-client-urls", "http://0.0.0.0:2379", "http://0.0.0.0:4001", "-initial-advertise-peer-urls", "http://10.1.1.187:2380", "-listen-peer-urls", "http://0.0.0.0:2380", "-initial-cluster-token", "etcd-cluster-1", **"-initial-cluster", "etcd0=http://10.1.1.109:2380", "etcd1=http://10.1.1.110:2380", "etcd2=http://10.1.1.187:2380"**, "-initial-cluster-state", "new"]

Note that the values following "-initial-cluster" are separate and surrounded by quotes, instead of the original string.


Discussion:
This is still the same if I define the string as a separate variable, and interpolate that instead, e.g.

```
        -initial-cluster {{ etcd_cluster }}
```

The debug command shoes that the variable creation is not splitting the string, it is preserved with commas:

```
ok: [10.1.1.109] => {
    "changed": false, 
    "msg": "LIST IS etcd0=http://10.1.1.109:2380,etcd1=http://10.1.1.110:2380,etcd2=http://10.1.1.187:2380"
}
ok: [10.1.1.110] => {
    "changed": false, 
    "msg": "LIST IS etcd0=http://10.1.1.109:2380,etcd1=http://10.1.1.110:2380,etcd2=http://10.1.1.187:2380"
}
ok: [10.1.1.187] => {
    "changed": false, 
    "msg": "LIST IS etcd0=http://10.1.1.109:2380,etcd1=http://10.1.1.110:2380,etcd2=http://10.1.1.187:2380"
}
```
Also note if I pass in the command as an array of strings, the problem does NOT occur:

```
    command: [
        "/usr/local/bin/etcd", 
        "-name etcd{{ node }}",
        "-advertise-client-urls http://{{ myip }}:2379,http://{{ myip }}:4001",
        "-listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001",
        "-initial-advertise-peer-urls http://{{ myip }}:2380",
        "-listen-peer-urls http://0.0.0.0:2380",
        "-initial-cluster-token etcd-cluster-1",
        "-initial-cluster {{ etcd_cluster }}",
        "-initial-cluster-state new"
      ]
```
/cc @chouseknecht 

Resolving patch:
diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py
--- a/lib/ansible/modules/cloud/docker/docker_container.py
+++ b/lib/ansible/modules/cloud/docker/docker_container.py
@@ -59,6 +59,8 @@
   command:
     description:
       - Command to execute when the container starts.
+        A command may be either a string or a list.
+        Prior to version 2.4, strings were split on commas.
     default: null
     required: false
   cpu_period:
@@ -814,7 +816,8 @@ def __init__(self, client):
 
         if self.command:
             # convert from list to str
-            self.command = ' '.join([str(x) for x in self.command])
+            if isinstance(self.command, list):
+                self.command = ' '.join([str(x) for x in self.command])
 
     def fail(self, msg):
         self.client.module.fail_json(msg=msg)
@@ -1970,7 +1973,7 @@ def main():
         blkio_weight=dict(type='int'),
         capabilities=dict(type='list'),
         cleanup=dict(type='bool', default=False),
-        command=dict(type='list'),
+        command=dict(type='raw'),
         cpu_period=dict(type='int'),
         cpu_quota=dict(type='int'),
         cpuset_cpus=dict(type='str'),


Test patch: