Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docker/api/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ def _check_api_features(version, task_template, update_config):
'Placement.preferences is not supported in'
' API version < 1.27'
)
if task_template.container_spec.get('TTY'):
if utils.version_lt(version, '1.25'):
raise errors.InvalidVersion(
'ContainerSpec.TTY is not supported in API version < 1.25'
)


class ServiceApiMixin(object):
Expand Down
2 changes: 2 additions & 0 deletions docker/models/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ def create(self, image, command=None, **kwargs):
of the service. Default: ``None``
user (str): User to run commands as.
workdir (str): Working directory for commands to run.
tty (boolean): Whether a pseudo-TTY should be allocated.

Returns:
(:py:class:`Service`) The created service.
Expand Down Expand Up @@ -212,6 +213,7 @@ def list(self, **kwargs):
'mounts',
'stop_grace_period',
'secrets',
'tty'
]

# kwargs to copy straight over to TaskTemplate
Expand Down
6 changes: 5 additions & 1 deletion docker/types/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,11 @@ class ContainerSpec(dict):
terminate before forcefully killing it.
secrets (list of py:class:`SecretReference`): List of secrets to be
made available inside the containers.
tty (boolean): Whether a pseudo-TTY should be allocated.
"""
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):
stop_grace_period=None, secrets=None, tty=None):
self['Image'] = image

if isinstance(command, six.string_types):
Expand Down Expand Up @@ -125,6 +126,9 @@ def __init__(self, image, command=None, args=None, hostname=None, env=None,
raise TypeError('secrets must be a list')
self['Secrets'] = secrets

if tty is not None:
self['TTY'] = tty


class Mount(dict):
"""
Expand Down
17 changes: 17 additions & 0 deletions tests/integration/api_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,23 @@ def test_create_service_with_env(self):
assert 'Env' in con_spec
assert con_spec['Env'] == ['DOCKER_PY_TEST=1']

@requires_api_version('1.25')
def test_create_service_with_tty(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['true'], tty=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 'TaskTemplate' in svc_info['Spec']
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
con_spec = svc_info['Spec']['TaskTemplate']['ContainerSpec']
assert 'TTY' in con_spec
assert con_spec['TTY'] is True

def test_create_service_global_mode(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['echo', 'hello']
Expand Down