Make compatible with requests 2.29.0 and urllib3 2.0 (#613)

* Make compatible with requests 2.29.0.

* This fix should also work with urllib3 2.0 according to urllib3 maintainer.

* Add changelog fragment.

* We still need the constraint for CI until Docker SDK for Python has a new release with a fix.

* Make modifications to response_class as small as possible.

* Revert "We still need the constraint for CI until Docker SDK for Python has a new release with a fix."

This reverts commit 698d544a1e08308e8bf8b4e56ab78c5079f9a17b.

* The pip coming with the ansible-core 2.11 alpine3 image seems to be too old.
This commit is contained in:
Felix Fontein 2023-05-05 22:09:02 +02:00 committed by GitHub
parent 5a26eee6d4
commit 39f2e9b9c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 36 additions and 38 deletions

View File

@ -101,6 +101,10 @@ jobs:
- '' - ''
target: target:
- '' - ''
extra-constraints:
# Specifying this other than '' likely destroys change detection, but at least it will make
# CI pass when necessary...
- ''
exclude: exclude:
- ansible: '' - ansible: ''
include: include:
@ -117,6 +121,7 @@ jobs:
docker: alpine3 docker: alpine3
python: '' python: ''
target: azp/4/ target: azp/4/
extra-constraints: urllib3 < 2.0.0
- ansible: '2.11' - ansible: '2.11'
docker: alpine3 docker: alpine3
python: '' python: ''
@ -144,6 +149,9 @@ jobs:
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto
; ;
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git ../../community/general git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git ../../community/general
${{ matrix.extra-constraints && format('; echo ''{0}'' >> tests/utils/constraints.txt', matrix.extra-constraints) || '' }}
;
cat tests/utils/constraints.txt
pull-request-change-detection: 'true' pull-request-change-detection: 'true'
target: ${{ matrix.target }} target: ${{ matrix.target }}
target-python-version: ${{ matrix.python }} target-python-version: ${{ matrix.python }}

View File

@ -26,7 +26,7 @@ Some modules and plugins require Docker CLI, or other external, programs. Some r
Installing the Docker SDK for Python also installs the requirements for the modules and plugins that use `requests`. If you want to directly install the Python libraries instead of the SDK, you need the following ones: Installing the Docker SDK for Python also installs the requirements for the modules and plugins that use `requests`. If you want to directly install the Python libraries instead of the SDK, you need the following ones:
- [requests](https://pypi.org/project/requests/) (versions before 2.29.0); - [requests](https://pypi.org/project/requests/);
- [pywin32](https://pypi.org/project/pywin32/) when using named pipes on Windows with the Windows 32 API; - [pywin32](https://pypi.org/project/pywin32/) when using named pipes on Windows with the Windows 32 API;
- [paramiko](https://pypi.org/project/paramiko/) when using SSH to connect to the Docker daemon with `use_ssh_client=false`; - [paramiko](https://pypi.org/project/paramiko/) when using SSH to connect to the Docker daemon with `use_ssh_client=false`;
- [pyOpenSSL](https://pypi.org/project/pyOpenSSL/) when using TLS to connect to the Docker daemon; - [pyOpenSSL](https://pypi.org/project/pyOpenSSL/) when using TLS to connect to the Docker daemon;

View File

@ -0,0 +1,2 @@
bugfixes:
- "Make vendored Docker SDK for Python code compatible with requests 2.29.0 and urllib3 2.0 (https://github.com/ansible-collections/community.docker/pull/613)."

View File

@ -3,8 +3,8 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
docker docker
urllib3 < 2.0 # TODO see https://github.com/ansible-collections/community.docker/issues/611 urllib3
requests < 2.29 # TODO see https://github.com/ansible-collections/community.docker/issues/611 requests
paramiko paramiko
# We assume that EEs are not based on Windows, and have Python >= 3.5. # We assume that EEs are not based on Windows, and have Python >= 3.5.

View File

@ -289,7 +289,7 @@ notes:
communicate with the Docker daemon. It uses code derived from the Docker SDK or Python that is included in this communicate with the Docker daemon. It uses code derived from the Docker SDK or Python that is included in this
collection. collection.
requirements: requirements:
- requests < 2.29.0 (see U(https://github.com/ansible-collections/community.docker/issues/611)) - requests
- pywin32 (when using named pipes on Windows 32) - pywin32 (when using named pipes on Windows 32)
- paramiko (when using SSH with I(use_ssh_client=false)) - paramiko (when using SSH with I(use_ssh_client=false))
- pyOpenSSL (when using TLS) - pyOpenSSL (when using TLS)

View File

@ -42,15 +42,20 @@ except ImportError:
try: try:
from requests.packages import urllib3 from requests.packages import urllib3
from requests.packages.urllib3 import connection as urllib3_connection # pylint: disable=unused-import
except ImportError: except ImportError:
try: try:
import urllib3 import urllib3
from urllib3 import connection as urllib3_connection # pylint: disable=unused-import
except ImportError: except ImportError:
URLLIB3_IMPORT_ERROR = traceback.format_exc() URLLIB3_IMPORT_ERROR = traceback.format_exc()
class _HTTPConnectionPool(object): class _HTTPConnectionPool(object):
pass pass
class _HTTPConnection(object):
pass
class FakeURLLIB3(object): class FakeURLLIB3(object):
def __init__(self): def __init__(self):
self._collections = self self._collections = self
@ -63,7 +68,12 @@ except ImportError:
self.match_hostname = object() self.match_hostname = object()
self.HTTPConnectionPool = _HTTPConnectionPool self.HTTPConnectionPool = _HTTPConnectionPool
class FakeURLLIB3Connection(object):
def __init__(self):
self.HTTPConnection = _HTTPConnection
urllib3 = FakeURLLIB3() urllib3 = FakeURLLIB3()
urllib3_connection = FakeURLLIB3Connection()
# Monkey-patching match_hostname with a version that supports # Monkey-patching match_hostname with a version that supports

View File

@ -10,24 +10,18 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from ansible.module_utils.six import PY3
from ansible.module_utils.six.moves.queue import Empty from ansible.module_utils.six.moves.queue import Empty
from .. import constants from .. import constants
from .._import_helper import HTTPAdapter, urllib3 from .._import_helper import HTTPAdapter, urllib3, urllib3_connection
from .basehttpadapter import BaseHTTPAdapter from .basehttpadapter import BaseHTTPAdapter
from .npipesocket import NpipeSocket from .npipesocket import NpipeSocket
if PY3:
import http.client as httplib
else:
import httplib
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class NpipeHTTPConnection(httplib.HTTPConnection, object): class NpipeHTTPConnection(urllib3_connection.HTTPConnection, object):
def __init__(self, npipe_path, timeout=60): def __init__(self, npipe_path, timeout=60):
super(NpipeHTTPConnection, self).__init__( super(NpipeHTTPConnection, self).__init__(
'localhost', timeout=timeout 'localhost', timeout=timeout

View File

@ -24,12 +24,7 @@ from ansible.module_utils.six.moves.urllib_parse import urlparse
from .basehttpadapter import BaseHTTPAdapter from .basehttpadapter import BaseHTTPAdapter
from .. import constants from .. import constants
if PY3: from .._import_helper import HTTPAdapter, urllib3, urllib3_connection
import http.client as httplib
else:
import httplib
from .._import_helper import HTTPAdapter, urllib3
PARAMIKO_IMPORT_ERROR = None PARAMIKO_IMPORT_ERROR = None
try: try:
@ -120,7 +115,7 @@ class SSHSocket(socket.socket):
self.proc.terminate() self.proc.terminate()
class SSHConnection(httplib.HTTPConnection, object): class SSHConnection(urllib3_connection.HTTPConnection, object):
def __init__(self, ssh_transport=None, timeout=60, host=None): def __init__(self, ssh_transport=None, timeout=60, host=None):
super(SSHConnection, self).__init__( super(SSHConnection, self).__init__(
'localhost', timeout=timeout 'localhost', timeout=timeout

View File

@ -13,29 +13,17 @@ __metaclass__ = type
import socket import socket
from ansible.module_utils.six import PY2 from ansible.module_utils.six import PY2
from ansible.module_utils.six.moves import http_client as httplib
from .basehttpadapter import BaseHTTPAdapter from .basehttpadapter import BaseHTTPAdapter
from .. import constants from .. import constants
from .._import_helper import HTTPAdapter, urllib3 from .._import_helper import HTTPAdapter, urllib3, urllib3_connection
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class UnixHTTPResponse(httplib.HTTPResponse, object): class UnixHTTPConnection(urllib3_connection.HTTPConnection, object):
def __init__(self, sock, *args, **kwargs):
disable_buffering = kwargs.pop('disable_buffering', False)
if PY2:
# FIXME: We may need to disable buffering on Py3 as well,
# but there's no clear way to do it at the moment. See:
# https://github.com/docker/docker-py/issues/1799
kwargs['buffering'] = not disable_buffering
super(UnixHTTPResponse, self).__init__(sock, *args, **kwargs)
class UnixHTTPConnection(httplib.HTTPConnection, object):
def __init__(self, base_url, unix_socket, timeout=60): def __init__(self, base_url, unix_socket, timeout=60):
super(UnixHTTPConnection, self).__init__( super(UnixHTTPConnection, self).__init__(
@ -58,10 +46,13 @@ class UnixHTTPConnection(httplib.HTTPConnection, object):
self.disable_buffering = True self.disable_buffering = True
def response_class(self, sock, *args, **kwargs): def response_class(self, sock, *args, **kwargs):
if self.disable_buffering: if PY2:
kwargs['disable_buffering'] = True # FIXME: We may need to disable buffering on Py3 as well,
# but there's no clear way to do it at the moment. See:
# https://github.com/docker/docker-py/issues/1799
kwargs['buffering'] = not self.disable_buffering
return UnixHTTPResponse(sock, *args, **kwargs) return super(UnixHTTPConnection, self).response_class(sock, *args, **kwargs)
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool): class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):

View File

@ -10,13 +10,11 @@ coverage >= 4.5.4, < 5.0.0 ; python_version > '3.7' # coverage had a bug in < 4.
cryptography >= 1.3.0, < 2.2 ; python_version < '2.7' # cryptography 2.2 drops support for python 2.6 cryptography >= 1.3.0, < 2.2 ; python_version < '2.7' # cryptography 2.2 drops support for python 2.6
cryptography >= 1.3.0, < 3.4 ; python_version < '3.6' # cryptography 3.4 drops support for python 2.7 cryptography >= 1.3.0, < 3.4 ; python_version < '3.6' # cryptography 3.4 drops support for python 2.7
urllib3 < 1.24 ; python_version < '2.7' # urllib3 1.24 and later require python 2.7 or later urllib3 < 1.24 ; python_version < '2.7' # urllib3 1.24 and later require python 2.7 or later
urllib3 < 2.0.0 # TODO see https://github.com/ansible-collections/community.docker/issues/611
wheel < 0.30.0 ; python_version < '2.7' # wheel 0.30.0 and later require python 2.7 or later wheel < 0.30.0 ; python_version < '2.7' # wheel 0.30.0 and later require python 2.7 or later
paramiko < 2.4.0 ; python_version < '2.7' # paramiko 2.4.0 drops support for python 2.6 paramiko < 2.4.0 ; python_version < '2.7' # paramiko 2.4.0 drops support for python 2.6
paramiko < 3.0.0 ; python_version < '3.7' # paramiko 3.0.0 forces installation of a too new cryptography paramiko < 3.0.0 ; python_version < '3.7' # paramiko 3.0.0 forces installation of a too new cryptography
requests < 2.20.0 ; python_version < '2.7' # requests 2.20.0 drops support for python 2.6 requests < 2.20.0 ; python_version < '2.7' # requests 2.20.0 drops support for python 2.6
requests < 2.28 ; python_version < '3.7' # requests 2.28.0 drops support for python < 3.7 requests < 2.28 ; python_version < '3.7' # requests 2.28.0 drops support for python < 3.7
requests < 2.29 # TODO see https://github.com/ansible-collections/community.docker/issues/611
virtualenv < 16.0.0 ; python_version < '2.7' # virtualenv 16.0.0 and later require python 2.7 or later virtualenv < 16.0.0 ; python_version < '2.7' # virtualenv 16.0.0 and later require python 2.7 or later
pyopenssl < 18.0.0 ; python_version < '2.7' # pyOpenSSL 18.0.0 and later require python 2.7 or later pyopenssl < 18.0.0 ; python_version < '2.7' # pyOpenSSL 18.0.0 and later require python 2.7 or later
setuptools < 45 ; python_version <= '2.7' # setuptools 45 and later require python 3.5 or later setuptools < 45 ; python_version <= '2.7' # setuptools 45 and later require python 3.5 or later