Repository: docker/docker-py

Issue:
create_service env can be a list or a dict
The docker-py docs say the `env` parameter of `create_service` is a dictionary, but this isn't accepted, it has to be a list:

```
>>> import docker
>>> c = docker.Client()
>>> c.version()
{u'KernelVersion': u'4.4.20-moby', u'Os': u'linux', u'BuildTime': u'2016-08-18T17:52:38.255390991+00:00', u'ApiVersion': u'1.24', u'Version': u'1.12.1', u'GitCommit': u'23cf638', u'Arch': u'amd64', u'GoVersion': u'go1.6.3'}
```

```
>>> contspec = docker.types.ContainerSpec(image='httpd', env={'A': 'B'})
>>> c.create_service(docker.types.TaskTemplate(contspec), name='test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "docker/utils/decorators.py", line 35, in wrapper
    return f(self, *args, **kwargs)
  File "docker/api/service.py", line 33, in create_service
    self._post_json(url, data=data, headers=headers), True
  File "docker/client.py", line 180, in _result
    self._raise_for_status(response)
  File "docker/client.py", line 176, in _raise_for_status
    raise errors.APIError(e, response, explanation=explanation)
docker.errors.APIError: 500 Server Error: Internal Server Error ("json: cannot unmarshal object into Go value of type []string")
```

```
>>> contspec = docker.types.ContainerSpec(image='httpd', env=['A=B'])
>>> c.create_service(docker.types.TaskTemplate(contspec), name='test')
{u'ID': u'5f4u3my4beeiecjzhx90q7aqc'}
```



Discussion:
Please sign your commits following these rules:
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

``` console
$ git clone -b "patch-1" git@github.com:manics/docker-py.git somewhere
$ cd somewhere
$ git commit --amend -s --no-edit
$ git push -f
```

Amending updates the existing PR. You **DO NOT** need to open a new one.

Rather than modify the documentation, I think we should modify the code in `ContainerSpec` to call `docker.utils.format_environment`.

@shin- I've tried to modify the code as suggested (separate branch): https://github.com/manics/docker-py/commit/bf1e41f70f9b6059a07218a528b52413e5fd047f
However this fails because adding `from ..utils.utils import format_environment` to `docker/types/services.py` introduces a circular dependency with `docker/utils/__init__.py`:

```
from ..types import LogConfig, Ulimit
from ..types import SwarmExternalCA, SwarmSpec
```

Do you have any advice on how best to deal with this?

@manics Sorry, I seem to have missed your message. A temporary solution would be to do a delayed import like here: https://github.com/docker/docker-py/blob/master/docker/types/services.py#L41


Resolving patch:
diff --git a/docker/types/services.py b/docker/types/services.py
--- a/docker/types/services.py
+++ b/docker/types/services.py
@@ -1,7 +1,7 @@
 import six
 
 from .. import errors
-from ..utils import split_command
+from ..utils import format_environment, split_command
 
 
 class TaskTemplate(dict):
@@ -82,7 +82,10 @@ def __init__(self, image, command=None, args=None, env=None, workdir=None,
         self['Args'] = args
 
         if env is not None:
-            self['Env'] = env
+            if isinstance(env, dict):
+                self['Env'] = format_environment(env)
+            else:
+                self['Env'] = env
         if workdir is not None:
             self['Dir'] = workdir
         if user is not None:
diff --git a/docker/utils/__init__.py b/docker/utils/__init__.py
--- a/docker/utils/__init__.py
+++ b/docker/utils/__init__.py
@@ -6,6 +6,7 @@
     create_host_config, parse_bytes, ping_registry, parse_env_file, version_lt,
     version_gte, decode_json_header, split_command, create_ipam_config,
     create_ipam_pool, parse_devices, normalize_links, convert_service_networks,
+    format_environment
 )
 
 from .decorators import check_resource, minimum_version, update_headers


Test patch:
diff --git a/tests/integration/api_service_test.py b/tests/integration/api_service_test.py
--- a/tests/integration/api_service_test.py
+++ b/tests/integration/api_service_test.py
@@ -231,3 +231,19 @@ def test_create_service_with_endpoint_spec(self):
             'PublishedPort': 12357, 'TargetPort': 1990, 'Protocol': 'udp'
         } in ports
         assert len(ports) == 3
+
+    def test_create_service_with_env(self):
+        container_spec = docker.types.ContainerSpec(
+            'busybox', ['true'], env={'DOCKER_PY_TEST': 1}
+        )
+        task_tmpl = docker.types.TaskTemplate(
+            container_spec,
+        )
+        name = self.get_service_name()
+        svc_id = self.client.create_service(task_tmpl, name=name)
+        svc_info = self.client.inspect_service(svc_id)
+        assert 'TaskTemplate' in svc_info['Spec']
+        assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
+        con_spec = svc_info['Spec']['TaskTemplate']['ContainerSpec']
+        assert 'Env' in con_spec
+        assert con_spec['Env'] == ['DOCKER_PY_TEST=1']