Skip to content

Commit

Permalink
Refuse API version < 1.21 ; Remove associated code paths
Browse files Browse the repository at this point in the history
Signed-off-by: Joffrey F <[email protected]>
  • Loading branch information
shin- committed Jan 31, 2018
1 parent b180b87 commit df8422d
Show file tree
Hide file tree
Showing 20 changed files with 140 additions and 519 deletions.
50 changes: 8 additions & 42 deletions docker/api/build.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import json
import logging
import os
import re

from .. import auth
from .. import constants
Expand All @@ -14,7 +13,7 @@

class BuildApiMixin(object):
def build(self, path=None, tag=None, quiet=False, fileobj=None,
nocache=False, rm=False, stream=False, timeout=None,
nocache=False, rm=False, timeout=None,
custom_context=False, encoding=None, pull=False,
forcerm=False, dockerfile=None, container_limits=None,
decode=False, buildargs=None, gzip=False, shmsize=None,
Expand Down Expand Up @@ -67,9 +66,6 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
rm (bool): Remove intermediate containers. The ``docker build``
command now defaults to ``--rm=true``, but we have kept the old
default of `False` to preserve backward compatibility
stream (bool): *Deprecated for API version > 1.8 (always True)*.
Return a blocking generator you can iterate over to retrieve
build output as it happens
timeout (int): HTTP timeout
custom_context (bool): Optional if using ``fileobj``
encoding (str): The encoding for a stream. Set to ``gzip`` for
Expand Down Expand Up @@ -154,17 +150,6 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
)
encoding = 'gzip' if gzip else encoding

if utils.compare_version('1.8', self._version) >= 0:
stream = True

if dockerfile and utils.compare_version('1.17', self._version) < 0:
raise errors.InvalidVersion(
'dockerfile was only introduced in API version 1.17'
)

if utils.compare_version('1.19', self._version) < 0:
pull = 1 if pull else 0

u = self._url('/build')
params = {
't': tag,
Expand All @@ -179,12 +164,7 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
params.update(container_limits)

if buildargs:
if utils.version_gte(self._version, '1.21'):
params.update({'buildargs': json.dumps(buildargs)})
else:
raise errors.InvalidVersion(
'buildargs was only introduced in API version 1.21'
)
params.update({'buildargs': json.dumps(buildargs)})

if shmsize:
if utils.version_gte(self._version, '1.22'):
Expand Down Expand Up @@ -256,30 +236,21 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
if encoding:
headers['Content-Encoding'] = encoding

if utils.compare_version('1.9', self._version) >= 0:
self._set_auth_headers(headers)
self._set_auth_headers(headers)

response = self._post(
u,
data=context,
params=params,
headers=headers,
stream=stream,
stream=True,
timeout=timeout,
)

if context is not None and not custom_context:
context.close()

if stream:
return self._stream_helper(response, decode=decode)
else:
output = self._result(response)
srch = r'Successfully built ([0-9a-f]+)'
match = re.search(srch, output)
if not match:
return None, output
return match.group(1), output
return self._stream_helper(response, decode=decode)

def _set_auth_headers(self, headers):
log.debug('Looking for auth config')
Expand Down Expand Up @@ -316,13 +287,8 @@ def _set_auth_headers(self, headers):
)
)

if utils.compare_version('1.19', self._version) >= 0:
headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
else:
headers['X-Registry-Config'] = auth.encode_header({
'configs': auth_data
})
headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
else:
log.debug('No auth config found')
27 changes: 5 additions & 22 deletions docker/api/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
import struct
import warnings
from functools import partial

import requests
Expand All @@ -27,7 +26,7 @@
MINIMUM_DOCKER_API_VERSION
)
from ..errors import (
DockerException, TLSParameterError,
DockerException, InvalidVersion, TLSParameterError,
create_api_error_from_http_exception
)
from ..tls import TLSConfig
Expand Down Expand Up @@ -160,11 +159,9 @@ def __init__(self, base_url=None, version=None,
)
)
if utils.version_lt(self._version, MINIMUM_DOCKER_API_VERSION):
warnings.warn(
'The minimum API version supported is {}, but you are using '
'version {}. It is recommended you either upgrade Docker '
'Engine or use an older version of Docker SDK for '
'Python.'.format(MINIMUM_DOCKER_API_VERSION, self._version)
raise InvalidVersion(
'API versions below {} are no longer supported by this '
'library.'.format(MINIMUM_DOCKER_API_VERSION)
)

def _retrieve_server_version(self):
Expand Down Expand Up @@ -353,17 +350,8 @@ def _multiplexed_response_stream_helper(self, response):
break
yield data

def _stream_raw_result_old(self, response):
''' Stream raw output for API versions below 1.6 '''
self._raise_for_status(response)
for line in response.iter_lines(chunk_size=1,
decode_unicode=True):
# filter out keep-alive new lines
if line:
yield line

def _stream_raw_result(self, response):
''' Stream result for TTY-enabled container above API 1.6 '''
''' Stream result for TTY-enabled container '''
self._raise_for_status(response)
for out in response.iter_content(chunk_size=1, decode_unicode=True):
yield out
Expand Down Expand Up @@ -419,11 +407,6 @@ def _get_result(self, container, stream, res):
return self._get_result_tty(stream, res, self._check_is_tty(container))

def _get_result_tty(self, stream, res, is_tty):
# Stream multi-plexing was only introduced in API v1.6. Anything
# before that needs old-style streaming.
if utils.compare_version('1.6', self._version) < 0:
return self._stream_raw_result_old(res)

# We should also use raw streaming (without keep-alives)
# if we're dealing with a tty-enabled container.
if is_tty:
Expand Down
137 changes: 51 additions & 86 deletions docker/api/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,13 @@ def containers(self, quiet=False, all=False, trunc=False, latest=False,
return res

def create_container(self, image, command=None, hostname=None, user=None,
detach=False, stdin_open=False, tty=False,
mem_limit=None, ports=None, environment=None,
dns=None, volumes=None, volumes_from=None,
detach=False, stdin_open=False, tty=False, ports=None,
environment=None, volumes=None,
network_disabled=False, name=None, entrypoint=None,
cpu_shares=None, working_dir=None, domainname=None,
memswap_limit=None, cpuset=None, host_config=None,
mac_address=None, labels=None, volume_driver=None,
stop_signal=None, networking_config=None,
healthcheck=None, stop_timeout=None, runtime=None):
working_dir=None, domainname=None, host_config=None,
mac_address=None, labels=None, stop_signal=None,
networking_config=None, healthcheck=None,
stop_timeout=None, runtime=None):
"""
Creates a container. Parameters are similar to those for the ``docker
run`` command except it doesn't support the attach options (``-a``).
Expand Down Expand Up @@ -354,35 +352,24 @@ def create_container(self, image, command=None, hostname=None, user=None,
return container ID
stdin_open (bool): Keep STDIN open even if not attached
tty (bool): Allocate a pseudo-TTY
mem_limit (float or str): Memory limit. Accepts float values (which
represent the memory limit of the created container in bytes)
or a string with a units identification char (``100000b``,
``1000k``, ``128m``, ``1g``). If a string is specified without
a units character, bytes are assumed as an intended unit.
ports (list of ints): A list of port numbers
environment (dict or list): A dictionary or a list of strings in
the following format ``["PASSWORD=xxx"]`` or
``{"PASSWORD": "xxx"}``.
dns (:py:class:`list`): DNS name servers. Deprecated since API
version 1.10. Use ``host_config`` instead.
volumes (str or list): List of paths inside the container to use
as volumes.
volumes_from (:py:class:`list`): List of container names or Ids to
get volumes from.
network_disabled (bool): Disable networking
name (str): A name for the container
entrypoint (str or list): An entrypoint
working_dir (str): Path to the working directory
domainname (str): The domain name to use for the container
memswap_limit (int):
host_config (dict): A dictionary created with
:py:meth:`create_host_config`.
mac_address (str): The Mac Address to assign the container
labels (dict or list): A dictionary of name-value labels (e.g.
``{"label1": "value1", "label2": "value2"}``) or a list of
names of labels to set with empty values (e.g.
``["label1", "label2"]``)
volume_driver (str): The name of a volume driver/plugin.
stop_signal (str): The stop signal to use to stop the container
(e.g. ``SIGINT``).
stop_timeout (int): Timeout to stop the container, in seconds.
Expand All @@ -405,17 +392,12 @@ def create_container(self, image, command=None, hostname=None, user=None,
if isinstance(volumes, six.string_types):
volumes = [volumes, ]

if host_config and utils.compare_version('1.15', self._version) < 0:
raise errors.InvalidVersion(
'host_config is not supported in API < 1.15'
)

config = self.create_container_config(
image, command, hostname, user, detach, stdin_open, tty, mem_limit,
ports, dns, environment, volumes, volumes_from,
network_disabled, entrypoint, cpu_shares, working_dir, domainname,
memswap_limit, cpuset, host_config, mac_address, labels,
volume_driver, stop_signal, networking_config, healthcheck,
image, command, hostname, user, detach, stdin_open, tty,
ports, environment, volumes,
network_disabled, entrypoint, working_dir, domainname,
host_config, mac_address, labels,
stop_signal, networking_config, healthcheck,
stop_timeout, runtime
)
return self.create_container_from_config(config, name)
Expand Down Expand Up @@ -681,7 +663,6 @@ def export(self, container):
return self._stream_raw_result(res)

@utils.check_resource('container')
@utils.minimum_version('1.20')
def get_archive(self, container, path):
"""
Retrieve a file or folder from a container in the form of a tar
Expand Down Expand Up @@ -786,59 +767,46 @@ def logs(self, container, stdout=True, stderr=True, stream=False,
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if utils.compare_version('1.11', self._version) >= 0:
if follow is None:
follow = stream
params = {'stderr': stderr and 1 or 0,
'stdout': stdout and 1 or 0,
'timestamps': timestamps and 1 or 0,
'follow': follow and 1 or 0,
}
if utils.compare_version('1.13', self._version) >= 0:
if tail != 'all' and (not isinstance(tail, int) or tail < 0):
tail = 'all'
params['tail'] = tail

if since is not None:
if utils.version_lt(self._version, '1.19'):
raise errors.InvalidVersion(
'since is not supported for API version < 1.19'
)
if isinstance(since, datetime):
params['since'] = utils.datetime_to_timestamp(since)
elif (isinstance(since, int) and since > 0):
params['since'] = since
else:
raise errors.InvalidArgument(
'since value should be datetime or positive int, '
'not {}'.format(type(since))
)

if until is not None:
if utils.version_lt(self._version, '1.35'):
raise errors.InvalidVersion(
'until is not supported for API version < 1.35'
)
if isinstance(until, datetime):
params['until'] = utils.datetime_to_timestamp(until)
elif (isinstance(until, int) and until > 0):
params['until'] = until
else:
raise errors.InvalidArgument(
'until value should be datetime or positive int, '
'not {}'.format(type(until))
)

url = self._url("/containers/{0}/logs", container)
res = self._get(url, params=params, stream=stream)
return self._get_result(container, stream, res)
return self.attach(
container,
stdout=stdout,
stderr=stderr,
stream=stream,
logs=True
)
if follow is None:
follow = stream
params = {'stderr': stderr and 1 or 0,
'stdout': stdout and 1 or 0,
'timestamps': timestamps and 1 or 0,
'follow': follow and 1 or 0,
}
if tail != 'all' and (not isinstance(tail, int) or tail < 0):
tail = 'all'
params['tail'] = tail

if since is not None:
if isinstance(since, datetime):
params['since'] = utils.datetime_to_timestamp(since)
elif (isinstance(since, int) and since > 0):
params['since'] = since
else:
raise errors.InvalidArgument(
'since value should be datetime or positive int, '
'not {}'.format(type(since))
)

if until is not None:
if utils.version_lt(self._version, '1.35'):
raise errors.InvalidVersion(
'until is not supported for API version < 1.35'
)
if isinstance(until, datetime):
params['until'] = utils.datetime_to_timestamp(until)
elif (isinstance(until, int) and until > 0):
params['until'] = until
else:
raise errors.InvalidArgument(
'until value should be datetime or positive int, '
'not {}'.format(type(until))
)

url = self._url("/containers/{0}/logs", container)
res = self._get(url, params=params, stream=stream)
return self._get_result(container, stream, res)

@utils.check_resource('container')
def pause(self, container):
Expand Down Expand Up @@ -906,7 +874,6 @@ def port(self, container, private_port):
return h_ports

@utils.check_resource('container')
@utils.minimum_version('1.20')
def put_archive(self, container, path, data):
"""
Insert a file or folder in an existing container using a tar archive as
Expand Down Expand Up @@ -976,7 +943,6 @@ def remove_container(self, container, v=False, link=False, force=False):
)
self._raise_for_status(res)

@utils.minimum_version('1.17')
@utils.check_resource('container')
def rename(self, container, name):
"""
Expand Down Expand Up @@ -1073,7 +1039,6 @@ def start(self, container, *args, **kwargs):
res = self._post(url)
self._raise_for_status(res)

@utils.minimum_version('1.17')
@utils.check_resource('container')
def stats(self, container, decode=None, stream=True):
"""
Expand Down
Loading

0 comments on commit df8422d

Please sign in to comment.