diff options
-rw-r--r-- | docker/api/build.py | 50 | ||||
-rw-r--r-- | docker/api/client.py | 27 | ||||
-rw-r--r-- | docker/api/container.py | 137 | ||||
-rw-r--r-- | docker/api/exec_api.py | 12 | ||||
-rw-r--r-- | docker/api/image.py | 50 | ||||
-rw-r--r-- | docker/api/network.py | 6 | ||||
-rw-r--r-- | docker/api/volume.py | 4 | ||||
-rw-r--r-- | docker/types/containers.py | 108 | ||||
-rw-r--r-- | tests/integration/api_build_test.py | 16 | ||||
-rw-r--r-- | tests/integration/api_container_test.py | 46 | ||||
-rw-r--r-- | tests/integration/api_network_test.py | 9 | ||||
-rw-r--r-- | tests/integration/api_volume_test.py | 1 | ||||
-rw-r--r-- | tests/unit/api_build_test.py | 11 | ||||
-rw-r--r-- | tests/unit/api_container_test.py | 60 | ||||
-rw-r--r-- | tests/unit/api_image_test.py | 20 | ||||
-rw-r--r-- | tests/unit/api_network_test.py | 7 | ||||
-rw-r--r-- | tests/unit/api_test.py | 1 | ||||
-rw-r--r-- | tests/unit/api_volume_test.py | 7 | ||||
-rw-r--r-- | tests/unit/dockertypes_test.py | 48 | ||||
-rw-r--r-- | tests/unit/fake_api.py | 39 |
20 files changed, 140 insertions, 519 deletions
diff --git a/docker/api/build.py b/docker/api/build.py index 220c93f..56f1fcf 100644 --- a/docker/api/build.py +++ b/docker/api/build.py @@ -1,7 +1,6 @@ import json import logging import os -import re from .. import auth from .. import constants @@ -14,7 +13,7 @@ log = logging.getLogger(__name__) 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, @@ -67,9 +66,6 @@ class BuildApiMixin(object): 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 @@ -154,17 +150,6 @@ class BuildApiMixin(object): ) 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, @@ -179,12 +164,7 @@ class BuildApiMixin(object): 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'): @@ -256,30 +236,21 @@ class BuildApiMixin(object): 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') @@ -316,13 +287,8 @@ class BuildApiMixin(object): ) ) - 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') diff --git a/docker/api/client.py b/docker/api/client.py index 07bcfae..e69d143 100644 --- a/docker/api/client.py +++ b/docker/api/client.py @@ -1,6 +1,5 @@ import json import struct -import warnings from functools import partial import requests @@ -27,7 +26,7 @@ from ..constants import ( MINIMUM_DOCKER_API_VERSION ) from ..errors import ( - DockerException, TLSParameterError, + DockerException, InvalidVersion, TLSParameterError, create_api_error_from_http_exception ) from ..tls import TLSConfig @@ -160,11 +159,9 @@ class APIClient( ) ) 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): @@ -353,17 +350,8 @@ class APIClient( 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 @@ -419,11 +407,6 @@ class APIClient( 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: diff --git a/docker/api/container.py b/docker/api/container.py index 419ae44..152a08b 100644 --- a/docker/api/container.py +++ b/docker/api/container.py @@ -204,15 +204,13 @@ class ContainerApiMixin(object): 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``). @@ -354,27 +352,17 @@ class ContainerApiMixin(object): 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 @@ -382,7 +370,6 @@ class ContainerApiMixin(object): ``{"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. @@ -405,17 +392,12 @@ class ContainerApiMixin(object): 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) @@ -681,7 +663,6 @@ class ContainerApiMixin(object): 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 @@ -786,59 +767,46 @@ class ContainerApiMixin(object): :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): @@ -906,7 +874,6 @@ class ContainerApiMixin(object): 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 @@ -976,7 +943,6 @@ class ContainerApiMixin(object): ) self._raise_for_status(res) - @utils.minimum_version('1.17') @utils.check_resource('container') def rename(self, container, name): """ @@ -1073,7 +1039,6 @@ class ContainerApiMixin(object): 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): """ diff --git a/docker/api/exec_api.py b/docker/api/exec_api.py index d607461..986d87f 100644 --- a/docker/api/exec_api.py +++ b/docker/api/exec_api.py @@ -5,7 +5,6 @@ from .. import utils class ExecApiMixin(object): - @utils.minimum_version('1.15') @utils.check_resource('container') def exec_create(self, container, cmd, stdout=True, stderr=True, stdin=False, tty=False, privileged=False, user='', @@ -41,14 +40,6 @@ class ExecApiMixin(object): If the server returns an error. """ - if privileged and utils.version_lt(self._version, '1.19'): - raise errors.InvalidVersion( - 'Privileged exec is not supported in API < 1.19' - ) - if user and utils.version_lt(self._version, '1.19'): - raise errors.InvalidVersion( - 'User-specific exec is not supported in API < 1.19' - ) if environment is not None and utils.version_lt(self._version, '1.25'): raise errors.InvalidVersion( 'Setting environment for exec is not supported in API < 1.25' @@ -88,7 +79,6 @@ class ExecApiMixin(object): res = self._post_json(url, data=data) return self._result(res, True) - @utils.minimum_version('1.16') def exec_inspect(self, exec_id): """ Return low-level information about an exec command. @@ -108,7 +98,6 @@ class ExecApiMixin(object): res = self._get(self._url("/exec/{0}/json", exec_id)) return self._result(res, True) - @utils.minimum_version('1.15') def exec_resize(self, exec_id, height=None, width=None): """ Resize the tty session used by the specified exec command. @@ -127,7 +116,6 @@ class ExecApiMixin(object): res = self._post(url, params=params) self._raise_for_status(res) - @utils.minimum_version('1.15') @utils.check_resource('exec_id') def exec_start(self, exec_id, detach=False, tty=False, stream=False, socket=False): diff --git a/docker/api/image.py b/docker/api/image.py index f37d2dd..fa832a3 100644 --- a/docker/api/image.py +++ b/docker/api/image.py @@ -54,8 +54,7 @@ class ImageApiMixin(object): res = self._get(self._url("/images/{0}/history", image)) return self._result(res, True) - def images(self, name=None, quiet=False, all=False, viz=False, - filters=None): + def images(self, name=None, quiet=False, all=False, filters=None): """ List images. Similar to the ``docker images`` command. @@ -76,10 +75,6 @@ class ImageApiMixin(object): :py:class:`docker.errors.APIError` If the server returns an error. """ - if viz: - if utils.compare_version('1.7', self._version) >= 0: - raise Exception('Viz output is not supported in API >= 1.7!') - return self._result(self._get(self._url("images/viz"))) params = { 'filter': name, 'only_ids': 1 if quiet else 0, @@ -226,19 +221,6 @@ class ImageApiMixin(object): ) @utils.check_resource('image') - def insert(self, image, url, path): - if utils.compare_version('1.12', self._version) >= 0: - raise errors.DeprecatedMethod( - 'insert is not available for API version >=1.12' - ) - api_url = self._url("/images/{0}/insert", image) - params = { - 'url': url, - 'path': path - } - return self._result(self._post(api_url, params=params)) - - @utils.check_resource('image') def inspect_image(self, image): """ Get detailed information about an image. Similar to the ``docker @@ -369,14 +351,13 @@ class ImageApiMixin(object): } headers = {} - if utils.version_gte(self._version, '1.5'): - if auth_config is None: - header = auth.get_config_header(self, registry) - if header: - headers['X-Registry-Auth'] = header - else: - log.debug('Sending supplied auth config') - headers['X-Registry-Auth'] = auth.encode_header(auth_config) + if auth_config is None: + header = auth.get_config_header(self, registry) + if header: + headers['X-Registry-Auth'] = header + else: + log.debug('Sending supplied auth config') + headers['X-Registry-Auth'] = auth.encode_header(auth_config) if platform is not None: if utils.version_lt(self._version, '1.32'): @@ -440,14 +421,13 @@ class ImageApiMixin(object): } headers = {} - if utils.compare_version('1.5', self._version) >= 0: - if auth_config is None: - header = auth.get_config_header(self, registry) - if header: - headers['X-Registry-Auth'] = header - else: - log.debug('Sending supplied auth config') - headers['X-Registry-Auth'] = auth.encode_header(auth_config) + if auth_config is None: + header = auth.get_config_header(self, registry) + if header: + headers['X-Registry-Auth'] = header + else: + log.debug('Sending supplied auth config') + headers['X-Registry-Auth'] = auth.encode_header(auth_config) response = self._post_json( u, None, headers=headers, stream=stream, params=params diff --git a/docker/api/network.py b/docker/api/network.py index 7977808..57ed8d3 100644 --- a/docker/api/network.py +++ b/docker/api/network.py @@ -5,7 +5,6 @@ from .. import utils class NetworkApiMixin(object): - @minimum_version('1.21') def networks(self, names=None, ids=None, filters=None): """ List networks. Similar to the ``docker networks ls`` command. @@ -38,7 +37,6 @@ class NetworkApiMixin(object): res = self._get(url, params=params) return self._result(res, json=True) - @minimum_version('1.21') def create_network(self, name, driver=None, options=None, ipam=None, check_duplicate=None, internal=False, labels=None, enable_ipv6=False, attachable=None, scope=None, @@ -175,7 +173,6 @@ class NetworkApiMixin(object): url = self._url('/networks/prune') return self._result(self._post(url, params=params), True) - @minimum_version('1.21') @check_resource('net_id') def remove_network(self, net_id): """ @@ -188,7 +185,6 @@ class NetworkApiMixin(object): res = self._delete(url) self._raise_for_status(res) - @minimum_version('1.21') @check_resource('net_id') def inspect_network(self, net_id, verbose=None, scope=None): """ @@ -216,7 +212,6 @@ class NetworkApiMixin(object): return self._result(res, json=True) @check_resource('container') - @minimum_version('1.21') def connect_container_to_network(self, container, net_id, ipv4_address=None, ipv6_address=None, aliases=None, links=None, @@ -253,7 +248,6 @@ class NetworkApiMixin(object): self._raise_for_status(res) @check_resource('container') - @minimum_version('1.21') def disconnect_container_from_network(self, container, net_id, force=False): """ diff --git a/docker/api/volume.py b/docker/api/volume.py index ce911c8..900a608 100644 --- a/docker/api/volume.py +++ b/docker/api/volume.py @@ -3,7 +3,6 @@ from .. import utils class VolumeApiMixin(object): - @utils.minimum_version('1.21') def volumes(self, filters=None): """ List volumes currently registered by the docker daemon. Similar to the @@ -37,7 +36,6 @@ class VolumeApiMixin(object): url = self._url('/volumes') return self._result(self._get(url, params=params), True) - @utils.minimum_version('1.21') def create_volume(self, name=None, driver=None, driver_opts=None, labels=None): """ @@ -90,7 +88,6 @@ class VolumeApiMixin(object): return self._result(self._post_json(url, data=data), True) - @utils.minimum_version('1.21') def inspect_volume(self, name): """ Retrieve volume info by name. @@ -138,7 +135,6 @@ class VolumeApiMixin(object): url = self._url('/volumes/prune') return self._result(self._post(url, params=params), True) - @utils.minimum_version('1.21') def remove_volume(self, name, force=False): """ Remove a volume. Similar to the ``docker volume rm`` command. diff --git a/docker/types/containers.py b/docker/types/containers.py index 3f15905..b4a329c 100644 --- a/docker/types/containers.py +++ b/docker/types/containers.py @@ -129,20 +129,12 @@ class HostConfig(dict): self['MemorySwap'] = parse_bytes(memswap_limit) if mem_reservation: - if version_lt(version, '1.21'): - raise host_config_version_error('mem_reservation', '1.21') - self['MemoryReservation'] = parse_bytes(mem_reservation) if kernel_memory: - if version_lt(version, '1.21'): - raise host_config_version_error('kernel_memory', '1.21') - self['KernelMemory'] = parse_bytes(kernel_memory) if mem_swappiness is not None: - if version_lt(version, '1.20'): - raise host_config_version_error('mem_swappiness', '1.20') if not isinstance(mem_swappiness, int): raise host_config_type_error( 'mem_swappiness', mem_swappiness, 'int' @@ -168,9 +160,6 @@ class HostConfig(dict): self['Privileged'] = privileged if oom_kill_disable: - if version_lt(version, '1.20'): - raise host_config_version_error('oom_kill_disable', '1.19') - self['OomKillDisable'] = oom_kill_disable if oom_score_adj: @@ -193,7 +182,7 @@ class HostConfig(dict): if network_mode: self['NetworkMode'] = network_mode - elif network_mode is None and version_gte(version, '1.20'): + elif network_mode is None: self['NetworkMode'] = 'default' if restart_policy: @@ -214,18 +203,12 @@ class HostConfig(dict): self['Devices'] = parse_devices(devices) if group_add: - if version_lt(version, '1.20'): - raise host_config_version_error('group_add', '1.20') - self['GroupAdd'] = [six.text_type(grp) for grp in group_add] if dns is not None: self['Dns'] = dns if dns_opt is not None: - if version_lt(version, '1.21'): - raise host_config_version_error('dns_opt', '1.21') - self['DnsOptions'] = dns_opt if security_opt is not None: @@ -298,38 +281,23 @@ class HostConfig(dict): if cpu_quota: if not isinstance(cpu_quota, int): raise host_config_type_error('cpu_quota', cpu_quota, 'int') - if version_lt(version, '1.19'): - raise host_config_version_error('cpu_quota', '1.19') - self['CpuQuota'] = cpu_quota if cpu_period: if not isinstance(cpu_period, int): raise host_config_type_error('cpu_period', cpu_period, 'int') - if version_lt(version, '1.19'): - raise host_config_version_error('cpu_period', '1.19') - self['CpuPeriod'] = cpu_period if cpu_shares: - if version_lt(version, '1.18'): - raise host_config_version_error('cpu_shares', '1.18') - if not isinstance(cpu_shares, int): raise host_config_type_error('cpu_shares', cpu_shares, 'int') self['CpuShares'] = cpu_shares if cpuset_cpus: - if version_lt(version, '1.18'): - raise host_config_version_error('cpuset_cpus', '1.18') - self['CpusetCpus'] = cpuset_cpus if cpuset_mems: - if version_lt(version, '1.19'): - raise host_config_version_error('cpuset_mems', '1.19') - if not isinstance(cpuset_mems, str): raise host_config_type_error( 'cpuset_mems', cpuset_mems, 'str' @@ -462,8 +430,6 @@ class HostConfig(dict): self['InitPath'] = init_path if volume_driver is not None: - if version_lt(version, '1.21'): - raise host_config_version_error('volume_driver', '1.21') self['VolumeDriver'] = volume_driver if cpu_count: @@ -520,53 +486,12 @@ def host_config_value_error(param, param_value): class ContainerConfig(dict): def __init__( self, version, image, command, hostname=None, user=None, detach=False, - stdin_open=False, tty=False, mem_limit=None, ports=None, dns=None, - environment=None, volumes=None, volumes_from=None, - network_disabled=False, 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 + stdin_open=False, tty=False, ports=None, environment=None, + volumes=None, network_disabled=False, entrypoint=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 ): - if version_gte(version, '1.10'): - message = ('{0!r} parameter has no effect on create_container().' - ' It has been moved to host_config') - if dns is not None: - raise errors.InvalidVersion(message.format('dns')) - if volumes_from is not None: - raise errors.InvalidVersion(message.format('volumes_from')) - - if version_lt(version, '1.18'): - if labels is not None: - raise errors.InvalidVersion( - 'labels were only introduced in API version 1.18' - ) - - if version_lt(version, '1.19'): - if volume_driver is not None: - raise errors.InvalidVersion( - 'Volume drivers were only introduced in API version 1.19' - ) - mem_limit = mem_limit if mem_limit is not None else 0 - memswap_limit = memswap_limit if memswap_limit is not None else 0 - else: - if mem_limit is not None: - raise errors.InvalidVersion( - 'mem_limit has been moved to host_config in API version' - ' 1.19' - ) - - if memswap_limit is not None: - raise errors.InvalidVersion( - 'memswap_limit has been moved to host_config in API ' - 'version 1.19' - ) - - if version_lt(version, '1.21'): - if stop_signal is not None: - raise errors.InvalidVersion( - 'stop_signal was only introduced in API version 1.21' - ) if stop_timeout is not None and version_lt(version, '1.25'): raise errors.InvalidVersion( @@ -597,12 +522,6 @@ class ContainerConfig(dict): if isinstance(labels, list): labels = dict((lbl, six.text_type('')) for lbl in labels) - if mem_limit is not None: - mem_limit = parse_bytes(mem_limit) - - if memswap_limit is not None: - memswap_limit = parse_bytes(memswap_limit) - if isinstance(ports, list): exposed_ports = {} for port_definition in ports: @@ -624,13 +543,6 @@ class ContainerConfig(dict): volumes_dict[vol] = {} volumes = volumes_dict - if volumes_from: - if not isinstance(volumes_from, six.string_types): - volumes_from = ','.join(volumes_from) - else: - # Force None, an empty list or dict causes client.start to fail - volumes_from = None - if healthcheck and isinstance(healthcheck, dict): healthcheck = Healthcheck(**healthcheck) @@ -655,28 +567,20 @@ class ContainerConfig(dict): 'Tty': tty, 'OpenStdin': stdin_open, 'StdinOnce': stdin_once, - 'Memory': mem_limit, 'AttachStdin': attach_stdin, 'AttachStdout': attach_stdout, 'AttachStderr': attach_stderr, 'Env': environment, 'Cmd': command, - 'Dns': dns, 'Image': image, 'Volumes': volumes, - 'VolumesFrom': volumes_from, 'NetworkDisabled': network_disabled, 'Entrypoint': entrypoint, - 'CpuShares': cpu_shares, - 'Cpuset': cpuset, - 'CpusetCpus': cpuset, 'WorkingDir': working_dir, - 'MemorySwap': memswap_limit, 'HostConfig': host_config, 'NetworkingConfig': networking_config, 'MacAddress': mac_address, 'Labels': labels, - 'VolumeDriver': volume_driver, 'StopSignal': stop_signal, 'Healthcheck': healthcheck, 'StopTimeout': stop_timeout, diff --git a/tests/integration/api_build_test.py b/tests/integration/api_build_test.py index ee9b68a..4c2b992 100644 --- a/tests/integration/api_build_test.py +++ b/tests/integration/api_build_test.py @@ -21,7 +21,7 @@ class BuildTest(BaseAPIIntegrationTest): 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz' ' /tmp/silence.tar.gz' ]).encode('ascii')) - stream = self.client.build(fileobj=script, stream=True, decode=True) + stream = self.client.build(fileobj=script, decode=True) logs = [] for chunk in stream: logs.append(chunk) @@ -37,7 +37,7 @@ class BuildTest(BaseAPIIntegrationTest): 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz' ' /tmp/silence.tar.gz' ])) - stream = self.client.build(fileobj=script, stream=True) + stream = self.client.build(fileobj=script) logs = '' for chunk in stream: if six.PY3: @@ -45,7 +45,6 @@ class BuildTest(BaseAPIIntegrationTest): logs += chunk assert logs != '' - @requires_api_version('1.8') def test_build_with_dockerignore(self): base_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, base_dir) @@ -97,7 +96,6 @@ class BuildTest(BaseAPIIntegrationTest): '/test/not-ignored' ]) - @requires_api_version('1.21') def test_build_with_buildargs(self): script = io.BytesIO('\n'.join([ 'FROM scratch', @@ -320,7 +318,7 @@ class BuildTest(BaseAPIIntegrationTest): ])) stream = self.client.build( - fileobj=script, stream=True, decode=True, nocache=True + fileobj=script, decode=True, nocache=True ) lines = [] for chunk in stream: @@ -341,7 +339,7 @@ class BuildTest(BaseAPIIntegrationTest): ])) stream = self.client.build( - path=base_dir, stream=True, decode=True, nocache=True, + path=base_dir, decode=True, nocache=True, gzip=True ) @@ -365,7 +363,7 @@ class BuildTest(BaseAPIIntegrationTest): ])) stream = self.client.build( - path=base_dir, stream=True, decode=True, nocache=True + path=base_dir, decode=True, nocache=True ) lines = [] @@ -383,9 +381,7 @@ class BuildTest(BaseAPIIntegrationTest): script = io.BytesIO('FROM busybox\n'.encode('ascii')) with pytest.raises(errors.APIError) as excinfo: - stream = self.client.build( - fileobj=script, stream=True, platform='foobar' - ) + stream = self.client.build(fileobj=script, platform='foobar') for _ in stream: pass diff --git a/tests/integration/api_container_test.py b/tests/integration/api_container_test.py index e5d7943..0925352 100644 --- a/tests/integration/api_container_test.py +++ b/tests/integration/api_container_test.py @@ -145,22 +145,18 @@ class CreateContainerTest(BaseAPIIntegrationTest): container2_id = res1['Id'] self.tmp_containers.append(container2_id) self.client.start(container2_id) - with pytest.raises(docker.errors.DockerException): - self.client.create_container( - BUSYBOX, 'cat', detach=True, stdin_open=True, - volumes_from=vol_names - ) - res2 = self.client.create_container( + + res = self.client.create_container( BUSYBOX, 'cat', detach=True, stdin_open=True, host_config=self.client.create_host_config( volumes_from=vol_names, network_mode='none' ) ) - container3_id = res2['Id'] + container3_id = res['Id'] self.tmp_containers.append(container3_id) self.client.start(container3_id) - info = self.client.inspect_container(res2['Id']) + info = self.client.inspect_container(res['Id']) assert len(info['HostConfig']['VolumesFrom']) == len(vol_names) def create_container_readonly_fs(self): @@ -222,7 +218,6 @@ class CreateContainerTest(BaseAPIIntegrationTest): self.client.kill(id) - @requires_api_version('1.20') def test_group_id_ints(self): container = self.client.create_container( BUSYBOX, 'id -G', @@ -239,7 +234,6 @@ class CreateContainerTest(BaseAPIIntegrationTest): assert '1000' in groups assert '1001' in groups - @requires_api_version('1.20') def test_group_id_strings(self): container = self.client.create_container( BUSYBOX, 'id -G', host_config=self.client.create_host_config( @@ -604,24 +598,15 @@ class VolumeBindTest(BaseAPIIntegrationTest): assert mount_data['RW'] is True def check_container_data(self, inspect_data, rw): - if docker.utils.compare_version('1.20', self.client._version) < 0: - assert 'Volumes' in inspect_data - assert self.mount_dest in inspect_data['Volumes'] - assert ( - self.mount_origin == inspect_data['Volumes'][self.mount_dest] - ) - assert self.mount_dest in inspect_data['VolumesRW'] - assert not inspect_data['VolumesRW'][self.mount_dest] - else: - assert 'Mounts' in inspect_data - filtered = list(filter( - lambda x: x['Destination'] == self.mount_dest, - inspect_data['Mounts'] - )) - assert len(filtered) == 1 - mount_data = filtered[0] - assert mount_data['Source'] == self.mount_origin - assert mount_data['RW'] == rw + assert 'Mounts' in inspect_data + filtered = list(filter( + lambda x: x['Destination'] == self.mount_dest, + inspect_data['Mounts'] + )) + assert len(filtered) == 1 + mount_data = filtered[0] + assert mount_data['Source'] == self.mount_origin + assert mount_data['RW'] == rw def run_with_volume(self, ro, *args, **kwargs): return self.run_container( @@ -640,7 +625,6 @@ class VolumeBindTest(BaseAPIIntegrationTest): ) -@requires_api_version('1.20') class ArchiveTest(BaseAPIIntegrationTest): def test_get_file_archive_from_container(self): data = 'The Maid and the Pocket Watch of Blood' @@ -1323,7 +1307,6 @@ class PruneTest(BaseAPIIntegrationTest): class GetContainerStatsTest(BaseAPIIntegrationTest): - @requires_api_version('1.19') def test_get_container_stats_no_stream(self): container = self.client.create_container( BUSYBOX, ['sleep', '60'], @@ -1338,7 +1321,6 @@ class GetContainerStatsTest(BaseAPIIntegrationTest): 'memory_stats', 'blkio_stats']: assert key in response - @requires_api_version('1.17') def test_get_container_stats_stream(self): container = self.client.create_container( BUSYBOX, ['sleep', '60'], @@ -1401,7 +1383,6 @@ class ContainerUpdateTest(BaseAPIIntegrationTest): class ContainerCPUTest(BaseAPIIntegrationTest): - @requires_api_version('1.18') def test_container_cpu_shares(self): cpu_shares = 512 container = self.client.create_container( @@ -1414,7 +1395,6 @@ class ContainerCPUTest(BaseAPIIntegrationTest): inspect_data = self.client.inspect_container(container) assert inspect_data['HostConfig']['CpuShares'] == 512 - @requires_api_version('1.18') def test_container_cpuset(self): cpuset_cpus = "0,1" container = self.client.create_container( diff --git a/tests/integration/api_network_test.py b/tests/integration/api_network_test.py index ec92bd7..b6726d0 100644 --- a/tests/integration/api_network_test.py +++ b/tests/integration/api_network_test.py @@ -17,7 +17,6 @@ class TestNetworks(BaseAPIIntegrationTest): self.tmp_networks.append(net_id) return (net_name, net_id) - @requires_api_version('1.21') def test_list_networks(self): networks = self.client.networks() @@ -32,7 +31,6 @@ class TestNetworks(BaseAPIIntegrationTest): networks_by_partial_id = self.client.networks(ids=[net_id[:8]]) assert [n['Id'] for n in networks_by_partial_id] == [net_id] - @requires_api_version('1.21') def test_inspect_network(self): net_name, net_id = self.create_network() @@ -43,7 +41,6 @@ class TestNetworks(BaseAPIIntegrationTest): assert net['Scope'] == 'local' assert net['IPAM']['Driver'] == 'default' - @requires_api_version('1.21') def test_create_network_with_ipam_config(self): _, net_id = self.create_network( ipam=IPAMConfig( @@ -81,12 +78,10 @@ class TestNetworks(BaseAPIIntegrationTest): }, }] - @requires_api_version('1.21') def test_create_network_with_host_driver_fails(self): with pytest.raises(docker.errors.APIError): self.client.create_network(random_name(), driver='host') - @requires_api_version('1.21') def test_remove_network(self): net_name, net_id = self.create_network() assert net_name in [n['Name'] for n in self.client.networks()] @@ -94,7 +89,6 @@ class TestNetworks(BaseAPIIntegrationTest): self.client.remove_network(net_id) assert net_name not in [n['Name'] for n in self.client.networks()] - @requires_api_version('1.21') def test_connect_and_disconnect_container(self): net_name, net_id = self.create_network() @@ -163,7 +157,6 @@ class TestNetworks(BaseAPIIntegrationTest): assert 'foo' in aliases assert 'bar' in aliases - @requires_api_version('1.21') def test_connect_on_container_create(self): net_name, net_id = self.create_network() @@ -309,7 +302,6 @@ class TestNetworks(BaseAPIIntegrationTest): self.execute(container, ['nslookup', 'bar']) - @requires_api_version('1.21') def test_create_check_duplicate(self): net_name, net_id = self.create_network() with pytest.raises(docker.errors.APIError): @@ -475,7 +467,6 @@ class TestNetworks(BaseAPIIntegrationTest): with pytest.raises(docker.errors.NotFound): self.client.inspect_network(net_name_swarm, scope='local') - @requires_api_version('1.21') def test_create_remove_network_with_space_in_name(self): net_id = self.client.create_network('test 01') self.tmp_networks.append(net_id) diff --git a/tests/integration/api_volume_test.py b/tests/integration/api_volume_test.py index e09f12a..8e7dd3a 100644 --- a/tests/integration/api_volume_test.py +++ b/tests/integration/api_volume_test.py @@ -5,7 +5,6 @@ from ..helpers import requires_api_version from .base import BaseAPIIntegrationTest -@requires_api_version('1.21') class TestVolumes(BaseAPIIntegrationTest): def test_create_volume(self): name = 'perfectcherryblossom' diff --git a/tests/unit/api_build_test.py b/tests/unit/api_build_test.py index b20daea..a7f34fd 100644 --- a/tests/unit/api_build_test.py +++ b/tests/unit/api_build_test.py @@ -31,17 +31,6 @@ class BuildTest(BaseAPIClientTest): self.client.build(fileobj=script, pull=True) - def test_build_container_stream(self): - script = io.BytesIO('\n'.join([ - 'FROM busybox', - 'RUN mkdir -p /tmp/test', - 'EXPOSE 8080', - 'ADD https://dl.dropboxusercontent.com/u/20637798/silence.tar.gz' - ' /tmp/silence.tar.gz' - ]).encode('ascii')) - - self.client.build(fileobj=script, stream=True) - def test_build_container_custom_context(self): script = io.BytesIO('\n'.join([ 'FROM busybox', diff --git a/tests/unit/api_container_test.py b/tests/unit/api_container_test.py index 3cb718a..c33f129 100644 --- a/tests/unit/api_container_test.py +++ b/tests/unit/api_container_test.py @@ -219,24 +219,6 @@ class CreateContainerTest(BaseAPIClientTest): ''') assert args[1]['headers'] == {'Content-Type': 'application/json'} - def test_create_container_with_cpu_shares(self): - with pytest.deprecated_call(): - self.client.create_container('busybox', 'ls', cpu_shares=5) - - args = fake_request.call_args - assert args[0][1] == url_prefix + 'containers/create' - assert json.loads(args[1]['data']) == json.loads(''' - {"Tty": false, "Image": "busybox", - "Cmd": ["ls"], "AttachStdin": false, - "AttachStderr": true, - "AttachStdout": true, "OpenStdin": false, - "StdinOnce": false, - "NetworkDisabled": false, - "CpuShares": 5} - ''') - assert args[1]['headers'] == {'Content-Type': 'application/json'} - - @requires_api_version('1.18') def test_create_container_with_host_config_cpu_shares(self): self.client.create_container( 'busybox', 'ls', host_config=self.client.create_host_config( @@ -261,25 +243,6 @@ class CreateContainerTest(BaseAPIClientTest): ''') assert args[1]['headers'] == {'Content-Type': 'application/json'} - def test_create_container_with_cpuset(self): - with pytest.deprecated_call(): - self.client.create_container('busybox', 'ls', cpuset='0,1') - - args = fake_request.call_args - assert args[0][1] == url_prefix + 'containers/create' - assert json.loads(args[1]['data']) == json.loads(''' - {"Tty": false, "Image": "busybox", - "Cmd": ["ls"], "AttachStdin": false, - "AttachStderr": true, - "AttachStdout": true, "OpenStdin": false, - "StdinOnce": false, - "NetworkDisabled": false, - "Cpuset": "0,1", - "CpusetCpus": "0,1"} - ''') - assert args[1]['headers'] == {'Content-Type': 'application/json'} - - @requires_api_version('1.18') def test_create_container_with_host_config_cpuset(self): self.client.create_container( 'busybox', 'ls', host_config=self.client.create_host_config( @@ -304,7 +267,6 @@ class CreateContainerTest(BaseAPIClientTest): ''') assert args[1]['headers'] == {'Content-Type': 'application/json'} - @requires_api_version('1.19') def test_create_container_with_host_config_cpuset_mems(self): self.client.create_container( 'busybox', 'ls', host_config=self.client.create_host_config( @@ -374,28 +336,6 @@ class CreateContainerTest(BaseAPIClientTest): ''') assert args[1]['headers'] == {'Content-Type': 'application/json'} - def test_create_container_with_volumes_from(self): - vol_names = ['foo', 'bar'] - try: - self.client.create_container('busybox', 'true', - volumes_from=vol_names) - except docker.errors.DockerException: - assert docker.utils.compare_version( - '1.10', self.client._version - ) >= 0 - return - - args = fake_request.call_args - assert args[0][1] == url_prefix + 'containers/create' - assert json.loads(args[1]['data'])['VolumesFrom'] == ','.join( - vol_names - ) - assert args[1]['headers'] == {'Content-Type': 'application/json'} - - def test_create_container_empty_volumes_from(self): - with pytest.raises(docker.errors.InvalidVersion): - self.client.create_container('busybox', 'true', volumes_from=[]) - def test_create_named_container(self): self.client.create_container('busybox', 'true', name='marisa-kirisame') diff --git a/tests/unit/api_image_test.py b/tests/unit/api_image_test.py index 785f887..1e2315d 100644 --- a/tests/unit/api_image_test.py +++ b/tests/unit/api_image_test.py @@ -197,26 +197,6 @@ class ImageTest(BaseAPIClientTest): assert excinfo.value.args[0] == 'Resource ID was not provided' - def test_insert_image(self): - try: - self.client.insert(fake_api.FAKE_IMAGE_NAME, - fake_api.FAKE_URL, fake_api.FAKE_PATH) - except docker.errors.DeprecatedMethod: - assert docker.utils.compare_version( - '1.12', self.client._version - ) >= 0 - return - - fake_request.assert_called_with( - 'POST', - url_prefix + 'images/test_image/insert', - params={ - 'url': fake_api.FAKE_URL, - 'path': fake_api.FAKE_PATH - }, - timeout=DEFAULT_TIMEOUT_SECONDS - ) - def test_push_image(self): with mock.patch('docker.auth.resolve_authconfig', fake_resolve_authconfig): diff --git a/tests/unit/api_network_test.py b/tests/unit/api_network_test.py index fbbc97b..c78554d 100644 --- a/tests/unit/api_network_test.py +++ b/tests/unit/api_network_test.py @@ -3,7 +3,6 @@ import json import six from .api_test import BaseAPIClientTest, url_prefix, response -from ..helpers import requires_api_version from docker.types import IPAMConfig, IPAMPool try: @@ -13,7 +12,6 @@ except ImportError: class NetworkTest(BaseAPIClientTest): - @requires_api_version('1.21') def test_list_networks(self): networks = [ { @@ -49,7 +47,6 @@ class NetworkTest(BaseAPIClientTest): filters = json.loads(get.call_args[1]['params']['filters']) assert filters == {'id': ['123']} - @requires_api_version('1.21') def test_create_network(self): network_data = { "id": 'abc12345', @@ -98,7 +95,6 @@ class NetworkTest(BaseAPIClientTest): } } - @requires_api_version('1.21') def test_remove_network(self): network_id = 'abc12345' delete = mock.Mock(return_value=response(status_code=200)) @@ -109,7 +105,6 @@ class NetworkTest(BaseAPIClientTest): args = delete.call_args assert args[0][0] == url_prefix + 'networks/{0}'.format(network_id) - @requires_api_version('1.21') def test_inspect_network(self): network_id = 'abc12345' network_name = 'foo' @@ -130,7 +125,6 @@ class NetworkTest(BaseAPIClientTest): args = get.call_args assert args[0][0] == url_prefix + 'networks/{0}'.format(network_id) - @requires_api_version('1.21') def test_connect_container_to_network(self): network_id = 'abc12345' container_id = 'def45678' @@ -157,7 +151,6 @@ class NetworkTest(BaseAPIClientTest): }, } - @requires_api_version('1.21') def test_disconnect_container_from_network(self): network_id = 'abc12345' container_id = 'def45678' diff --git a/tests/unit/api_test.py b/tests/unit/api_test.py index b9e0d52..c53a4be 100644 --- a/tests/unit/api_test.py +++ b/tests/unit/api_test.py @@ -437,7 +437,6 @@ class StreamTest(unittest.TestCase): try: stream = client.build( path=self.build_context, - stream=True ) break except requests.ConnectionError as e: diff --git a/tests/unit/api_volume_test.py b/tests/unit/api_volume_test.py index f5e5001..7850c22 100644 --- a/tests/unit/api_volume_test.py +++ b/tests/unit/api_volume_test.py @@ -7,7 +7,6 @@ from .api_test import BaseAPIClientTest, url_prefix, fake_request class VolumeTest(BaseAPIClientTest): - @requires_api_version('1.21') def test_list_volumes(self): volumes = self.client.volumes() assert 'Volumes' in volumes @@ -17,7 +16,6 @@ class VolumeTest(BaseAPIClientTest): assert args[0][0] == 'GET' assert args[0][1] == url_prefix + 'volumes' - @requires_api_version('1.21') def test_list_volumes_and_filters(self): volumes = self.client.volumes(filters={'dangling': True}) assert 'Volumes' in volumes @@ -29,7 +27,6 @@ class VolumeTest(BaseAPIClientTest): assert args[1] == {'params': {'filters': '{"dangling": ["true"]}'}, 'timeout': 60} - @requires_api_version('1.21') def test_create_volume(self): name = 'perfectcherryblossom' result = self.client.create_volume(name) @@ -59,7 +56,6 @@ class VolumeTest(BaseAPIClientTest): with pytest.raises(TypeError): self.client.create_volume(name, labels=1) - @requires_api_version('1.21') def test_create_volume_with_driver(self): name = 'perfectcherryblossom' driver_name = 'sshfs' @@ -72,7 +68,6 @@ class VolumeTest(BaseAPIClientTest): assert 'Driver' in data assert data['Driver'] == driver_name - @requires_api_version('1.21') def test_create_volume_invalid_opts_type(self): with pytest.raises(TypeError): self.client.create_volume( @@ -99,7 +94,6 @@ class VolumeTest(BaseAPIClientTest): assert 'Scope' in result assert result['Scope'] == 'local' - @requires_api_version('1.21') def test_inspect_volume(self): name = 'perfectcherryblossom' result = self.client.inspect_volume(name) @@ -112,7 +106,6 @@ class VolumeTest(BaseAPIClientTest): assert args[0][0] == 'GET' assert args[0][1] == '{0}volumes/{1}'.format(url_prefix, name) - @requires_api_version('1.21') def test_remove_volume(self): name = 'perfectcherryblossom' self.client.remove_volume(name) diff --git a/tests/unit/dockertypes_test.py b/tests/unit/dockertypes_test.py index 71dae7e..2be0578 100644 --- a/tests/unit/dockertypes_test.py +++ b/tests/unit/dockertypes_test.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- import unittest -import warnings import pytest from docker.constants import DEFAULT_DOCKER_API_VERSION from docker.errors import InvalidArgument, InvalidVersion from docker.types import ( - ContainerConfig, ContainerSpec, EndpointConfig, HostConfig, IPAMConfig, + ContainerSpec, EndpointConfig, HostConfig, IPAMConfig, IPAMPool, LogConfig, Mount, ServiceMode, Ulimit, ) from docker.types.services import convert_service_ports @@ -24,33 +23,29 @@ def create_host_config(*args, **kwargs): class HostConfigTest(unittest.TestCase): - def test_create_host_config_no_options(self): - config = create_host_config(version='1.19') - assert not ('NetworkMode' in config) - def test_create_host_config_no_options_newer_api_version(self): - config = create_host_config(version='1.20') + config = create_host_config(version='1.21') assert config['NetworkMode'] == 'default' def test_create_host_config_invalid_cpu_cfs_types(self): with pytest.raises(TypeError): - create_host_config(version='1.20', cpu_quota='0') + create_host_config(version='1.21', cpu_quota='0') with pytest.raises(TypeError): - create_host_config(version='1.20', cpu_period='0') + create_host_config(version='1.21', cpu_period='0') with pytest.raises(TypeError): - create_host_config(version='1.20', cpu_quota=23.11) + create_host_config(version='1.21', cpu_quota=23.11) with pytest.raises(TypeError): - create_host_config(version='1.20', cpu_period=1999.0) + create_host_config(version='1.21', cpu_period=1999.0) def test_create_host_config_with_cpu_quota(self): - config = create_host_config(version='1.20', cpu_quota=1999) + config = create_host_config(version='1.21', cpu_quota=1999) assert config.get('CpuQuota') == 1999 def test_create_host_config_with_cpu_period(self): - config = create_host_config(version='1.20', cpu_period=1999) + config = create_host_config(version='1.21', cpu_period=1999) assert config.get('CpuPeriod') == 1999 def test_create_host_config_with_blkio_constraints(self): @@ -79,10 +74,8 @@ class HostConfigTest(unittest.TestCase): assert config.get('ShmSize') == 67108864 def test_create_host_config_with_oom_kill_disable(self): - config = create_host_config(version='1.20', oom_kill_disable=True) + config = create_host_config(version='1.21', oom_kill_disable=True) assert config.get('OomKillDisable') is True - with pytest.raises(InvalidVersion): - create_host_config(version='1.18.3', oom_kill_disable=True) def test_create_host_config_with_userns_mode(self): config = create_host_config(version='1.23', userns_mode='host') @@ -109,20 +102,13 @@ class HostConfigTest(unittest.TestCase): assert 'use-vc' in dns_opts assert 'no-tld-query' in dns_opts - with pytest.raises(InvalidVersion): - create_host_config(version='1.20', dns_opt=tested_opts) - def test_create_host_config_with_mem_reservation(self): config = create_host_config(version='1.21', mem_reservation=67108864) assert config.get('MemoryReservation') == 67108864 - with pytest.raises(InvalidVersion): - create_host_config(version='1.20', mem_reservation=67108864) def test_create_host_config_with_kernel_memory(self): config = create_host_config(version='1.21', kernel_memory=67108864) assert config.get('KernelMemory') == 67108864 - with pytest.raises(InvalidVersion): - create_host_config(version='1.20', kernel_memory=67108864) def test_create_host_config_with_pids_limit(self): config = create_host_config(version='1.23', pids_limit=1024) @@ -158,9 +144,6 @@ class HostConfigTest(unittest.TestCase): create_host_config(version='1.24', mem_swappiness='40') def test_create_host_config_with_volume_driver(self): - with pytest.raises(InvalidVersion): - create_host_config(version='1.20', volume_driver='local') - config = create_host_config(version='1.21', volume_driver='local') assert config.get('VolumeDriver') == 'local' @@ -215,19 +198,6 @@ class HostConfigTest(unittest.TestCase): create_host_config(version='1.24', cpu_rt_runtime=1000) -class ContainerConfigTest(unittest.TestCase): - def test_create_container_config_volume_driver_warning(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - ContainerConfig( - version='1.21', image='scratch', command=None, - volume_driver='local' - ) - - assert len(w) == 1 - assert 'The volume_driver option has been moved' in str(w[0].message) - - class ContainerSpecTest(unittest.TestCase): def test_parse_mounts(self): spec = ContainerSpec( diff --git a/tests/unit/fake_api.py b/tests/unit/fake_api.py index 37154a3..63d7331 100644 --- a/tests/unit/fake_api.py +++ b/tests/unit/fake_api.py @@ -21,21 +21,36 @@ FAKE_NODE_ID = '24ifsmvkjbyhk' # for clarity and readability -def get_fake_raw_version(): +def get_fake_version(): status_code = 200 response = { - "ApiVersion": "1.18", - "GitCommit": "fake-commit", - "GoVersion": "go1.3.3", - "Version": "1.5.0" + 'ApiVersion': '1.35', + 'Arch': 'amd64', + 'BuildTime': '2018-01-10T20:09:37.000000000+00:00', + 'Components': [{ + 'Details': { + 'ApiVersion': '1.35', + 'Arch': 'amd64', + 'BuildTime': '2018-01-10T20:09:37.000000000+00:00', + 'Experimental': 'false', + 'GitCommit': '03596f5', + 'GoVersion': 'go1.9.2', + 'KernelVersion': '4.4.0-112-generic', + 'MinAPIVersion': '1.12', + 'Os': 'linux' + }, + 'Name': 'Engine', + 'Version': '18.01.0-ce' + }], + 'GitCommit': '03596f5', + 'GoVersion': 'go1.9.2', + 'KernelVersion': '4.4.0-112-generic', + 'MinAPIVersion': '1.12', + 'Os': 'linux', + 'Platform': {'Name': ''}, + 'Version': '18.01.0-ce' } - return status_code, response - -def get_fake_version(): - status_code = 200 - response = {'GoVersion': '1', 'Version': '1.1.1', - 'GitCommit': 'deadbeef+CHANGES'} return status_code, response @@ -503,7 +518,7 @@ if constants.IS_WINDOWS_PLATFORM: fake_responses = { '{0}/version'.format(prefix): - get_fake_raw_version, + get_fake_version, '{1}/{0}/version'.format(CURRENT_VERSION, prefix): get_fake_version, '{1}/{0}/info'.format(CURRENT_VERSION, prefix): |