Repository: docker/docker-py

Issue:
client.services.create does not support init option
`docker service create` supports an `--init` option since API 1.37.

https://docs.docker.com/engine/reference/commandline/service_create/

This option is not yet available in client.services.create.


Discussion:

Resolving patch:
diff --git a/docker/api/service.py b/docker/api/service.py
--- a/docker/api/service.py
+++ b/docker/api/service.py
@@ -88,6 +88,10 @@ def raise_version_error(param, min_version):
                 if container_spec.get('Isolation') is not None:
                     raise_version_error('ContainerSpec.isolation', '1.35')
 
+            if utils.version_lt(version, '1.38'):
+                if container_spec.get('Init') is not None:
+                    raise_version_error('ContainerSpec.init', '1.38')
+
         if task_template.get('Resources'):
             if utils.version_lt(version, '1.32'):
                 if task_template['Resources'].get('GenericResources'):
diff --git a/docker/models/services.py b/docker/models/services.py
--- a/docker/models/services.py
+++ b/docker/models/services.py
@@ -165,6 +165,8 @@ def create(self, image, command=None, **kwargs):
             env (list of str): Environment variables, in the form
                 ``KEY=val``.
             hostname (string): Hostname to set on the container.
+            init (boolean): Run an init inside the container that forwards
+                signals and reaps processes
             isolation (string): Isolation technology used by the service's
                 containers. Only used for Windows containers.
             labels (dict): Labels to apply to the service.
@@ -280,6 +282,7 @@ def list(self, **kwargs):
     'hostname',
     'hosts',
     'image',
+    'init',
     'isolation',
     'labels',
     'mounts',
diff --git a/docker/types/services.py b/docker/types/services.py
--- a/docker/types/services.py
+++ b/docker/types/services.py
@@ -110,13 +110,15 @@ class ContainerSpec(dict):
         privileges (Privileges): Security options for the service's containers.
         isolation (string): Isolation technology used by the service's
             containers. Only used for Windows containers.
+        init (boolean): Run an init inside the container that forwards signals
+            and reaps processes.
     """
     def __init__(self, image, command=None, args=None, hostname=None, env=None,
                  workdir=None, user=None, labels=None, mounts=None,
                  stop_grace_period=None, secrets=None, tty=None, groups=None,
                  open_stdin=None, read_only=None, stop_signal=None,
                  healthcheck=None, hosts=None, dns_config=None, configs=None,
-                 privileges=None, isolation=None):
+                 privileges=None, isolation=None, init=None):
         self['Image'] = image
 
         if isinstance(command, six.string_types):
@@ -183,6 +185,9 @@ def __init__(self, image, command=None, args=None, hostname=None, env=None,
         if isolation is not None:
             self['Isolation'] = isolation
 
+        if init is not None:
+            self['Init'] = init
+
 
 class Mount(dict):
     """


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
@@ -850,6 +850,20 @@ def test_create_service_with_privileges(self):
         )
         assert privileges['SELinuxContext']['Disable'] is True
 
+    @requires_api_version('1.38')
+    def test_create_service_with_init(self):
+        container_spec = docker.types.ContainerSpec(
+            'busybox', ['sleep', '999'], init=True
+        )
+        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 'Init' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
+        assert (
+            svc_info['Spec']['TaskTemplate']['ContainerSpec']['Init'] is True
+        )
+
     @requires_api_version('1.25')
     def test_update_service_with_defaults_name(self):
         container_spec = docker.types.ContainerSpec(