From db4878118b02124100c669b39249f0bdeed2aad0 Mon Sep 17 00:00:00 2001 From: Milas Bowman Date: Tue, 21 Nov 2023 10:42:53 -0500 Subject: [PATCH] breaking: Python 3.12 compatibility & remove custom SSL adapter (#3185) Add support for Python 3.12. `match_hostname` is gone in Python 3.12 and has been unused by Python since 3.7. The custom SSL adapter allows passing a specific SSL version; this was first introduced a looong time ago to handle some SSL issues at the time. Closes #3176. --------- Signed-off-by: Hugo van Kemenade Signed-off-by: Milas Bowman Co-authored-by: Hugo van Kemenade --- .github/workflows/ci.yml | 12 ++- .github/workflows/release.yml | 6 +- Dockerfile | 2 +- Dockerfile-docs | 2 +- Jenkinsfile | 147 ----------------------------- docker/api/client.py | 5 +- docker/client.py | 2 - docker/tls.py | 29 +----- docker/transport/__init__.py | 1 - docker/transport/ssladapter.py | 62 ------------ docker/utils/utils.py | 9 +- setup.py | 1 + test-requirements.txt | 6 +- tests/Dockerfile | 2 +- tests/Dockerfile-dind-certs | 2 +- tests/unit/models_networks_test.py | 18 ++-- tests/unit/ssladapter_test.py | 71 -------------- tests/unit/utils_test.py | 15 ++- tox.ini | 2 +- 19 files changed, 41 insertions(+), 353 deletions(-) delete mode 100644 Jenkinsfile delete mode 100644 docker/transport/ssladapter.py delete mode 100644 tests/unit/ssladapter_test.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfbcc701e..977199ceb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,15 +4,16 @@ on: [push, pull_request] env: DOCKER_BUILDKIT: '1' + FORCE_COLOR: 1 jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: - python-version: '3.11' + python-version: '3.x' - run: pip install -U ruff==0.0.284 - name: Run ruff run: ruff docker tests @@ -21,14 +22,15 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + allow-prereleases: true - name: Install dependencies run: | python3 -m pip install --upgrade pip @@ -46,7 +48,7 @@ jobs: variant: [ "integration-dind", "integration-dind-ssl", "integration-dind-ssh" ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: make ${{ matrix.variant }} run: | docker logout diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7c6358a22..b8b1f57d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,11 +12,15 @@ on: type: boolean default: true +env: + DOCKER_BUILDKIT: '1' + FORCE_COLOR: 1 + jobs: publish: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: diff --git a/Dockerfile b/Dockerfile index 3476c6d03..293888d72 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION=3.10 +ARG PYTHON_VERSION=3.12 FROM python:${PYTHON_VERSION} diff --git a/Dockerfile-docs b/Dockerfile-docs index 11adbfe85..266b2099e 100644 --- a/Dockerfile-docs +++ b/Dockerfile-docs @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION=3.10 +ARG PYTHON_VERSION=3.12 FROM python:${PYTHON_VERSION} diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index f9431eac0..000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,147 +0,0 @@ -#!groovy - -def imageNameBase = "dockerpinata/docker-py" -def imageNamePy3 -def imageDindSSH -def images = [:] - -def buildImage = { name, buildargs, pyTag -> - img = docker.image(name) - try { - img.pull() - } catch (Exception exc) { - img = docker.build(name, buildargs) - img.push() - } - if (pyTag?.trim()) images[pyTag] = img.id -} - -def buildImages = { -> - wrappedNode(label: "amd64 && ubuntu-2004 && overlay2", cleanWorkspace: true) { - stage("build image") { - checkout(scm) - - imageNamePy3 = "${imageNameBase}:py3-${gitCommit()}" - imageDindSSH = "${imageNameBase}:sshdind-${gitCommit()}" - withDockerRegistry(credentialsId:'dockerbuildbot-index.docker.io') { - buildImage(imageDindSSH, "-f tests/Dockerfile-ssh-dind .", "") - buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.10 .", "py3.10") - } - } - } -} - -def getDockerVersions = { -> - def dockerVersions = ["19.03.12"] - wrappedNode(label: "amd64 && ubuntu-2004 && overlay2") { - def result = sh(script: """docker run --rm \\ - --entrypoint=python \\ - ${imageNamePy3} \\ - /src/scripts/versions.py - """, returnStdout: true - ) - dockerVersions = dockerVersions + result.trim().tokenize(' ') - } - return dockerVersions -} - -def getAPIVersion = { engineVersion -> - def versionMap = [ - '18.09': '1.39', - '19.03': '1.40' - ] - def result = versionMap[engineVersion.substring(0, 5)] - if (!result) { - return '1.40' - } - return result -} - -def runTests = { Map settings -> - def dockerVersion = settings.get("dockerVersion", null) - def pythonVersion = settings.get("pythonVersion", null) - def testImage = settings.get("testImage", null) - def apiVersion = getAPIVersion(dockerVersion) - - if (!testImage) { - throw new Exception("Need test image object, e.g.: `runTests(testImage: img)`") - } - if (!dockerVersion) { - throw new Exception("Need Docker version to test, e.g.: `runTests(dockerVersion: '19.03.12')`") - } - if (!pythonVersion) { - throw new Exception("Need Python version being tested, e.g.: `runTests(pythonVersion: 'py3.x')`") - } - - { -> - wrappedNode(label: "amd64 && ubuntu-2004 && overlay2", cleanWorkspace: true) { - stage("test python=${pythonVersion} / docker=${dockerVersion}") { - checkout(scm) - def dindContainerName = "dpy-dind-\$BUILD_NUMBER-\$EXECUTOR_NUMBER-${pythonVersion}-${dockerVersion}" - def testContainerName = "dpy-tests-\$BUILD_NUMBER-\$EXECUTOR_NUMBER-${pythonVersion}-${dockerVersion}" - def testNetwork = "dpy-testnet-\$BUILD_NUMBER-\$EXECUTOR_NUMBER-${pythonVersion}-${dockerVersion}" - withDockerRegistry(credentialsId:'dockerbuildbot-index.docker.io') { - try { - // unit tests - sh """docker run --rm \\ - -e 'DOCKER_TEST_API_VERSION=${apiVersion}' \\ - ${testImage} \\ - py.test -v -rxs --cov=docker tests/unit - """ - // integration tests - sh """docker network create ${testNetwork}""" - sh """docker run --rm -d --name ${dindContainerName} -v /tmp --privileged --network ${testNetwork} \\ - ${imageDindSSH} dockerd -H tcp://0.0.0.0:2375 - """ - sh """docker run --rm \\ - --name ${testContainerName} \\ - -e "DOCKER_HOST=tcp://${dindContainerName}:2375" \\ - -e 'DOCKER_TEST_API_VERSION=${apiVersion}' \\ - --network ${testNetwork} \\ - --volumes-from ${dindContainerName} \\ - -v $DOCKER_CONFIG/config.json:/root/.docker/config.json \\ - ${testImage} \\ - py.test -v -rxs --cov=docker tests/integration - """ - sh """docker stop ${dindContainerName}""" - // start DIND container with SSH - sh """docker run --rm -d --name ${dindContainerName} -v /tmp --privileged --network ${testNetwork} \\ - ${imageDindSSH} dockerd --experimental""" - sh """docker exec ${dindContainerName} sh -c /usr/sbin/sshd """ - // run SSH tests only - sh """docker run --rm \\ - --name ${testContainerName} \\ - -e "DOCKER_HOST=ssh://${dindContainerName}:22" \\ - -e 'DOCKER_TEST_API_VERSION=${apiVersion}' \\ - --network ${testNetwork} \\ - --volumes-from ${dindContainerName} \\ - -v $DOCKER_CONFIG/config.json:/root/.docker/config.json \\ - ${testImage} \\ - py.test -v -rxs --cov=docker tests/ssh - """ - } finally { - sh """ - docker stop ${dindContainerName} - docker network rm ${testNetwork} - """ - } - } - } - } - } -} - - -buildImages() - -def dockerVersions = getDockerVersions() - -def testMatrix = [failFast: false] - -for (imgKey in new ArrayList(images.keySet())) { - for (version in dockerVersions) { - testMatrix["${imgKey}_${version}"] = runTests([testImage: images[imgKey], dockerVersion: version, pythonVersion: imgKey]) - } -} - -parallel(testMatrix) diff --git a/docker/api/client.py b/docker/api/client.py index 20f8a2af7..499a7c785 100644 --- a/docker/api/client.py +++ b/docker/api/client.py @@ -4,6 +4,7 @@ from functools import partial import requests +import requests.adapters import requests.exceptions from .. import auth @@ -14,7 +15,7 @@ from ..errors import (DockerException, InvalidVersion, TLSParameterError, create_api_error_from_http_exception) from ..tls import TLSConfig -from ..transport import SSLHTTPAdapter, UnixHTTPAdapter +from ..transport import UnixHTTPAdapter from ..utils import check_resource, config, update_headers, utils from ..utils.json_stream import json_stream from ..utils.proxy import ProxyConfig @@ -183,7 +184,7 @@ def __init__(self, base_url=None, version=None, if isinstance(tls, TLSConfig): tls.configure_client(self) elif tls: - self._custom_adapter = SSLHTTPAdapter( + self._custom_adapter = requests.adapters.HTTPAdapter( pool_connections=num_pools) self.mount('https://', self._custom_adapter) self.base_url = base_url diff --git a/docker/client.py b/docker/client.py index 4dbd846f1..2910c1259 100644 --- a/docker/client.py +++ b/docker/client.py @@ -71,8 +71,6 @@ def from_env(cls, **kwargs): timeout (int): Default timeout for API calls, in seconds. max_pool_size (int): The maximum number of connections to save in the pool. - ssl_version (int): A valid `SSL version`_. - assert_hostname (bool): Verify the hostname of the server. environment (dict): The environment to read environment variables from. Default: the value of ``os.environ`` credstore_env (dict): Override environment variables when calling diff --git a/docker/tls.py b/docker/tls.py index a4dd00209..ad4966c90 100644 --- a/docker/tls.py +++ b/docker/tls.py @@ -1,8 +1,6 @@ import os -import ssl from . import errors -from .transport import SSLHTTPAdapter class TLSConfig: @@ -15,35 +13,18 @@ class TLSConfig: verify (bool or str): This can be a bool or a path to a CA cert file to verify against. If ``True``, verify using ca_cert; if ``False`` or not specified, do not verify. - ssl_version (int): A valid `SSL version`_. - assert_hostname (bool): Verify the hostname of the server. - - .. _`SSL version`: - https://docs.python.org/3.5/library/ssl.html#ssl.PROTOCOL_TLSv1 """ cert = None ca_cert = None verify = None - ssl_version = None - def __init__(self, client_cert=None, ca_cert=None, verify=None, - ssl_version=None, assert_hostname=None, - assert_fingerprint=None): + def __init__(self, client_cert=None, ca_cert=None, verify=None): # Argument compatibility/mapping with # https://docs.docker.com/engine/articles/https/ # This diverges from the Docker CLI in that users can specify 'tls' # here, but also disable any public/default CA pool verification by # leaving verify=False - self.assert_hostname = assert_hostname - self.assert_fingerprint = assert_fingerprint - - # If the user provides an SSL version, we should use their preference - if ssl_version: - self.ssl_version = ssl_version - else: - self.ssl_version = ssl.PROTOCOL_TLS_CLIENT - # "client_cert" must have both or neither cert/key files. In # either case, Alert the user when both are expected, but any are # missing. @@ -77,8 +58,6 @@ def configure_client(self, client): """ Configure a client with these TLS options. """ - client.ssl_version = self.ssl_version - if self.verify and self.ca_cert: client.verify = self.ca_cert else: @@ -86,9 +65,3 @@ def configure_client(self, client): if self.cert: client.cert = self.cert - - client.mount('https://', SSLHTTPAdapter( - ssl_version=self.ssl_version, - assert_hostname=self.assert_hostname, - assert_fingerprint=self.assert_fingerprint, - )) diff --git a/docker/transport/__init__.py b/docker/transport/__init__.py index 54492c11a..07bc7fd58 100644 --- a/docker/transport/__init__.py +++ b/docker/transport/__init__.py @@ -1,5 +1,4 @@ from .unixconn import UnixHTTPAdapter -from .ssladapter import SSLHTTPAdapter try: from .npipeconn import NpipeHTTPAdapter from .npipesocket import NpipeSocket diff --git a/docker/transport/ssladapter.py b/docker/transport/ssladapter.py deleted file mode 100644 index 69274bd1d..000000000 --- a/docker/transport/ssladapter.py +++ /dev/null @@ -1,62 +0,0 @@ -""" Resolves OpenSSL issues in some servers: - https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/ - https://github.com/kennethreitz/requests/pull/799 -""" -from packaging.version import Version -from requests.adapters import HTTPAdapter - -from docker.transport.basehttpadapter import BaseHTTPAdapter - -import urllib3 - - -PoolManager = urllib3.poolmanager.PoolManager - - -class SSLHTTPAdapter(BaseHTTPAdapter): - '''An HTTPS Transport Adapter that uses an arbitrary SSL version.''' - - __attrs__ = HTTPAdapter.__attrs__ + ['assert_fingerprint', - 'assert_hostname', - 'ssl_version'] - - def __init__(self, ssl_version=None, assert_hostname=None, - assert_fingerprint=None, **kwargs): - self.ssl_version = ssl_version - self.assert_hostname = assert_hostname - self.assert_fingerprint = assert_fingerprint - super().__init__(**kwargs) - - def init_poolmanager(self, connections, maxsize, block=False): - kwargs = { - 'num_pools': connections, - 'maxsize': maxsize, - 'block': block, - 'assert_hostname': self.assert_hostname, - 'assert_fingerprint': self.assert_fingerprint, - } - if self.ssl_version and self.can_override_ssl_version(): - kwargs['ssl_version'] = self.ssl_version - - self.poolmanager = PoolManager(**kwargs) - - def get_connection(self, *args, **kwargs): - """ - Ensure assert_hostname is set correctly on our pool - - We already take care of a normal poolmanager via init_poolmanager - - But we still need to take care of when there is a proxy poolmanager - """ - conn = super().get_connection(*args, **kwargs) - if conn.assert_hostname != self.assert_hostname: - conn.assert_hostname = self.assert_hostname - return conn - - def can_override_ssl_version(self): - urllib_ver = urllib3.__version__.split('-')[0] - if urllib_ver is None: - return False - if urllib_ver == 'dev': - return True - return Version(urllib_ver) > Version('1.5') diff --git a/docker/utils/utils.py b/docker/utils/utils.py index 0f28afb11..759ddd2f1 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -341,7 +341,7 @@ def parse_devices(devices): return device_list -def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None): +def kwargs_from_env(environment=None): if not environment: environment = os.environ host = environment.get('DOCKER_HOST') @@ -369,18 +369,11 @@ def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None): if not cert_path: cert_path = os.path.join(os.path.expanduser('~'), '.docker') - if not tls_verify and assert_hostname is None: - # assert_hostname is a subset of TLS verification, - # so if it's not set already then set it to false. - assert_hostname = False - params['tls'] = TLSConfig( client_cert=(os.path.join(cert_path, 'cert.pem'), os.path.join(cert_path, 'key.pem')), ca_cert=os.path.join(cert_path, 'ca.pem'), verify=tls_verify, - ssl_version=ssl_version, - assert_hostname=assert_hostname, ) return params diff --git a/setup.py b/setup.py index 79bf3bdb6..d63cbe0a1 100644 --- a/setup.py +++ b/setup.py @@ -74,6 +74,7 @@ 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Software Development', 'Topic :: Utilities', 'License :: OSI Approved :: Apache Software License', diff --git a/test-requirements.txt b/test-requirements.txt index 951b3be9f..031d0acf0 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,6 +1,6 @@ setuptools==65.5.1 -coverage==6.4.2 +coverage==7.2.7 ruff==0.0.284 -pytest==7.1.2 -pytest-cov==3.0.0 +pytest==7.4.2 +pytest-cov==4.1.0 pytest-timeout==2.1.0 diff --git a/tests/Dockerfile b/tests/Dockerfile index 366abe23b..d7c14b6cc 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION=3.10 +ARG PYTHON_VERSION=3.12 FROM python:${PYTHON_VERSION} diff --git a/tests/Dockerfile-dind-certs b/tests/Dockerfile-dind-certs index 288a340ab..7b819eb15 100644 --- a/tests/Dockerfile-dind-certs +++ b/tests/Dockerfile-dind-certs @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION=3.10 +ARG PYTHON_VERSION=3.12 FROM python:${PYTHON_VERSION} RUN mkdir /tmp/certs diff --git a/tests/unit/models_networks_test.py b/tests/unit/models_networks_test.py index 58c9fce66..f10e1e3e3 100644 --- a/tests/unit/models_networks_test.py +++ b/tests/unit/models_networks_test.py @@ -10,8 +10,8 @@ def test_create(self): client = make_fake_client() network = client.networks.create("foobar", labels={'foo': 'bar'}) assert network.id == FAKE_NETWORK_ID - assert client.api.inspect_network.called_once_with(FAKE_NETWORK_ID) - assert client.api.create_network.called_once_with( + client.api.inspect_network.assert_called_once_with(FAKE_NETWORK_ID) + client.api.create_network.assert_called_once_with( "foobar", labels={'foo': 'bar'} ) @@ -20,21 +20,21 @@ def test_get(self): client = make_fake_client() network = client.networks.get(FAKE_NETWORK_ID) assert network.id == FAKE_NETWORK_ID - assert client.api.inspect_network.called_once_with(FAKE_NETWORK_ID) + client.api.inspect_network.assert_called_once_with(FAKE_NETWORK_ID) def test_list(self): client = make_fake_client() networks = client.networks.list() assert networks[0].id == FAKE_NETWORK_ID - assert client.api.networks.called_once_with() + client.api.networks.assert_called_once_with() client = make_fake_client() client.networks.list(ids=["abc"]) - assert client.api.networks.called_once_with(ids=["abc"]) + client.api.networks.assert_called_once_with(ids=["abc"]) client = make_fake_client() client.networks.list(names=["foobar"]) - assert client.api.networks.called_once_with(names=["foobar"]) + client.api.networks.assert_called_once_with(names=["foobar"]) class NetworkTest(unittest.TestCase): @@ -43,7 +43,7 @@ def test_connect(self): client = make_fake_client() network = client.networks.get(FAKE_NETWORK_ID) network.connect(FAKE_CONTAINER_ID) - assert client.api.connect_container_to_network.called_once_with( + client.api.connect_container_to_network.assert_called_once_with( FAKE_CONTAINER_ID, FAKE_NETWORK_ID ) @@ -52,7 +52,7 @@ def test_disconnect(self): client = make_fake_client() network = client.networks.get(FAKE_NETWORK_ID) network.disconnect(FAKE_CONTAINER_ID) - assert client.api.disconnect_container_from_network.called_once_with( + client.api.disconnect_container_from_network.assert_called_once_with( FAKE_CONTAINER_ID, FAKE_NETWORK_ID ) @@ -61,4 +61,4 @@ def test_remove(self): client = make_fake_client() network = client.networks.get(FAKE_NETWORK_ID) network.remove() - assert client.api.remove_network.called_once_with(FAKE_NETWORK_ID) + client.api.remove_network.assert_called_once_with(FAKE_NETWORK_ID) diff --git a/tests/unit/ssladapter_test.py b/tests/unit/ssladapter_test.py deleted file mode 100644 index d3f2407c3..000000000 --- a/tests/unit/ssladapter_test.py +++ /dev/null @@ -1,71 +0,0 @@ -import unittest -from ssl import match_hostname, CertificateError - -import pytest -from docker.transport import ssladapter - -try: - from ssl import OP_NO_SSLv3, OP_NO_SSLv2, OP_NO_TLSv1 -except ImportError: - OP_NO_SSLv2 = 0x1000000 - OP_NO_SSLv3 = 0x2000000 - OP_NO_TLSv1 = 0x4000000 - - -class SSLAdapterTest(unittest.TestCase): - def test_only_uses_tls(self): - ssl_context = ssladapter.urllib3.util.ssl_.create_urllib3_context() - - assert ssl_context.options & OP_NO_SSLv3 - # if OpenSSL is compiled without SSL2 support, OP_NO_SSLv2 will be 0 - assert not bool(OP_NO_SSLv2) or ssl_context.options & OP_NO_SSLv2 - assert not ssl_context.options & OP_NO_TLSv1 - - -class MatchHostnameTest(unittest.TestCase): - cert = { - 'issuer': ( - (('countryName', 'US'),), - (('stateOrProvinceName', 'California'),), - (('localityName', 'San Francisco'),), - (('organizationName', 'Docker Inc'),), - (('organizationalUnitName', 'Docker-Python'),), - (('commonName', 'localhost'),), - (('emailAddress', 'info@docker.com'),) - ), - 'notAfter': 'Mar 25 23:08:23 2030 GMT', - 'notBefore': 'Mar 25 23:08:23 2016 GMT', - 'serialNumber': 'BD5F894C839C548F', - 'subject': ( - (('countryName', 'US'),), - (('stateOrProvinceName', 'California'),), - (('localityName', 'San Francisco'),), - (('organizationName', 'Docker Inc'),), - (('organizationalUnitName', 'Docker-Python'),), - (('commonName', 'localhost'),), - (('emailAddress', 'info@docker.com'),) - ), - 'subjectAltName': ( - ('DNS', 'localhost'), - ('DNS', '*.gensokyo.jp'), - ('IP Address', '127.0.0.1'), - ), - 'version': 3 - } - - def test_match_ip_address_success(self): - assert match_hostname(self.cert, '127.0.0.1') is None - - def test_match_localhost_success(self): - assert match_hostname(self.cert, 'localhost') is None - - def test_match_dns_success(self): - assert match_hostname(self.cert, 'touhou.gensokyo.jp') is None - - def test_match_ip_address_failure(self): - with pytest.raises(CertificateError): - match_hostname(self.cert, '192.168.0.25') - - def test_match_dns_failure(self): - with pytest.raises(CertificateError): - match_hostname(self.cert, 'foobar.co.uk') diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py index b47cb0c62..de79e3037 100644 --- a/tests/unit/utils_test.py +++ b/tests/unit/utils_test.py @@ -75,13 +75,12 @@ def test_kwargs_from_env_tls(self): os.environ.update(DOCKER_HOST='tcp://192.168.59.103:2376', DOCKER_CERT_PATH=TEST_CERT_DIR, DOCKER_TLS_VERIFY='1') - kwargs = kwargs_from_env(assert_hostname=False) + kwargs = kwargs_from_env() assert 'tcp://192.168.59.103:2376' == kwargs['base_url'] assert 'ca.pem' in kwargs['tls'].ca_cert assert 'cert.pem' in kwargs['tls'].cert[0] assert 'key.pem' in kwargs['tls'].cert[1] - assert kwargs['tls'].assert_hostname is False - assert kwargs['tls'].verify + assert kwargs['tls'].verify is True parsed_host = parse_host(kwargs['base_url'], IS_WINDOWS_PLATFORM, True) kwargs['version'] = DEFAULT_DOCKER_API_VERSION @@ -97,12 +96,11 @@ def test_kwargs_from_env_tls_verify_false(self): os.environ.update(DOCKER_HOST='tcp://192.168.59.103:2376', DOCKER_CERT_PATH=TEST_CERT_DIR, DOCKER_TLS_VERIFY='') - kwargs = kwargs_from_env(assert_hostname=True) + kwargs = kwargs_from_env() assert 'tcp://192.168.59.103:2376' == kwargs['base_url'] assert 'ca.pem' in kwargs['tls'].ca_cert assert 'cert.pem' in kwargs['tls'].cert[0] assert 'key.pem' in kwargs['tls'].cert[1] - assert kwargs['tls'].assert_hostname is True assert kwargs['tls'].verify is False parsed_host = parse_host(kwargs['base_url'], IS_WINDOWS_PLATFORM, True) kwargs['version'] = DEFAULT_DOCKER_API_VERSION @@ -123,12 +121,12 @@ def test_kwargs_from_env_tls_verify_false_no_cert(self): HOME=temp_dir, DOCKER_TLS_VERIFY='') os.environ.pop('DOCKER_CERT_PATH', None) - kwargs = kwargs_from_env(assert_hostname=True) + kwargs = kwargs_from_env() assert 'tcp://192.168.59.103:2376' == kwargs['base_url'] def test_kwargs_from_env_no_cert_path(self): + temp_dir = tempfile.mkdtemp() try: - temp_dir = tempfile.mkdtemp() cert_dir = os.path.join(temp_dir, '.docker') shutil.copytree(TEST_CERT_DIR, cert_dir) @@ -142,8 +140,7 @@ def test_kwargs_from_env_no_cert_path(self): assert cert_dir in kwargs['tls'].cert[0] assert cert_dir in kwargs['tls'].cert[1] finally: - if temp_dir: - shutil.rmtree(temp_dir) + shutil.rmtree(temp_dir) def test_kwargs_from_env_alternate_env(self): # Values in os.environ are entirely ignored if an alternate is diff --git a/tox.ini b/tox.ini index 2028dd395..03467aea2 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{37,38,39,310,311}, ruff +envlist = py{37,38,39,310,311,312}, ruff skipsdist=True [testenv]