Merge pull request #2443 from docker/4.1.0-release

4.1.0 release
This commit is contained in:
Chris Crone 2019-10-03 16:16:42 +02:00 committed by GitHub
commit 66495870de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 453 additions and 248 deletions

View File

@ -1,4 +1,6 @@
FROM python:2.7
ARG PYTHON_VERSION=2.7
FROM python:${PYTHON_VERSION}
RUN mkdir /src
WORKDIR /src

View File

@ -1,4 +1,6 @@
FROM python:3.5
ARG PYTHON_VERSION=3.7
FROM python:${PYTHON_VERSION}
ARG uid=1000
ARG gid=1000

View File

@ -1,4 +1,6 @@
FROM python:3.6
ARG PYTHON_VERSION=3.7
FROM python:${PYTHON_VERSION}
RUN mkdir /src
WORKDIR /src

10
Jenkinsfile vendored
View File

@ -25,7 +25,7 @@ def buildImages = { ->
imageNamePy3 = "${imageNameBase}:py3-${gitCommit()}"
buildImage(imageNamePy2, "-f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 .", "py2.7")
buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.6 .", "py3.6")
buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.7 .", "py3.7")
}
}
}
@ -46,12 +46,14 @@ def getDockerVersions = { ->
def getAPIVersion = { engineVersion ->
def versionMap = [
'17.06': '1.30', '17.12': '1.35', '18.02': '1.36', '18.03': '1.37',
'18.06': '1.38', '18.09': '1.39'
'17.06': '1.30',
'18.03': '1.37',
'18.09': '1.39',
'19.03': '1.40'
]
def result = versionMap[engineVersion.substring(0, 5)]
if (!result) {
return '1.39'
return '1.40'
}
return result
}

View File

@ -8,11 +8,11 @@ clean:
.PHONY: build
build:
docker build -t docker-sdk-python -f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 .
docker build -t docker-sdk-python -f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 --build-arg APT_MIRROR .
.PHONY: build-py3
build-py3:
docker build -t docker-sdk-python3 -f tests/Dockerfile .
docker build -t docker-sdk-python3 -f tests/Dockerfile --build-arg APT_MIRROR .
.PHONY: build-docs
build-docs:

View File

@ -308,7 +308,8 @@ class BuildApiMixin(object):
auth_data = self._auth_configs.get_all_credentials()
# See https://github.com/docker/docker-py/issues/1683
if auth.INDEX_URL not in auth_data and auth.INDEX_URL in auth_data:
if (auth.INDEX_URL not in auth_data and
auth.INDEX_NAME in auth_data):
auth_data[auth.INDEX_URL] = auth_data.get(auth.INDEX_NAME, {})
log.debug(

View File

@ -174,7 +174,8 @@ class ContainerApiMixin(object):
- `exited` (int): Only containers with specified exit code
- `status` (str): One of ``restarting``, ``running``,
``paused``, ``exited``
- `label` (str): format either ``"key"`` or ``"key=value"``
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
- `id` (str): The id of the container.
- `name` (str): The name of the container.
- `ancestor` (str): Filter by container ancestor. Format of
@ -502,6 +503,7 @@ class ContainerApiMixin(object):
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
mem_reservation (int or str): Memory soft limit.
mem_swappiness (int): Tune a container's memory swappiness
behavior. Accepts number between 0 and 100.
memswap_limit (str or int): Maximum amount of memory + swap a

View File

@ -70,7 +70,8 @@ class ImageApiMixin(object):
filters (dict): Filters to be processed on the image list.
Available filters:
- ``dangling`` (bool)
- ``label`` (str): format either ``key`` or ``key=value``
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
Returns:
(dict or list): A list if ``quiet=True``, otherwise a dict.

View File

@ -7,7 +7,7 @@ from .. import utils
class NetworkApiMixin(object):
def networks(self, names=None, ids=None, filters=None):
"""
List networks. Similar to the ``docker networks ls`` command.
List networks. Similar to the ``docker network ls`` command.
Args:
names (:py:class:`list`): List of names to filter by
@ -15,7 +15,8 @@ class NetworkApiMixin(object):
filters (dict): Filters to be processed on the network list.
Available filters:
- ``driver=[<driver-name>]`` Matches a network's driver.
- ``label=[<key>]`` or ``label=[<key>=<value>]``.
- ``label=[<key>]``, ``label=[<key>=<value>]`` or a list of
such.
- ``type=["custom"|"builtin"]`` Filters networks by type.
Returns:

View File

@ -135,8 +135,9 @@ class ServiceApiMixin(object):
of the service. Default: ``None``
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs to attach
the service to. Default: ``None``.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
access and load balance a service. Default: ``None``.
@ -383,8 +384,9 @@ class ServiceApiMixin(object):
of the service. Default: ``None``.
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs to attach
the service to. Default: ``None``.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
access and load balance a service. Default: ``None``.
fetch_current_spec (boolean): Use the undefined settings from the

View File

@ -303,12 +303,14 @@ class AuthConfig(dict):
auth_data[k] = self._resolve_authconfig_credstore(
k, self.creds_store
)
auth_data[convert_to_hostname(k)] = auth_data[k]
# credHelpers entries take priority over all others
for reg, store_name in self.cred_helpers.items():
auth_data[reg] = self._resolve_authconfig_credstore(
reg, store_name
)
auth_data[convert_to_hostname(reg)] = auth_data[reg]
return auth_data

View File

@ -618,7 +618,7 @@ class ContainerCollection(Collection):
(``100000b``, ``1000k``, ``128m``, ``1g``). If a string is
specified without a units character, bytes are assumed as an
intended unit.
mem_reservation (int or str): Memory soft limit
mem_reservation (int or str): Memory soft limit.
mem_swappiness (int): Tune a container's memory swappiness
behavior. Accepts number between 0 and 100.
memswap_limit (str or int): Maximum amount of memory + swap a
@ -900,7 +900,8 @@ class ContainerCollection(Collection):
- `exited` (int): Only containers with specified exit code
- `status` (str): One of ``restarting``, ``running``,
``paused``, ``exited``
- `label` (str): format either ``"key"`` or ``"key=value"``
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
- `id` (str): The id of the container.
- `name` (str): The name of the container.
- `ancestor` (str): Filter by container ancestor. Format of

View File

@ -350,7 +350,8 @@ class ImageCollection(Collection):
filters (dict): Filters to be processed on the image list.
Available filters:
- ``dangling`` (bool)
- ``label`` (str): format either ``key`` or ``key=value``
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
Returns:
(list of :py:class:`Image`): The images.

View File

@ -190,7 +190,8 @@ class NetworkCollection(Collection):
filters (dict): Filters to be processed on the network list.
Available filters:
- ``driver=[<driver-name>]`` Matches a network's driver.
- ``label=[<key>]`` or ``label=[<key>=<value>]``.
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
- ``type=["custom"|"builtin"]`` Filters networks by type.
greedy (bool): Fetch more details for each network individually.
You might want this to get the containers attached to them.

View File

@ -178,11 +178,12 @@ class ServiceCollection(Collection):
``source:target:options``, where options is either
``ro`` or ``rw``.
name (str): Name to give to the service.
networks (list of str): List of network names or IDs to attach
the service to. Default: ``None``.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
resources (Resources): Resource limits and reservations.
restart_policy (RestartPolicy): Restart policy for containers.
secrets (list of :py:class:`docker.types.SecretReference`): List
secrets (list of :py:class:`~docker.types.SecretReference`): List
of secrets accessible to containers for this service.
stop_grace_period (int): Amount of time to wait for
containers to terminate before forcefully killing them.
@ -205,8 +206,9 @@ class ServiceCollection(Collection):
the container's `hosts` file.
dns_config (DNSConfig): Specification for DNS
related configurations in resolver configuration file.
configs (:py:class:`list`): List of :py:class:`ConfigReference`
that will be exposed to the service.
configs (:py:class:`list`): List of
:py:class:`~docker.types.ConfigReference` that will be exposed
to the service.
privileges (Privileges): Security options for the service's
containers.

View File

@ -7,6 +7,6 @@ from .services import (
ConfigReference, ContainerSpec, DNSConfig, DriverConfig, EndpointSpec,
Mount, Placement, PlacementPreference, Privileges, Resources,
RestartPolicy, RollbackConfig, SecretReference, ServiceMode, TaskTemplate,
UpdateConfig
UpdateConfig, NetworkAttachmentConfig
)
from .swarm import SwarmSpec, SwarmExternalCA

View File

@ -26,8 +26,8 @@ class TaskTemplate(dict):
placement (Placement): Placement instructions for the scheduler.
If a list is passed instead, it is assumed to be a list of
constraints as part of a :py:class:`Placement` object.
networks (:py:class:`list`): List of network names or IDs to attach
the containers to.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`NetworkAttachmentConfig` to attach the service to.
force_update (int): A counter that triggers an update even if no
relevant parameters have been changed.
"""
@ -770,3 +770,21 @@ class Privileges(dict):
if len(selinux_context) > 0:
self['SELinuxContext'] = selinux_context
class NetworkAttachmentConfig(dict):
"""
Network attachment options for a service.
Args:
target (str): The target network for attachment.
Can be a network name or ID.
aliases (:py:class:`list`): A list of discoverable alternate names
for the service.
options (:py:class:`dict`): Driver attachment options for the
network target.
"""
def __init__(self, target, aliases=None, options=None):
self['Target'] = target
self['Aliases'] = aliases
self['DriverOpts'] = options

View File

@ -1,2 +1,2 @@
version = "4.0.2"
version = "4.1.0"
version_info = tuple([int(d) for d in version.split("-")[0].split(".")])

View File

@ -142,6 +142,7 @@ Configuration types
.. autoclass:: IPAMPool
.. autoclass:: LogConfig
.. autoclass:: Mount
.. autoclass:: NetworkAttachmentConfig
.. autoclass:: Placement
.. autoclass:: PlacementPreference
.. autoclass:: Privileges

View File

@ -1,6 +1,27 @@
Change log
==========
4.1.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/milestone/61?closed=1)
### Bugfixes
- Correct `INDEX_URL` logic in build.py _set_auth_headers
- Fix for empty auth keys in config.json
### Features
- Add `NetworkAttachmentConfig` for service create/update
### Miscellaneous
- Bump pytest to 4.3.1
- Adjust `--platform` tests for changes in docker engine
- Update credentials-helpers to v0.6.3
4.0.2
-----

View File

@ -1,2 +1,5 @@
[pytest]
addopts = --tb=short -rxs
junit_suite_name = docker-py
junit_family = xunit2

View File

@ -1,6 +1,6 @@
coverage==4.5.2
flake8==3.6.0
mock==1.0.1
pytest==4.1.0
pytest==4.3.1
pytest-cov==2.6.1
pytest-timeout==1.3.3

View File

@ -1,5 +1,11 @@
ARG PYTHON_VERSION=3.6
FROM python:$PYTHON_VERSION-jessie
ARG PYTHON_VERSION=3.7
FROM python:${PYTHON_VERSION}
ARG APT_MIRROR
RUN sed -ri "s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g" /etc/apt/sources.list \
&& sed -ri "s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g" /etc/apt/sources.list
RUN apt-get update && apt-get -y install \
gnupg2 \
pass \
@ -8,9 +14,9 @@ RUN apt-get update && apt-get -y install \
COPY ./tests/gpg-keys /gpg-keys
RUN gpg2 --import gpg-keys/secret
RUN gpg2 --import-ownertrust gpg-keys/ownertrust
RUN yes | pass init $(gpg2 --no-auto-check-trustdb --list-secret-keys | grep ^sec | cut -d/ -f2 | cut -d" " -f1)
RUN yes | pass init $(gpg2 --no-auto-check-trustdb --list-secret-key | awk '/^sec/{getline; $1=$1; print}')
RUN gpg2 --check-trustdb
ARG CREDSTORE_VERSION=v0.6.0
ARG CREDSTORE_VERSION=v0.6.3
RUN curl -sSL -o /opt/docker-credential-pass.tar.gz \
https://github.com/docker/docker-credential-helpers/releases/download/$CREDSTORE_VERSION/docker-credential-pass-$CREDSTORE_VERSION-amd64.tar.gz && \
tar -xf /opt/docker-credential-pass.tar.gz -O > /usr/local/bin/docker-credential-pass && \

View File

@ -1,4 +1,6 @@
FROM python:2.7
ARG PYTHON_VERSION=2.7
FROM python:${PYTHON_VERSION}
RUN mkdir /tmp/certs
VOLUME /certs

View File

@ -9,7 +9,7 @@ from docker.utils.proxy import ProxyConfig
import pytest
import six
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
from ..helpers import random_name, requires_api_version, requires_experimental
@ -277,7 +277,7 @@ class BuildTest(BaseAPIIntegrationTest):
# Set up pingable endpoint on custom network
network = self.client.create_network(random_name())['Id']
self.tmp_networks.append(network)
container = self.client.create_container(BUSYBOX, 'top')
container = self.client.create_container(TEST_IMG, 'top')
self.tmp_containers.append(container)
self.client.start(container)
self.client.connect_container_to_network(
@ -448,8 +448,10 @@ class BuildTest(BaseAPIIntegrationTest):
for _ in stream:
pass
assert excinfo.value.status_code == 400
assert 'invalid platform' in excinfo.exconly()
# Some API versions incorrectly returns 500 status; assert 4xx or 5xx
assert excinfo.value.is_error()
assert 'unknown operating system' in excinfo.exconly() \
or 'invalid platform' in excinfo.exconly()
def test_build_out_of_context_dockerfile(self):
base_dir = tempfile.mkdtemp()

View File

@ -15,7 +15,7 @@ from ..helpers import assert_cat_socket_detached_with_keys
from ..helpers import ctrl_with
from ..helpers import requires_api_version
from .base import BaseAPIIntegrationTest
from .base import BUSYBOX
from .base import TEST_IMG
from docker.constants import IS_WINDOWS_PLATFORM
from docker.utils.socket import next_frame_header
from docker.utils.socket import read_exactly
@ -25,7 +25,7 @@ class ListContainersTest(BaseAPIIntegrationTest):
def test_list_containers(self):
res0 = self.client.containers(all=True)
size = len(res0)
res1 = self.client.create_container(BUSYBOX, 'true')
res1 = self.client.create_container(TEST_IMG, 'true')
assert 'Id' in res1
self.client.start(res1['Id'])
self.tmp_containers.append(res1['Id'])
@ -44,13 +44,13 @@ class ListContainersTest(BaseAPIIntegrationTest):
class CreateContainerTest(BaseAPIIntegrationTest):
def test_create(self):
res = self.client.create_container(BUSYBOX, 'true')
res = self.client.create_container(TEST_IMG, 'true')
assert 'Id' in res
self.tmp_containers.append(res['Id'])
def test_create_with_host_pid_mode(self):
ctnr = self.client.create_container(
BUSYBOX, 'true', host_config=self.client.create_host_config(
TEST_IMG, 'true', host_config=self.client.create_host_config(
pid_mode='host', network_mode='none'
)
)
@ -65,7 +65,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_links(self):
res0 = self.client.create_container(
BUSYBOX, 'cat',
TEST_IMG, 'cat',
detach=True, stdin_open=True,
environment={'FOO': '1'})
@ -75,7 +75,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
self.client.start(container1_id)
res1 = self.client.create_container(
BUSYBOX, 'cat',
TEST_IMG, 'cat',
detach=True, stdin_open=True,
environment={'FOO': '1'})
@ -94,7 +94,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
link_env_prefix2 = link_alias2.upper()
res2 = self.client.create_container(
BUSYBOX, 'env', host_config=self.client.create_host_config(
TEST_IMG, 'env', host_config=self.client.create_host_config(
links={link_path1: link_alias1, link_path2: link_alias2},
network_mode='bridge'
)
@ -114,7 +114,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_restart_policy(self):
container = self.client.create_container(
BUSYBOX, ['sleep', '2'],
TEST_IMG, ['sleep', '2'],
host_config=self.client.create_host_config(
restart_policy={"Name": "always", "MaximumRetryCount": 0},
network_mode='none'
@ -133,21 +133,21 @@ class CreateContainerTest(BaseAPIIntegrationTest):
vol_names = ['foobar_vol0', 'foobar_vol1']
res0 = self.client.create_container(
BUSYBOX, 'true', name=vol_names[0]
TEST_IMG, 'true', name=vol_names[0]
)
container1_id = res0['Id']
self.tmp_containers.append(container1_id)
self.client.start(container1_id)
res1 = self.client.create_container(
BUSYBOX, 'true', name=vol_names[1]
TEST_IMG, 'true', name=vol_names[1]
)
container2_id = res1['Id']
self.tmp_containers.append(container2_id)
self.client.start(container2_id)
res = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True,
TEST_IMG, 'cat', detach=True, stdin_open=True,
host_config=self.client.create_host_config(
volumes_from=vol_names, network_mode='none'
)
@ -161,7 +161,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def create_container_readonly_fs(self):
ctnr = self.client.create_container(
BUSYBOX, ['mkdir', '/shrine'],
TEST_IMG, ['mkdir', '/shrine'],
host_config=self.client.create_host_config(
read_only=True, network_mode='none'
)
@ -173,7 +173,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
assert res != 0
def create_container_with_name(self):
res = self.client.create_container(BUSYBOX, 'true', name='foobar')
res = self.client.create_container(TEST_IMG, 'true', name='foobar')
assert 'Id' in res
self.tmp_containers.append(res['Id'])
inspect = self.client.inspect_container(res['Id'])
@ -182,7 +182,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def create_container_privileged(self):
res = self.client.create_container(
BUSYBOX, 'true', host_config=self.client.create_host_config(
TEST_IMG, 'true', host_config=self.client.create_host_config(
privileged=True, network_mode='none'
)
)
@ -208,7 +208,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_mac_address(self):
mac_address_expected = "02:42:ac:11:00:0a"
container = self.client.create_container(
BUSYBOX, ['sleep', '60'], mac_address=mac_address_expected)
TEST_IMG, ['sleep', '60'], mac_address=mac_address_expected)
id = container['Id']
@ -220,7 +220,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_group_id_ints(self):
container = self.client.create_container(
BUSYBOX, 'id -G',
TEST_IMG, 'id -G',
host_config=self.client.create_host_config(group_add=[1000, 1001])
)
self.tmp_containers.append(container)
@ -236,7 +236,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_group_id_strings(self):
container = self.client.create_container(
BUSYBOX, 'id -G', host_config=self.client.create_host_config(
TEST_IMG, 'id -G', host_config=self.client.create_host_config(
group_add=['1000', '1001']
)
)
@ -259,7 +259,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
)
container = self.client.create_container(
BUSYBOX, ['true'],
TEST_IMG, ['true'],
host_config=self.client.create_host_config(log_config=log_config)
)
self.tmp_containers.append(container['Id'])
@ -281,7 +281,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
with pytest.raises(docker.errors.APIError) as excinfo:
# raises an internal server error 500
container = self.client.create_container(
BUSYBOX, ['true'], host_config=self.client.create_host_config(
TEST_IMG, ['true'], host_config=self.client.create_host_config(
log_config=log_config
)
)
@ -296,7 +296,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
)
container = self.client.create_container(
BUSYBOX, ['true'],
TEST_IMG, ['true'],
host_config=self.client.create_host_config(log_config=log_config)
)
self.tmp_containers.append(container['Id'])
@ -315,7 +315,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
)
container = self.client.create_container(
BUSYBOX, ['true'],
TEST_IMG, ['true'],
host_config=self.client.create_host_config(log_config=log_config)
)
self.tmp_containers.append(container['Id'])
@ -329,7 +329,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_memory_constraints_with_str(self):
ctnr = self.client.create_container(
BUSYBOX, 'true',
TEST_IMG, 'true',
host_config=self.client.create_host_config(
memswap_limit='1G',
mem_limit='700M'
@ -347,7 +347,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_memory_constraints_with_int(self):
ctnr = self.client.create_container(
BUSYBOX, 'true',
TEST_IMG, 'true',
host_config=self.client.create_host_config(mem_swappiness=40)
)
assert 'Id' in ctnr
@ -361,7 +361,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_environment_variable_no_value(self):
container = self.client.create_container(
BUSYBOX,
TEST_IMG,
['echo'],
environment={'Foo': None, 'Other': 'one', 'Blank': ''},
)
@ -378,7 +378,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
}
container = self.client.create_container(
BUSYBOX,
TEST_IMG,
['echo'],
host_config=self.client.create_host_config(
tmpfs=tmpfs))
@ -390,7 +390,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
@requires_api_version('1.24')
def test_create_with_isolation(self):
container = self.client.create_container(
BUSYBOX, ['echo'], host_config=self.client.create_host_config(
TEST_IMG, ['echo'], host_config=self.client.create_host_config(
isolation='default'
)
)
@ -404,7 +404,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
auto_remove=True
)
container = self.client.create_container(
BUSYBOX, ['echo', 'test'], host_config=host_config
TEST_IMG, ['echo', 'test'], host_config=host_config
)
self.tmp_containers.append(container['Id'])
config = self.client.inspect_container(container)
@ -413,7 +413,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_create_with_stop_timeout(self):
container = self.client.create_container(
BUSYBOX, ['echo', 'test'], stop_timeout=25
TEST_IMG, ['echo', 'test'], stop_timeout=25
)
self.tmp_containers.append(container['Id'])
config = self.client.inspect_container(container)
@ -426,7 +426,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
storage_opt={'size': '120G'}
)
container = self.client.create_container(
BUSYBOX, ['echo', 'test'], host_config=host_config
TEST_IMG, ['echo', 'test'], host_config=host_config
)
self.tmp_containers.append(container)
config = self.client.inspect_container(container)
@ -437,7 +437,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_create_with_init(self):
ctnr = self.client.create_container(
BUSYBOX, 'true',
TEST_IMG, 'true',
host_config=self.client.create_host_config(
init=True
)
@ -451,7 +451,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
reason='CONFIG_RT_GROUP_SCHED isn\'t enabled')
def test_create_with_cpu_rt_options(self):
ctnr = self.client.create_container(
BUSYBOX, 'true', host_config=self.client.create_host_config(
TEST_IMG, 'true', host_config=self.client.create_host_config(
cpu_rt_period=1000, cpu_rt_runtime=500
)
)
@ -464,7 +464,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_device_cgroup_rules(self):
rule = 'c 7:128 rwm'
ctnr = self.client.create_container(
BUSYBOX, 'cat /sys/fs/cgroup/devices/devices.list',
TEST_IMG, 'cat /sys/fs/cgroup/devices/devices.list',
host_config=self.client.create_host_config(
device_cgroup_rules=[rule]
)
@ -477,7 +477,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
def test_create_with_uts_mode(self):
container = self.client.create_container(
BUSYBOX, ['echo'], host_config=self.client.create_host_config(
TEST_IMG, ['echo'], host_config=self.client.create_host_config(
uts_mode='host'
)
)
@ -501,7 +501,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
self.run_with_volume(
False,
BUSYBOX,
TEST_IMG,
['touch', os.path.join(self.mount_dest, self.filename)],
)
@ -509,7 +509,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
container = self.run_with_volume(
False,
BUSYBOX,
TEST_IMG,
['ls', self.mount_dest],
)
logs = self.client.logs(container)
@ -523,12 +523,12 @@ class VolumeBindTest(BaseAPIIntegrationTest):
def test_create_with_binds_ro(self):
self.run_with_volume(
False,
BUSYBOX,
TEST_IMG,
['touch', os.path.join(self.mount_dest, self.filename)],
)
container = self.run_with_volume(
True,
BUSYBOX,
TEST_IMG,
['ls', self.mount_dest],
)
logs = self.client.logs(container)
@ -547,7 +547,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
)
host_config = self.client.create_host_config(mounts=[mount])
container = self.run_container(
BUSYBOX, ['ls', self.mount_dest],
TEST_IMG, ['ls', self.mount_dest],
host_config=host_config
)
assert container
@ -566,7 +566,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
)
host_config = self.client.create_host_config(mounts=[mount])
container = self.run_container(
BUSYBOX, ['ls', self.mount_dest],
TEST_IMG, ['ls', self.mount_dest],
host_config=host_config
)
assert container
@ -585,7 +585,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
)
host_config = self.client.create_host_config(mounts=[mount])
container = self.client.create_container(
BUSYBOX, ['true'], host_config=host_config,
TEST_IMG, ['true'], host_config=host_config,
)
assert container
inspect_data = self.client.inspect_container(container)
@ -631,7 +631,7 @@ class ArchiveTest(BaseAPIIntegrationTest):
def test_get_file_archive_from_container(self):
data = 'The Maid and the Pocket Watch of Blood'
ctnr = self.client.create_container(
BUSYBOX, 'sh -c "echo {0} > /vol1/data.txt"'.format(data),
TEST_IMG, 'sh -c "echo {0} > /vol1/data.txt"'.format(data),
volumes=['/vol1']
)
self.tmp_containers.append(ctnr)
@ -650,7 +650,7 @@ class ArchiveTest(BaseAPIIntegrationTest):
def test_get_file_stat_from_container(self):
data = 'The Maid and the Pocket Watch of Blood'
ctnr = self.client.create_container(
BUSYBOX, 'sh -c "echo -n {0} > /vol1/data.txt"'.format(data),
TEST_IMG, 'sh -c "echo -n {0} > /vol1/data.txt"'.format(data),
volumes=['/vol1']
)
self.tmp_containers.append(ctnr)
@ -668,7 +668,7 @@ class ArchiveTest(BaseAPIIntegrationTest):
test_file.write(data)
test_file.seek(0)
ctnr = self.client.create_container(
BUSYBOX,
TEST_IMG,
'cat {0}'.format(
os.path.join('/vol1/', os.path.basename(test_file.name))
),
@ -690,7 +690,7 @@ class ArchiveTest(BaseAPIIntegrationTest):
dirs = ['foo', 'bar']
base = helpers.make_tree(dirs, files)
ctnr = self.client.create_container(
BUSYBOX, 'ls -p /vol1', volumes=['/vol1']
TEST_IMG, 'ls -p /vol1', volumes=['/vol1']
)
self.tmp_containers.append(ctnr)
with docker.utils.tar(base) as test_tar:
@ -711,7 +711,7 @@ class RenameContainerTest(BaseAPIIntegrationTest):
def test_rename_container(self):
version = self.client.version()['Version']
name = 'hong_meiling'
res = self.client.create_container(BUSYBOX, 'true')
res = self.client.create_container(TEST_IMG, 'true')
assert 'Id' in res
self.tmp_containers.append(res['Id'])
self.client.rename(res, name)
@ -725,7 +725,7 @@ class RenameContainerTest(BaseAPIIntegrationTest):
class StartContainerTest(BaseAPIIntegrationTest):
def test_start_container(self):
res = self.client.create_container(BUSYBOX, 'true')
res = self.client.create_container(TEST_IMG, 'true')
assert 'Id' in res
self.tmp_containers.append(res['Id'])
self.client.start(res['Id'])
@ -741,7 +741,7 @@ class StartContainerTest(BaseAPIIntegrationTest):
assert inspect['State']['ExitCode'] == 0
def test_start_container_with_dict_instead_of_id(self):
res = self.client.create_container(BUSYBOX, 'true')
res = self.client.create_container(TEST_IMG, 'true')
assert 'Id' in res
self.tmp_containers.append(res['Id'])
self.client.start(res)
@ -769,7 +769,7 @@ class StartContainerTest(BaseAPIIntegrationTest):
'true && echo "Night of Nights"'
]
for cmd in commands:
container = self.client.create_container(BUSYBOX, cmd)
container = self.client.create_container(TEST_IMG, cmd)
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -779,7 +779,7 @@ class StartContainerTest(BaseAPIIntegrationTest):
class WaitTest(BaseAPIIntegrationTest):
def test_wait(self):
res = self.client.create_container(BUSYBOX, ['sleep', '3'])
res = self.client.create_container(TEST_IMG, ['sleep', '3'])
id = res['Id']
self.tmp_containers.append(id)
self.client.start(id)
@ -792,7 +792,7 @@ class WaitTest(BaseAPIIntegrationTest):
assert inspect['State']['ExitCode'] == exitcode
def test_wait_with_dict_instead_of_id(self):
res = self.client.create_container(BUSYBOX, ['sleep', '3'])
res = self.client.create_container(TEST_IMG, ['sleep', '3'])
id = res['Id']
self.tmp_containers.append(id)
self.client.start(res)
@ -806,13 +806,13 @@ class WaitTest(BaseAPIIntegrationTest):
@requires_api_version('1.30')
def test_wait_with_condition(self):
ctnr = self.client.create_container(BUSYBOX, 'true')
ctnr = self.client.create_container(TEST_IMG, 'true')
self.tmp_containers.append(ctnr)
with pytest.raises(requests.exceptions.ConnectionError):
self.client.wait(ctnr, condition='removed', timeout=1)
ctnr = self.client.create_container(
BUSYBOX, ['sleep', '3'],
TEST_IMG, ['sleep', '3'],
host_config=self.client.create_host_config(auto_remove=True)
)
self.tmp_containers.append(ctnr)
@ -826,7 +826,7 @@ class LogsTest(BaseAPIIntegrationTest):
def test_logs(self):
snippet = 'Flowering Nights (Sakuya Iyazoi)'
container = self.client.create_container(
BUSYBOX, 'echo {0}'.format(snippet)
TEST_IMG, 'echo {0}'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -840,7 +840,7 @@ class LogsTest(BaseAPIIntegrationTest):
snippet = '''Line1
Line2'''
container = self.client.create_container(
BUSYBOX, 'echo "{0}"'.format(snippet)
TEST_IMG, 'echo "{0}"'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -853,7 +853,7 @@ Line2'''
def test_logs_streaming_and_follow(self):
snippet = 'Flowering Nights (Sakuya Iyazoi)'
container = self.client.create_container(
BUSYBOX, 'echo {0}'.format(snippet)
TEST_IMG, 'echo {0}'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -873,7 +873,7 @@ Line2'''
def test_logs_streaming_and_follow_and_cancel(self):
snippet = 'Flowering Nights (Sakuya Iyazoi)'
container = self.client.create_container(
BUSYBOX, 'sh -c "echo \\"{0}\\" && sleep 3"'.format(snippet)
TEST_IMG, 'sh -c "echo \\"{0}\\" && sleep 3"'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -891,7 +891,7 @@ Line2'''
def test_logs_with_dict_instead_of_id(self):
snippet = 'Flowering Nights (Sakuya Iyazoi)'
container = self.client.create_container(
BUSYBOX, 'echo {0}'.format(snippet)
TEST_IMG, 'echo {0}'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -904,7 +904,7 @@ Line2'''
def test_logs_with_tail_0(self):
snippet = 'Flowering Nights (Sakuya Iyazoi)'
container = self.client.create_container(
BUSYBOX, 'echo "{0}"'.format(snippet)
TEST_IMG, 'echo "{0}"'.format(snippet)
)
id = container['Id']
self.tmp_containers.append(id)
@ -918,7 +918,7 @@ Line2'''
def test_logs_with_until(self):
snippet = 'Shanghai Teahouse (Hong Meiling)'
container = self.client.create_container(
BUSYBOX, 'echo "{0}"'.format(snippet)
TEST_IMG, 'echo "{0}"'.format(snippet)
)
self.tmp_containers.append(container)
@ -933,7 +933,7 @@ Line2'''
class DiffTest(BaseAPIIntegrationTest):
def test_diff(self):
container = self.client.create_container(BUSYBOX, ['touch', '/test'])
container = self.client.create_container(TEST_IMG, ['touch', '/test'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -946,7 +946,7 @@ class DiffTest(BaseAPIIntegrationTest):
assert test_diff[0]['Kind'] == 1
def test_diff_with_dict_instead_of_id(self):
container = self.client.create_container(BUSYBOX, ['touch', '/test'])
container = self.client.create_container(TEST_IMG, ['touch', '/test'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -961,7 +961,7 @@ class DiffTest(BaseAPIIntegrationTest):
class StopTest(BaseAPIIntegrationTest):
def test_stop(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -973,7 +973,7 @@ class StopTest(BaseAPIIntegrationTest):
assert state['Running'] is False
def test_stop_with_dict_instead_of_id(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
assert 'Id' in container
id = container['Id']
self.client.start(container)
@ -988,7 +988,7 @@ class StopTest(BaseAPIIntegrationTest):
class KillTest(BaseAPIIntegrationTest):
def test_kill(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -1002,7 +1002,7 @@ class KillTest(BaseAPIIntegrationTest):
assert state['Running'] is False
def test_kill_with_dict_instead_of_id(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -1016,7 +1016,7 @@ class KillTest(BaseAPIIntegrationTest):
assert state['Running'] is False
def test_kill_with_signal(self):
id = self.client.create_container(BUSYBOX, ['sleep', '60'])
id = self.client.create_container(TEST_IMG, ['sleep', '60'])
self.tmp_containers.append(id)
self.client.start(id)
self.client.kill(
@ -1033,7 +1033,7 @@ class KillTest(BaseAPIIntegrationTest):
assert state['Running'] is False, state
def test_kill_with_signal_name(self):
id = self.client.create_container(BUSYBOX, ['sleep', '60'])
id = self.client.create_container(TEST_IMG, ['sleep', '60'])
self.client.start(id)
self.tmp_containers.append(id)
self.client.kill(id, signal='SIGKILL')
@ -1048,7 +1048,7 @@ class KillTest(BaseAPIIntegrationTest):
assert state['Running'] is False, state
def test_kill_with_signal_integer(self):
id = self.client.create_container(BUSYBOX, ['sleep', '60'])
id = self.client.create_container(TEST_IMG, ['sleep', '60'])
self.client.start(id)
self.tmp_containers.append(id)
self.client.kill(id, signal=9)
@ -1077,7 +1077,7 @@ class PortTest(BaseAPIIntegrationTest):
]
container = self.client.create_container(
BUSYBOX, ['sleep', '60'], ports=ports,
TEST_IMG, ['sleep', '60'], ports=ports,
host_config=self.client.create_host_config(
port_bindings=port_bindings, network_mode='bridge'
)
@ -1104,7 +1104,7 @@ class PortTest(BaseAPIIntegrationTest):
class ContainerTopTest(BaseAPIIntegrationTest):
def test_top(self):
container = self.client.create_container(
BUSYBOX, ['sleep', '60']
TEST_IMG, ['sleep', '60']
)
self.tmp_containers.append(container)
@ -1124,7 +1124,7 @@ class ContainerTopTest(BaseAPIIntegrationTest):
)
def test_top_with_psargs(self):
container = self.client.create_container(
BUSYBOX, ['sleep', '60'])
TEST_IMG, ['sleep', '60'])
self.tmp_containers.append(container)
@ -1140,7 +1140,7 @@ class ContainerTopTest(BaseAPIIntegrationTest):
class RestartContainerTest(BaseAPIIntegrationTest):
def test_restart(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -1159,7 +1159,7 @@ class RestartContainerTest(BaseAPIIntegrationTest):
self.client.kill(id)
def test_restart_with_low_timeout(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
self.client.start(container)
self.client.timeout = 3
self.client.restart(container, timeout=1)
@ -1168,7 +1168,7 @@ class RestartContainerTest(BaseAPIIntegrationTest):
self.client.kill(container)
def test_restart_with_dict_instead_of_id(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
assert 'Id' in container
id = container['Id']
self.client.start(container)
@ -1190,7 +1190,7 @@ class RestartContainerTest(BaseAPIIntegrationTest):
class RemoveContainerTest(BaseAPIIntegrationTest):
def test_remove(self):
container = self.client.create_container(BUSYBOX, ['true'])
container = self.client.create_container(TEST_IMG, ['true'])
id = container['Id']
self.client.start(id)
self.client.wait(id)
@ -1200,7 +1200,7 @@ class RemoveContainerTest(BaseAPIIntegrationTest):
assert len(res) == 0
def test_remove_with_dict_instead_of_id(self):
container = self.client.create_container(BUSYBOX, ['true'])
container = self.client.create_container(TEST_IMG, ['true'])
id = container['Id']
self.client.start(id)
self.client.wait(id)
@ -1212,7 +1212,7 @@ class RemoveContainerTest(BaseAPIIntegrationTest):
class AttachContainerTest(BaseAPIIntegrationTest):
def test_run_container_streaming(self):
container = self.client.create_container(BUSYBOX, '/bin/sh',
container = self.client.create_container(TEST_IMG, '/bin/sh',
detach=True, stdin_open=True)
id = container['Id']
self.tmp_containers.append(id)
@ -1224,7 +1224,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
line = 'hi there and stuff and things, words!'
# `echo` appends CRLF, `printf` doesn't
command = "printf '{0}'".format(line)
container = self.client.create_container(BUSYBOX, command,
container = self.client.create_container(TEST_IMG, command,
detach=True, tty=False)
self.tmp_containers.append(container)
@ -1242,7 +1242,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
def test_attach_no_stream(self):
container = self.client.create_container(
BUSYBOX, 'echo hello'
TEST_IMG, 'echo hello'
)
self.tmp_containers.append(container)
self.client.start(container)
@ -1257,7 +1257,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
reason='Flaky test on TLS')
def test_attach_stream_and_cancel(self):
container = self.client.create_container(
BUSYBOX, 'sh -c "sleep 2 && echo hello && sleep 60"',
TEST_IMG, 'sh -c "sleep 2 && echo hello && sleep 60"',
tty=True
)
self.tmp_containers.append(container)
@ -1275,7 +1275,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
def test_detach_with_default(self):
container = self.client.create_container(
BUSYBOX, 'cat',
TEST_IMG, 'cat',
detach=True, stdin_open=True, tty=True
)
self.tmp_containers.append(container)
@ -1294,7 +1294,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
self.client._general_configs['detachKeys'] = 'ctrl-p'
container = self.client.create_container(
BUSYBOX, 'cat',
TEST_IMG, 'cat',
detach=True, stdin_open=True, tty=True
)
self.tmp_containers.append(container)
@ -1311,7 +1311,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
self.client._general_configs['detachKeys'] = 'ctrl-p'
container = self.client.create_container(
BUSYBOX, 'cat',
TEST_IMG, 'cat',
detach=True, stdin_open=True, tty=True
)
self.tmp_containers.append(container)
@ -1327,7 +1327,7 @@ class AttachContainerTest(BaseAPIIntegrationTest):
class PauseTest(BaseAPIIntegrationTest):
def test_pause_unpause(self):
container = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container = self.client.create_container(TEST_IMG, ['sleep', '9999'])
id = container['Id']
self.tmp_containers.append(id)
self.client.start(container)
@ -1358,9 +1358,9 @@ class PruneTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_prune_containers(self):
container1 = self.client.create_container(
BUSYBOX, ['sh', '-c', 'echo hello > /data.txt']
TEST_IMG, ['sh', '-c', 'echo hello > /data.txt']
)
container2 = self.client.create_container(BUSYBOX, ['sleep', '9999'])
container2 = self.client.create_container(TEST_IMG, ['sleep', '9999'])
self.client.start(container1)
self.client.start(container2)
self.client.wait(container1)
@ -1373,7 +1373,7 @@ class PruneTest(BaseAPIIntegrationTest):
class GetContainerStatsTest(BaseAPIIntegrationTest):
def test_get_container_stats_no_stream(self):
container = self.client.create_container(
BUSYBOX, ['sleep', '60'],
TEST_IMG, ['sleep', '60'],
)
self.tmp_containers.append(container)
self.client.start(container)
@ -1387,7 +1387,7 @@ class GetContainerStatsTest(BaseAPIIntegrationTest):
def test_get_container_stats_stream(self):
container = self.client.create_container(
BUSYBOX, ['sleep', '60'],
TEST_IMG, ['sleep', '60'],
)
self.tmp_containers.append(container)
self.client.start(container)
@ -1405,7 +1405,7 @@ class ContainerUpdateTest(BaseAPIIntegrationTest):
old_mem_limit = 400 * 1024 * 1024
new_mem_limit = 300 * 1024 * 1024
container = self.client.create_container(
BUSYBOX, 'top', host_config=self.client.create_host_config(
TEST_IMG, 'top', host_config=self.client.create_host_config(
mem_limit=old_mem_limit
)
)
@ -1426,7 +1426,7 @@ class ContainerUpdateTest(BaseAPIIntegrationTest):
'Name': 'on-failure'
}
container = self.client.create_container(
BUSYBOX, ['sleep', '60'],
TEST_IMG, ['sleep', '60'],
host_config=self.client.create_host_config(
restart_policy=old_restart_policy
)
@ -1450,7 +1450,7 @@ class ContainerCPUTest(BaseAPIIntegrationTest):
def test_container_cpu_shares(self):
cpu_shares = 512
container = self.client.create_container(
BUSYBOX, 'ls', host_config=self.client.create_host_config(
TEST_IMG, 'ls', host_config=self.client.create_host_config(
cpu_shares=cpu_shares
)
)
@ -1462,7 +1462,7 @@ class ContainerCPUTest(BaseAPIIntegrationTest):
def test_container_cpuset(self):
cpuset_cpus = "0,1"
container = self.client.create_container(
BUSYBOX, 'ls', host_config=self.client.create_host_config(
TEST_IMG, 'ls', host_config=self.client.create_host_config(
cpuset_cpus=cpuset_cpus
)
)
@ -1474,7 +1474,7 @@ class ContainerCPUTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_create_with_runtime(self):
container = self.client.create_container(
BUSYBOX, ['echo', 'test'], runtime='runc'
TEST_IMG, ['echo', 'test'], runtime='runc'
)
self.tmp_containers.append(container['Id'])
config = self.client.inspect_container(container)
@ -1485,7 +1485,7 @@ class LinkTest(BaseAPIIntegrationTest):
def test_remove_link(self):
# Create containers
container1 = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
TEST_IMG, 'cat', detach=True, stdin_open=True
)
container1_id = container1['Id']
self.tmp_containers.append(container1_id)
@ -1497,7 +1497,7 @@ class LinkTest(BaseAPIIntegrationTest):
link_alias = 'mylink'
container2 = self.client.create_container(
BUSYBOX, 'cat', host_config=self.client.create_host_config(
TEST_IMG, 'cat', host_config=self.client.create_host_config(
links={link_path: link_alias}
)
)

View File

@ -2,7 +2,7 @@ from ..helpers import assert_cat_socket_detached_with_keys
from ..helpers import ctrl_with
from ..helpers import requires_api_version
from .base import BaseAPIIntegrationTest
from .base import BUSYBOX
from .base import TEST_IMG
from docker.utils.proxy import ProxyConfig
from docker.utils.socket import next_frame_header
from docker.utils.socket import read_exactly
@ -16,7 +16,7 @@ class ExecTest(BaseAPIIntegrationTest):
)
container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True,
TEST_IMG, 'cat', detach=True, stdin_open=True,
)
self.client.start(container)
self.tmp_containers.append(container)
@ -48,7 +48,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert item in output
def test_execute_command(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -61,7 +61,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert exec_log == b'hello\n'
def test_exec_command_string(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -74,7 +74,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert exec_log == b'hello world\n'
def test_exec_command_as_user(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -87,7 +87,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert exec_log == b'postgres\n'
def test_exec_command_as_root(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -100,7 +100,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert exec_log == b'root\n'
def test_exec_command_streaming(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.tmp_containers.append(id)
@ -115,7 +115,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert res == b'hello\nworld\n'
def test_exec_start_socket(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
container_id = container['Id']
self.client.start(container_id)
@ -137,7 +137,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert data.decode('utf-8') == line
def test_exec_start_detached(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
container_id = container['Id']
self.client.start(container_id)
@ -152,7 +152,7 @@ class ExecTest(BaseAPIIntegrationTest):
assert response == ""
def test_exec_inspect(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -167,7 +167,7 @@ class ExecTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_exec_command_with_env(self):
container = self.client.create_container(BUSYBOX, 'cat',
container = self.client.create_container(TEST_IMG, 'cat',
detach=True, stdin_open=True)
id = container['Id']
self.client.start(id)
@ -182,7 +182,7 @@ class ExecTest(BaseAPIIntegrationTest):
@requires_api_version('1.35')
def test_exec_command_with_workdir(self):
container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
TEST_IMG, 'cat', detach=True, stdin_open=True
)
self.tmp_containers.append(container)
self.client.start(container)
@ -193,7 +193,7 @@ class ExecTest(BaseAPIIntegrationTest):
def test_detach_with_default(self):
container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
TEST_IMG, 'cat', detach=True, stdin_open=True
)
id = container['Id']
self.client.start(id)
@ -212,7 +212,7 @@ class ExecTest(BaseAPIIntegrationTest):
def test_detach_with_config_file(self):
self.client._general_configs['detachKeys'] = 'ctrl-p'
container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
TEST_IMG, 'cat', detach=True, stdin_open=True
)
id = container['Id']
self.client.start(id)
@ -226,24 +226,6 @@ class ExecTest(BaseAPIIntegrationTest):
assert_cat_socket_detached_with_keys(sock, [ctrl_with('p')])
def test_detach_with_arg(self):
self.client._general_configs['detachKeys'] = 'ctrl-p'
container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
)
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
exec_id = self.client.exec_create(
id, 'cat',
stdin=True, tty=True, detach_keys='ctrl-x', stdout=True
)
sock = self.client.exec_start(exec_id, tty=True, socket=True)
self.addCleanup(sock.close)
assert_cat_socket_detached_with_keys(sock, [ctrl_with('x')])
class ExecDemuxTest(BaseAPIIntegrationTest):
cmd = 'sh -c "{}"'.format(' ; '.join([
@ -259,7 +241,7 @@ class ExecDemuxTest(BaseAPIIntegrationTest):
def setUp(self):
super(ExecDemuxTest, self).setUp()
self.container = self.client.create_container(
BUSYBOX, 'cat', detach=True, stdin_open=True
TEST_IMG, 'cat', detach=True, stdin_open=True
)
self.client.start(self.container)
self.tmp_containers.append(self.container)

View File

@ -1,4 +1,4 @@
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
from .. import helpers
SECOND = 1000000000
@ -16,7 +16,7 @@ class HealthcheckTest(BaseAPIIntegrationTest):
@helpers.requires_api_version('1.24')
def test_healthcheck_shell_command(self):
container = self.client.create_container(
BUSYBOX, 'top', healthcheck=dict(test='echo "hello world"'))
TEST_IMG, 'top', healthcheck=dict(test='echo "hello world"'))
self.tmp_containers.append(container)
res = self.client.inspect_container(container)
@ -27,7 +27,7 @@ class HealthcheckTest(BaseAPIIntegrationTest):
@helpers.requires_api_version('1.24')
def test_healthcheck_passes(self):
container = self.client.create_container(
BUSYBOX, 'top', healthcheck=dict(
TEST_IMG, 'top', healthcheck=dict(
test="true",
interval=1 * SECOND,
timeout=1 * SECOND,
@ -40,7 +40,7 @@ class HealthcheckTest(BaseAPIIntegrationTest):
@helpers.requires_api_version('1.24')
def test_healthcheck_fails(self):
container = self.client.create_container(
BUSYBOX, 'top', healthcheck=dict(
TEST_IMG, 'top', healthcheck=dict(
test="false",
interval=1 * SECOND,
timeout=1 * SECOND,
@ -53,7 +53,7 @@ class HealthcheckTest(BaseAPIIntegrationTest):
@helpers.requires_api_version('1.29')
def test_healthcheck_start_period(self):
container = self.client.create_container(
BUSYBOX, 'top', healthcheck=dict(
TEST_IMG, 'top', healthcheck=dict(
test="echo 'x' >> /counter.txt && "
"test `cat /counter.txt | wc -l` -ge 3",
interval=1 * SECOND,

View File

@ -15,7 +15,7 @@ from six.moves import socketserver
import docker
from ..helpers import requires_api_version, requires_experimental
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
class ListImagesTest(BaseAPIIntegrationTest):
@ -69,13 +69,15 @@ class PullImageTest(BaseAPIIntegrationTest):
with pytest.raises(docker.errors.APIError) as excinfo:
self.client.pull('hello-world', platform='foobar')
assert excinfo.value.status_code == 500
assert 'invalid platform' in excinfo.exconly()
# Some API versions incorrectly returns 500 status; assert 4xx or 5xx
assert excinfo.value.is_error()
assert 'unknown operating system' in excinfo.exconly() \
or 'invalid platform' in excinfo.exconly()
class CommitTest(BaseAPIIntegrationTest):
def test_commit(self):
container = self.client.create_container(BUSYBOX, ['touch', '/test'])
container = self.client.create_container(TEST_IMG, ['touch', '/test'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -88,13 +90,13 @@ class CommitTest(BaseAPIIntegrationTest):
assert img['Container'].startswith(id)
assert 'ContainerConfig' in img
assert 'Image' in img['ContainerConfig']
assert BUSYBOX == img['ContainerConfig']['Image']
busybox_id = self.client.inspect_image(BUSYBOX)['Id']
assert TEST_IMG == img['ContainerConfig']['Image']
busybox_id = self.client.inspect_image(TEST_IMG)['Id']
assert 'Parent' in img
assert img['Parent'] == busybox_id
def test_commit_with_changes(self):
cid = self.client.create_container(BUSYBOX, ['touch', '/test'])
cid = self.client.create_container(TEST_IMG, ['touch', '/test'])
self.tmp_containers.append(cid)
self.client.start(cid)
img_id = self.client.commit(
@ -110,7 +112,7 @@ class CommitTest(BaseAPIIntegrationTest):
class RemoveImageTest(BaseAPIIntegrationTest):
def test_remove(self):
container = self.client.create_container(BUSYBOX, ['touch', '/test'])
container = self.client.create_container(TEST_IMG, ['touch', '/test'])
id = container['Id']
self.client.start(id)
self.tmp_containers.append(id)
@ -317,7 +319,7 @@ class PruneImagesTest(BaseAPIIntegrationTest):
pass
# Ensure busybox does not get pruned
ctnr = self.client.create_container(BUSYBOX, ['sleep', '9999'])
ctnr = self.client.create_container(TEST_IMG, ['sleep', '9999'])
self.tmp_containers.append(ctnr)
self.client.pull('hello-world', tag='latest')
@ -341,7 +343,7 @@ class SaveLoadImagesTest(BaseAPIIntegrationTest):
@requires_api_version('1.23')
def test_get_image_load_image(self):
with tempfile.TemporaryFile() as f:
stream = self.client.get_image(BUSYBOX)
stream = self.client.get_image(TEST_IMG)
for chunk in stream:
f.write(chunk)
@ -349,7 +351,7 @@ class SaveLoadImagesTest(BaseAPIIntegrationTest):
result = self.client.load_image(f.read())
success = False
result_line = 'Loaded image: {}\n'.format(BUSYBOX)
result_line = 'Loaded image: {}\n'.format(TEST_IMG)
for data in result:
print(data)
if 'stream' in data:

View File

@ -3,7 +3,7 @@ from docker.types import IPAMConfig, IPAMPool
import pytest
from ..helpers import random_name, requires_api_version
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
class TestNetworks(BaseAPIIntegrationTest):
@ -92,7 +92,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_and_disconnect_container(self):
net_name, net_id = self.create_network()
container = self.client.create_container(BUSYBOX, 'top')
container = self.client.create_container(TEST_IMG, 'top')
self.tmp_containers.append(container)
self.client.start(container)
@ -119,7 +119,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_and_force_disconnect_container(self):
net_name, net_id = self.create_network()
container = self.client.create_container(BUSYBOX, 'top')
container = self.client.create_container(TEST_IMG, 'top')
self.tmp_containers.append(container)
self.client.start(container)
@ -144,7 +144,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_with_aliases(self):
net_name, net_id = self.create_network()
container = self.client.create_container(BUSYBOX, 'top')
container = self.client.create_container(TEST_IMG, 'top')
self.tmp_containers.append(container)
self.client.start(container)
@ -161,7 +161,7 @@ class TestNetworks(BaseAPIIntegrationTest):
net_name, net_id = self.create_network()
container = self.client.create_container(
image=BUSYBOX,
image=TEST_IMG,
command='top',
host_config=self.client.create_host_config(network_mode=net_name),
)
@ -181,7 +181,7 @@ class TestNetworks(BaseAPIIntegrationTest):
net_name, net_id = self.create_network()
container = self.client.create_container(
image=BUSYBOX,
image=TEST_IMG,
command='top',
host_config=self.client.create_host_config(
network_mode=net_name,
@ -211,7 +211,7 @@ class TestNetworks(BaseAPIIntegrationTest):
),
)
container = self.client.create_container(
image=BUSYBOX, command='top',
image=TEST_IMG, command='top',
host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config(
@ -237,7 +237,7 @@ class TestNetworks(BaseAPIIntegrationTest):
),
)
container = self.client.create_container(
image=BUSYBOX, command='top',
image=TEST_IMG, command='top',
host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config(
@ -257,7 +257,7 @@ class TestNetworks(BaseAPIIntegrationTest):
@requires_api_version('1.24')
def test_create_with_linklocal_ips(self):
container = self.client.create_container(
BUSYBOX, 'top',
TEST_IMG, 'top',
networking_config=self.client.create_networking_config(
{
'bridge': self.client.create_endpoint_config(

View File

@ -10,7 +10,7 @@ import six
from ..helpers import (
force_leave_swarm, requires_api_version, requires_experimental
)
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
class ServiceTest(BaseAPIIntegrationTest):
@ -60,7 +60,7 @@ class ServiceTest(BaseAPIIntegrationTest):
name = self.get_service_name()
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['echo', 'hello']
TEST_IMG, ['echo', 'hello']
)
task_tmpl = docker.types.TaskTemplate(container_spec)
return name, self.client.create_service(
@ -156,7 +156,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_custom_log_driver(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['echo', 'hello']
TEST_IMG, ['echo', 'hello']
)
log_cfg = docker.types.DriverConfig('none')
task_tmpl = docker.types.TaskTemplate(
@ -174,7 +174,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_volume_mount(self):
vol_name = self.get_service_name()
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['ls'],
TEST_IMG, ['ls'],
mounts=[
docker.types.Mount(target='/test', source=vol_name)
]
@ -194,7 +194,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert mount['Type'] == 'volume'
def test_create_service_with_resources_constraints(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
resources = docker.types.Resources(
cpu_limit=4000000, mem_limit=3 * 1024 * 1024 * 1024,
cpu_reservation=3500000, mem_reservation=2 * 1024 * 1024 * 1024
@ -214,7 +214,7 @@ class ServiceTest(BaseAPIIntegrationTest):
]
def _create_service_with_generic_resources(self, generic_resources):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
resources = docker.types.Resources(
generic_resources=generic_resources
@ -265,7 +265,7 @@ class ServiceTest(BaseAPIIntegrationTest):
self._create_service_with_generic_resources(test_input)
def test_create_service_with_update_config(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
update_config = docker.types.UpdateConfig(
parallelism=10, delay=5, failure_action='pause'
@ -283,7 +283,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.28')
def test_create_service_with_failure_action_rollback(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
update_config = docker.types.UpdateConfig(failure_action='rollback')
name = self.get_service_name()
@ -314,7 +314,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.28')
def test_create_service_with_rollback_config(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
rollback_cfg = docker.types.RollbackConfig(
parallelism=10, delay=5, failure_action='pause',
@ -334,7 +334,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert rollback_cfg['MaxFailureRatio'] == rc['MaxFailureRatio']
def test_create_service_with_restart_policy(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
policy = docker.types.RestartPolicy(
docker.types.RestartPolicy.condition_types.ANY,
delay=5, max_attempts=5
@ -357,7 +357,7 @@ class ServiceTest(BaseAPIIntegrationTest):
'dockerpytest_2', driver='overlay', ipam={'Driver': 'default'}
)
self.tmp_networks.append(net2['Id'])
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
svc_id = self.client.create_service(
@ -371,9 +371,38 @@ class ServiceTest(BaseAPIIntegrationTest):
{'Target': net1['Id']}, {'Target': net2['Id']}
]
def test_create_service_with_network_attachment_config(self):
network = self.client.create_network(
'dockerpytest_1', driver='overlay', ipam={'Driver': 'default'}
)
self.tmp_networks.append(network['Id'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
network_config = docker.types.NetworkAttachmentConfig(
target='dockerpytest_1',
aliases=['dockerpytest_1_alias'],
options={
'foo': 'bar'
}
)
task_tmpl = docker.types.TaskTemplate(
container_spec,
networks=[network_config]
)
name = self.get_service_name()
svc_id = self.client.create_service(
task_tmpl, name=name
)
svc_info = self.client.inspect_service(svc_id)
assert 'Networks' in svc_info['Spec']['TaskTemplate']
service_networks_info = svc_info['Spec']['TaskTemplate']['Networks']
assert len(service_networks_info) == 1
assert service_networks_info[0]['Target'] == network['Id']
assert service_networks_info[0]['Aliases'] == ['dockerpytest_1_alias']
assert service_networks_info[0]['DriverOpts'] == {'foo': 'bar'}
def test_create_service_with_placement(self):
node_id = self.client.nodes()[0]['ID']
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(
container_spec, placement=['node.id=={}'.format(node_id)]
)
@ -386,7 +415,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_placement_object(self):
node_id = self.client.nodes()[0]['ID']
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
placemt = docker.types.Placement(
constraints=['node.id=={}'.format(node_id)]
)
@ -401,7 +430,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.30')
def test_create_service_with_placement_platform(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
placemt = docker.types.Placement(platforms=[('x86_64', 'linux')])
task_tmpl = docker.types.TaskTemplate(
container_spec, placement=placemt
@ -414,7 +443,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.27')
def test_create_service_with_placement_preferences(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
placemt = docker.types.Placement(preferences=[
{'Spread': {'SpreadDescriptor': 'com.dockerpy.test'}}
])
@ -429,7 +458,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.27')
def test_create_service_with_placement_preferences_tuple(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
placemt = docker.types.Placement(preferences=(
('spread', 'com.dockerpy.test'),
))
@ -443,7 +472,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert svc_info['Spec']['TaskTemplate']['Placement'] == placemt
def test_create_service_with_endpoint_spec(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
endpoint_spec = docker.types.EndpointSpec(ports={
@ -473,7 +502,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.32')
def test_create_service_with_endpoint_spec_host_publish_mode(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
endpoint_spec = docker.types.EndpointSpec(ports={
@ -493,7 +522,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_env(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['true'], env={'DOCKER_PY_TEST': 1}
TEST_IMG, ['true'], env={'DOCKER_PY_TEST': 1}
)
task_tmpl = docker.types.TaskTemplate(
container_spec,
@ -509,7 +538,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.29')
def test_create_service_with_update_order(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
update_config = docker.types.UpdateConfig(
parallelism=10, delay=5, order='start-first'
@ -528,7 +557,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_create_service_with_tty(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['true'], tty=True
TEST_IMG, ['true'], tty=True
)
task_tmpl = docker.types.TaskTemplate(
container_spec,
@ -545,7 +574,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_create_service_with_tty_dict(self):
container_spec = {
'Image': BUSYBOX,
'Image': TEST_IMG,
'Command': ['true'],
'TTY': True
}
@ -561,7 +590,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_global_mode(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['echo', 'hello']
TEST_IMG, ['echo', 'hello']
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -574,7 +603,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_replicated_mode(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['echo', 'hello']
TEST_IMG, ['echo', 'hello']
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -767,7 +796,7 @@ class ServiceTest(BaseAPIIntegrationTest):
search=['local'], options=['debug']
)
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], dns_config=dns_config
TEST_IMG, ['sleep', '999'], dns_config=dns_config
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -787,7 +816,7 @@ class ServiceTest(BaseAPIIntegrationTest):
start_period=3 * second, interval=int(second / 2),
)
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], healthcheck=hc
TEST_IMG, ['sleep', '999'], healthcheck=hc
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -804,7 +833,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.28')
def test_create_service_with_readonly(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], read_only=True
TEST_IMG, ['sleep', '999'], read_only=True
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -818,7 +847,7 @@ class ServiceTest(BaseAPIIntegrationTest):
@requires_api_version('1.28')
def test_create_service_with_stop_signal(self):
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], stop_signal='SIGINT'
TEST_IMG, ['sleep', '999'], stop_signal='SIGINT'
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -836,7 +865,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_privileges(self):
priv = docker.types.Privileges(selinux_disable=True)
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], privileges=priv
TEST_IMG, ['sleep', '999'], privileges=priv
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -992,7 +1021,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert labels['container.label'] == 'SampleLabel'
def test_update_service_with_defaults_update_config(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
update_config = docker.types.UpdateConfig(
parallelism=10, delay=5, failure_action='pause'
@ -1031,7 +1060,7 @@ class ServiceTest(BaseAPIIntegrationTest):
'dockerpytest_2', driver='overlay', ipam={'Driver': 'default'}
)
self.tmp_networks.append(net2['Id'])
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
svc_id = self.client.create_service(
@ -1070,7 +1099,7 @@ class ServiceTest(BaseAPIIntegrationTest):
]
def test_update_service_with_defaults_endpoint_spec(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
container_spec = docker.types.ContainerSpec(TEST_IMG, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
endpoint_spec = docker.types.EndpointSpec(ports={
@ -1134,7 +1163,7 @@ class ServiceTest(BaseAPIIntegrationTest):
start_period=3 * second, interval=int(second / 2),
)
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], healthcheck=hc
TEST_IMG, ['sleep', '999'], healthcheck=hc
)
task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name()
@ -1149,7 +1178,7 @@ class ServiceTest(BaseAPIIntegrationTest):
)
container_spec = docker.types.ContainerSpec(
BUSYBOX, ['sleep', '999'], healthcheck={}
TEST_IMG, ['sleep', '999'], healthcheck={}
)
task_tmpl = docker.types.TaskTemplate(container_spec)

View File

@ -250,5 +250,6 @@ class SwarmTest(BaseAPIIntegrationTest):
assert key_1['UnlockKey'] != key_2['UnlockKey']
@requires_api_version('1.30')
@pytest.mark.xfail(reason='Can fail if eth0 has multiple IP addresses')
def test_init_swarm_data_path_addr(self):
assert self.init_swarm(data_path_addr='eth0')

View File

@ -6,7 +6,7 @@ import docker
from .. import helpers
from docker.utils import kwargs_from_env
BUSYBOX = 'alpine:3.9.3' # FIXME: this should probably be renamed
TEST_IMG = 'alpine:3.10'
TEST_API_VERSION = os.environ.get('DOCKER_TEST_API_VERSION')
@ -108,7 +108,7 @@ class BaseAPIIntegrationTest(BaseIntegrationTest):
return container
def create_and_start(self, image=BUSYBOX, command='top', **kwargs):
def create_and_start(self, image=TEST_IMG, command='top', **kwargs):
container = self.client.create_container(
image=image, command=command, **kwargs)
self.tmp_containers.append(container)

View File

@ -7,7 +7,7 @@ import docker.errors
from docker.utils import kwargs_from_env
import pytest
from .base import BUSYBOX
from .base import TEST_IMG
@pytest.fixture(autouse=True, scope='session')
@ -15,15 +15,15 @@ def setup_test_session():
warnings.simplefilter('error')
c = docker.APIClient(version='auto', **kwargs_from_env())
try:
c.inspect_image(BUSYBOX)
c.inspect_image(TEST_IMG)
except docker.errors.NotFound:
print("\npulling {0}".format(BUSYBOX), file=sys.stderr)
for data in c.pull(BUSYBOX, stream=True, decode=True):
print("\npulling {0}".format(TEST_IMG), file=sys.stderr)
for data in c.pull(TEST_IMG, stream=True, decode=True):
status = data.get("status")
progress = data.get("progress")
detail = "{0} - {1}".format(status, progress)
print(detail, file=sys.stderr)
# Double make sure we now have busybox
c.inspect_image(BUSYBOX)
c.inspect_image(TEST_IMG)
c.close()

View File

@ -1,11 +1,11 @@
from docker.errors import APIError
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
import pytest
class ErrorsTest(BaseAPIIntegrationTest):
def test_api_error_parses_json(self):
container = self.client.create_container(BUSYBOX, ['sleep', '10'])
container = self.client.create_container(TEST_IMG, ['sleep', '10'])
self.client.start(container['Id'])
with pytest.raises(APIError) as cm:
self.client.remove_container(container['Id'])

View File

@ -4,7 +4,7 @@ import tempfile
import docker
import pytest
from .base import BaseIntegrationTest, BUSYBOX, TEST_API_VERSION
from .base import BaseIntegrationTest, TEST_IMG, TEST_API_VERSION
from ..helpers import random_name
@ -72,8 +72,8 @@ class ImageCollectionTest(BaseIntegrationTest):
def test_pull_with_tag(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.pull('alpine', tag='3.3')
assert 'alpine:3.3' in image.attrs['RepoTags']
image = client.images.pull('alpine', tag='3.10')
assert 'alpine:3.10' in image.attrs['RepoTags']
def test_pull_with_sha(self):
image_ref = (
@ -97,7 +97,7 @@ class ImageCollectionTest(BaseIntegrationTest):
def test_save_and_load(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.get(BUSYBOX)
image = client.images.get(TEST_IMG)
with tempfile.TemporaryFile() as f:
stream = image.save()
for chunk in stream:
@ -111,7 +111,7 @@ class ImageCollectionTest(BaseIntegrationTest):
def test_save_and_load_repo_name(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.get(BUSYBOX)
image = client.images.get(TEST_IMG)
additional_tag = random_name()
image.tag(additional_tag)
self.tmp_imgs.append(additional_tag)
@ -131,7 +131,7 @@ class ImageCollectionTest(BaseIntegrationTest):
def test_save_name_error(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.get(BUSYBOX)
image = client.images.get(TEST_IMG)
with pytest.raises(docker.errors.InvalidArgument):
image.save(named='sakuya/izayoi')

View File

@ -4,7 +4,7 @@ import random
import docker
import six
from .base import BaseAPIIntegrationTest, BUSYBOX
from .base import BaseAPIIntegrationTest, TEST_IMG
import pytest
@ -19,7 +19,7 @@ class TestRegressions(BaseAPIIntegrationTest):
def test_542_truncate_ids_client_side(self):
self.client.start(
self.client.create_container(BUSYBOX, ['true'])
self.client.create_container(TEST_IMG, ['true'])
)
result = self.client.containers(all=True, trunc=True)
assert len(result[0]['Id']) == 12
@ -30,12 +30,12 @@ class TestRegressions(BaseAPIIntegrationTest):
def test_649_handle_timeout_value_none(self):
self.client.timeout = None
ctnr = self.client.create_container(BUSYBOX, ['sleep', '2'])
ctnr = self.client.create_container(TEST_IMG, ['sleep', '2'])
self.client.start(ctnr)
self.client.stop(ctnr)
def test_715_handle_user_param_as_int_value(self):
ctnr = self.client.create_container(BUSYBOX, ['id', '-u'], user=1000)
ctnr = self.client.create_container(TEST_IMG, ['id', '-u'], user=1000)
self.client.start(ctnr)
self.client.wait(ctnr)
logs = self.client.logs(ctnr)
@ -47,7 +47,7 @@ class TestRegressions(BaseAPIIntegrationTest):
tcp_port, udp_port = random.sample(range(9999, 32000), 2)
ctnr = self.client.create_container(
BUSYBOX, ['sleep', '9999'], ports=[2000, (2000, 'udp')],
TEST_IMG, ['sleep', '9999'], ports=[2000, (2000, 'udp')],
host_config=self.client.create_host_config(
port_bindings={'2000/tcp': tcp_port, '2000/udp': udp_port}
)

View File

@ -530,11 +530,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
}
def test_get_all_credentials_with_empty_credhelper(self):
@ -548,11 +558,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'registry1.io': None,
}
@ -571,11 +591,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
}
def test_get_all_credentials_with_auths_entries(self):
@ -591,11 +621,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'registry1.io': {
'ServerAddress': 'registry1.io',
'Username': 'reimu',
@ -603,6 +643,62 @@ class CredstoreTest(unittest.TestCase):
},
}
def test_get_all_credentials_with_empty_auths_entry(self):
self.authconfig.add_auth('default.com', {})
assert self.authconfig.get_all_credentials() == {
'https://gensokyo.jp/v2': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
}
def test_get_all_credentials_credstore_overrides_auth_entry(self):
self.authconfig.add_auth('default.com', {
'Username': 'shouldnotsee',
'Password': 'thisentry',
'ServerAddress': 'https://default.com/v2',
})
assert self.authconfig.get_all_credentials() == {
'https://gensokyo.jp/v2': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
}
def test_get_all_credentials_helpers_override_default(self):
self.authconfig['credHelpers'] = {
'https://default.com/v2': 'truesecret',
@ -616,11 +712,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'reimu',
'Password': 'hakurei',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'reimu',
'Password': 'hakurei',
'ServerAddress': 'https://default.com/v2',
},
}
def test_get_all_credentials_3_sources(self):
@ -642,11 +748,21 @@ class CredstoreTest(unittest.TestCase):
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'gensokyo.jp': {
'Username': 'sakuya',
'Password': 'izayoi',
'ServerAddress': 'https://gensokyo.jp/v2',
},
'https://default.com/v2': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'default.com': {
'Username': 'user',
'Password': 'hunter2',
'ServerAddress': 'https://default.com/v2',
},
'registry1.io': {
'ServerAddress': 'registry1.io',
'Username': 'reimu',