Skip to content

Commit

Permalink
Merge pull request #1519 from shin-/2.2.0-release
Browse files Browse the repository at this point in the history
2.2.0 release
  • Loading branch information
shin- authored Mar 21, 2017
2 parents 5742774 + cca9818 commit b474ea2
Show file tree
Hide file tree
Showing 27 changed files with 396 additions and 82 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def buildImages = { ->
}

def getAPIVersion = { engineVersion ->
def versionMap = ['1.12': '1.24', '1.13': '1.25']
def versionMap = ['1.12': '1.24', '1.13': '1.26']
return versionMap[engineVersion.substring(0, 4)]
}

Expand Down
16 changes: 8 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ integration-test-py3: build-py3
.PHONY: integration-dind
integration-dind: build build-py3
docker rm -vf dpy-dind || :
docker run -d --name dpy-dind --privileged dockerswarm/dind:1.13.0 docker daemon\
-H tcp://0.0.0.0:2375
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=1.25"\
docker run -d --name dpy-dind --privileged dockerswarm/dind:1.13.1 docker daemon\
-H tcp://0.0.0.0:2375 --experimental
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=1.26"\
--link=dpy-dind:docker docker-sdk-python py.test tests/integration
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=1.25"\
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=1.26"\
--link=dpy-dind:docker docker-sdk-python3 py.test tests/integration
docker rm -vf dpy-dind

Expand All @@ -57,14 +57,14 @@ integration-dind-ssl: build-dind-certs build build-py3
docker run -d --name dpy-dind-certs dpy-dind-certs
docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1"\
--env="DOCKER_CERT_PATH=/certs" --volumes-from dpy-dind-certs --name dpy-dind-ssl\
-v /tmp --privileged dockerswarm/dind:1.13.0 docker daemon --tlsverify\
-v /tmp --privileged dockerswarm/dind:1.13.1 docker daemon --tlsverify\
--tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\
--tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375
--tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375 --experimental
docker run --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=1.25"\
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=1.26"\
--link=dpy-dind-ssl:docker docker-sdk-python py.test tests/integration
docker run --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=1.25"\
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=1.26"\
--link=dpy-dind-ssl:docker docker-sdk-python3 py.test tests/integration
docker rm -vf dpy-dind-ssl dpy-dind-certs

Expand Down
3 changes: 3 additions & 0 deletions docker/api/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,9 @@ def create_host_config(self, *args, **kwargs):
container, as a mapping of hostname to IP address.
group_add (:py:class:`list`): List of additional group names and/or
IDs that the container process will run as.
init (bool): Run an init inside the container that forwards
signals and reaps processes
init_path (str): Path to the docker-init binary
ipc_mode (str): Set the IPC mode for the container.
isolation (str): Isolation technology to use. Default: `None`.
links (dict or list of tuples): Either a dictionary mapping name
Expand Down
18 changes: 17 additions & 1 deletion docker/api/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@


class DaemonApiMixin(object):
@utils.minimum_version('1.25')
def df(self):
"""
Get data usage information.
Returns:
(dict): A dictionary representing different resource categories
and their respective data usage.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/system/df')
return self._result(self._get(url), True)

def events(self, since=None, until=None, filters=None, decode=None):
"""
Get real-time events from the server. Similar to the ``docker events``
Expand Down Expand Up @@ -54,7 +70,7 @@ def events(self, since=None, until=None, filters=None, decode=None):
}

return self._stream_helper(
self.get(self._url('/events'), params=params, stream=True),
self._get(self._url('/events'), params=params, stream=True),
decode=decode
)

Expand Down
37 changes: 37 additions & 0 deletions docker/api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def push_plugin(self, name):
return self._stream_helper(res, decode=True)

@utils.minimum_version('1.25')
@utils.check_resource
def remove_plugin(self, name, force=False):
"""
Remove an installed plugin.
Expand All @@ -212,3 +213,39 @@ def remove_plugin(self, name, force=False):
res = self._delete(url, params={'force': force})
self._raise_for_status(res)
return True

@utils.minimum_version('1.26')
@utils.check_resource
def upgrade_plugin(self, name, remote, privileges):
"""
Upgrade an installed plugin.
Args:
name (string): Name of the plugin to upgrade. The ``:latest``
tag is optional and is the default if omitted.
remote (string): Remote reference to upgrade to. The
``:latest`` tag is optional and is the default if omitted.
privileges (list): A list of privileges the user consents to
grant to the plugin. Can be retrieved using
:py:meth:`~plugin_privileges`.
Returns:
An iterable object streaming the decoded API logs
"""

url = self._url('/plugins/{0}/upgrade', name)
params = {
'remote': remote,
}

headers = {}
registry, repo_name = auth.resolve_repository_name(remote)
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
response = self._post_json(
url, params=params, headers=headers, data=privileges,
stream=True
)
self._raise_for_status(response)
return self._stream_helper(response, decode=True)
50 changes: 50 additions & 0 deletions docker/api/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,56 @@ def services(self, filters=None):
url = self._url('/services')
return self._result(self._get(url, params=params), True)

@utils.minimum_version('1.25')
@utils.check_resource
def service_logs(self, service, details=False, follow=False, stdout=False,
stderr=False, since=0, timestamps=False, tail='all',
is_tty=None):
"""
Get log stream for a service.
Note: This endpoint works only for services with the ``json-file``
or ``journald`` logging drivers.
Args:
service (str): ID or name of the service
details (bool): Show extra details provided to logs.
Default: ``False``
follow (bool): Keep connection open to read logs as they are
sent by the Engine. Default: ``False``
stdout (bool): Return logs from ``stdout``. Default: ``False``
stderr (bool): Return logs from ``stderr``. Default: ``False``
since (int): UNIX timestamp for the logs staring point.
Default: 0
timestamps (bool): Add timestamps to every log line.
tail (string or int): Number of log lines to be returned,
counting from the current end of the logs. Specify an
integer or ``'all'`` to output all log lines.
Default: ``all``
is_tty (bool): Whether the service's :py:class:`ContainerSpec`
enables the TTY option. If omitted, the method will query
the Engine for the information, causing an additional
roundtrip.
Returns (generator): Logs for the service.
"""
params = {
'details': details,
'follow': follow,
'stdout': stdout,
'stderr': stderr,
'since': since,
'timestamps': timestamps,
'tail': tail
}

url = self._url('/services/{0}/logs', service)
res = self._get(url, params=params, stream=True)
if is_tty is None:
is_tty = self.inspect_service(
service
)['Spec']['TaskTemplate']['ContainerSpec'].get('TTY', False)
return self._get_result_tty(True, res, is_tty)

@utils.minimum_version('1.24')
def tasks(self, filters=None):
"""
Expand Down
4 changes: 4 additions & 0 deletions docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ def events(self, *args, **kwargs):
return self.api.events(*args, **kwargs)
events.__doc__ = APIClient.events.__doc__

def df(self):
return self.api.df()
df.__doc__ = APIClient.df.__doc__

def info(self, *args, **kwargs):
return self.api.info(*args, **kwargs)
info.__doc__ = APIClient.info.__doc__
Expand Down
2 changes: 1 addition & 1 deletion docker/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys
from .version import version

DEFAULT_DOCKER_API_VERSION = '1.24'
DEFAULT_DOCKER_API_VERSION = '1.26'
MINIMUM_DOCKER_API_VERSION = '1.21'
DEFAULT_TIMEOUT_SECONDS = 60
STREAM_HEADER_SIZE_BYTES = 8
Expand Down
7 changes: 6 additions & 1 deletion docker/models/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,9 @@ def run(self, image, command=None, stdout=True, stderr=False,
group_add (:py:class:`list`): List of additional group names and/or
IDs that the container process will run as.
hostname (str): Optional hostname for the container.
init (bool): Run an init inside the container that forwards
signals and reaps processes
init_path (str): Path to the docker-init binary
ipc_mode (str): Set the IPC mode for the container.
isolation (str): Isolation technology to use. Default: `None`.
labels (dict or list): A dictionary of name-value labels (e.g.
Expand Down Expand Up @@ -726,7 +729,7 @@ def list(self, all=False, before=None, filters=None, limit=-1, since=None):
Args:
all (bool): Show all containers. Only running containers are shown
by default trunc (bool): Truncate output
by default
since (str): Show only containers created since Id or Name, include
non-running ones
before (str): Show only container created before Id or Name,
Expand Down Expand Up @@ -814,6 +817,8 @@ def prune(self, filters=None):
'dns',
'extra_hosts',
'group_add',
'init',
'init_path',
'ipc_mode',
'isolation',
'kernel_memory',
Expand Down
25 changes: 25 additions & 0 deletions docker/models/plugins.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .. import errors
from .resource import Collection, Model


Expand Down Expand Up @@ -96,6 +97,30 @@ def remove(self, force=False):
"""
return self.client.api.remove_plugin(self.name, force=force)

def upgrade(self, remote=None):
"""
Upgrade the plugin.
Args:
remote (string): Remote reference to upgrade to. The
``:latest`` tag is optional and is the default if omitted.
Default: this plugin's name.
Returns:
A generator streaming the decoded API logs
"""
if self.enabled:
raise errors.DockerError(
'Plugin must be disabled before upgrading.'
)

if remote is None:
remote = self.name
privileges = self.client.api.plugin_privileges(remote)
for d in self.client.api.upgrade_plugin(self.name, remote, privileges):
yield d
self._reload()


class PluginCollection(Collection):
model = Plugin
Expand Down
34 changes: 32 additions & 2 deletions docker/models/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ def update(self, **kwargs):
**create_kwargs
)

def logs(self, **kwargs):
"""
Get log stream for the service.
Note: This method works only for services with the ``json-file``
or ``journald`` logging drivers.
Args:
details (bool): Show extra details provided to logs.
Default: ``False``
follow (bool): Keep connection open to read logs as they are
sent by the Engine. Default: ``False``
stdout (bool): Return logs from ``stdout``. Default: ``False``
stderr (bool): Return logs from ``stderr``. Default: ``False``
since (int): UNIX timestamp for the logs staring point.
Default: 0
timestamps (bool): Add timestamps to every log line.
tail (string or int): Number of log lines to be returned,
counting from the current end of the logs. Specify an
integer or ``'all'`` to output all log lines.
Default: ``all``
Returns (generator): Logs for the service.
"""
is_tty = self.attrs['Spec']['TaskTemplate']['ContainerSpec'].get(
'TTY', False
)
return self.client.api.service_logs(self.id, is_tty=is_tty, **kwargs)


class ServiceCollection(Collection):
"""Services on the Docker server."""
Expand All @@ -96,11 +124,12 @@ def create(self, image, command=None, **kwargs):
access and load balance a service. Default: ``None``.
env (list of str): Environment variables, in the form
``KEY=val``.
hostname (string): Hostname to set on the container.
labels (dict): Labels to apply to the service.
log_driver (str): Log driver to use for containers.
log_driver_options (dict): Log driver options.
mode (str): Scheduling mode for the service (``replicated`` or
``global``). Defaults to ``replicated``.
mode (ServiceMode): Scheduling mode for the service.
Default:``None``
mounts (list of str): Mounts for the containers, in the form
``source:target:options``, where options is either
``ro`` or ``rw``.
Expand Down Expand Up @@ -176,6 +205,7 @@ def list(self, **kwargs):
'command',
'args',
'env',
'hostname',
'workdir',
'user',
'labels',
Expand Down
13 changes: 12 additions & 1 deletion docker/types/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ def __init__(self, version, binds=None, port_bindings=None,
oom_kill_disable=False, shm_size=None, sysctls=None,
tmpfs=None, oom_score_adj=None, dns_opt=None, cpu_shares=None,
cpuset_cpus=None, userns_mode=None, pids_limit=None,
isolation=None, auto_remove=False, storage_opt=None):
isolation=None, auto_remove=False, storage_opt=None,
init=None, init_path=None):

if mem_limit is not None:
self['Memory'] = parse_bytes(mem_limit)
Expand Down Expand Up @@ -417,6 +418,16 @@ def __init__(self, version, binds=None, port_bindings=None,
raise host_config_version_error('storage_opt', '1.24')
self['StorageOpt'] = storage_opt

if init is not None:
if version_lt(version, '1.25'):
raise host_config_version_error('init', '1.25')
self['Init'] = init

if init_path is not None:
if version_lt(version, '1.25'):
raise host_config_version_error('init_path', '1.25')
self['InitPath'] = init_path


def host_config_type_error(param, param_value, expected):
error_msg = 'Invalid type for {0} param: expected {1} but found {2}'
Expand Down
9 changes: 6 additions & 3 deletions docker/types/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class ContainerSpec(dict):
image (string): The image name to use for the container.
command (string or list): The command to be run in the image.
args (:py:class:`list`): Arguments to the command.
hostname (string): The hostname to set on the container.
env (dict): Environment variables.
dir (string): The working directory for commands to run in.
user (string): The user inside the container.
Expand All @@ -82,16 +83,18 @@ class ContainerSpec(dict):
secrets (list of py:class:`SecretReference`): List of secrets to be
made available inside the containers.
"""
def __init__(self, image, command=None, args=None, env=None, workdir=None,
user=None, labels=None, mounts=None, stop_grace_period=None,
secrets=None):
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):
self['Image'] = image

if isinstance(command, six.string_types):
command = split_command(command)
self['Command'] = command
self['Args'] = args

if hostname is not None:
self['Hostname'] = hostname
if env is not None:
if isinstance(env, dict):
self['Env'] = format_environment(env)
Expand Down
Loading

0 comments on commit b474ea2

Please sign in to comment.