mirror of
https://github.com/ansible-collections/community.docker.git
synced 2025-12-16 11:58:43 +00:00
vendored Docker SDK for Python code: update to latest version (#619)
* socket: fix for errors on pipe close in Windows (https://github.com/docker/docker-py/pull/3099) Need to return data, not size. By returning an empty string, EOF will be detected properly since `len()` will be `0`. Fixes https://github.com/docker/docker-py/issues/3098. Cherry-picked fromf84623225eCo-authored-by: Milas Bowman <milas.bowman@docker.com> * socket: use poll() instead of select() except on Windows (https://github.com/docker/docker-py/pull/2865) Fixes https://github.com/docker/docker-py/issues/2278, which was originally addressed in https://github.com/docker/docker-py/pull/2279, but was not properly merged. Additionally it did not address the problem of poll not existing on Windows. This patch falls back on the more limited select method if host system is Windows. Cherry-picked froma02ba74333Co-authored-by: Tyler Westland <tylerofthewest@gmail.com> * api: respect timeouts on Windows named pipes (https://github.com/docker/docker-py/pull/3112) Cherry-picked from9cadad009eCo-authored-by: Imogen <59090860+ImogenBits@users.noreply.github.com> * Add URL to changelog. * api: avoid socket timeouts when executing commands (https://github.com/docker/docker-py/pull/3125) Only listen to read events when polling a socket in order to avoid incorrectly trying to read from a socket that is not actually ready. Cherry-picked fromc5e582c413Co-authored-by: Loïc Leyendecker <loic.leyendecker@gmail.com> --------- Co-authored-by: Milas Bowman <milas.bowman@docker.com> Co-authored-by: Tyler Westland <tylerofthewest@gmail.com> Co-authored-by: Imogen <59090860+ImogenBits@users.noreply.github.com> Co-authored-by: Loïc Leyendecker <loic.leyendecker@gmail.com>
This commit is contained in:
parent
2259246f4f
commit
1660bf4104
4
changelogs/fragments/docker-py.yml
Normal file
4
changelogs/fragments/docker-py.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
bugfixes:
|
||||||
|
- "vendored Docker SDK for Python code - fix for errors on pipe close in Windows (https://github.com/ansible-collections/community.docker/pull/619)."
|
||||||
|
- "vendored Docker SDK for Python code - use ``poll()`` instead of ``select()`` except on Windows (https://github.com/ansible-collections/community.docker/pull/619)."
|
||||||
|
- "vendored Docker SDK for Python code - respect timeouts on Windows named pipes (https://github.com/ansible-collections/community.docker/pull/619)."
|
||||||
@ -21,6 +21,9 @@ PYWIN32_IMPORT_ERROR = None
|
|||||||
try:
|
try:
|
||||||
import win32file
|
import win32file
|
||||||
import win32pipe
|
import win32pipe
|
||||||
|
import pywintypes
|
||||||
|
import win32event
|
||||||
|
import win32api
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PYWIN32_IMPORT_ERROR = traceback.format_exc()
|
PYWIN32_IMPORT_ERROR = traceback.format_exc()
|
||||||
|
|
||||||
@ -74,7 +77,9 @@ class NpipeSocket(object):
|
|||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
win32file.OPEN_EXISTING,
|
win32file.OPEN_EXISTING,
|
||||||
cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT,
|
(cSECURITY_ANONYMOUS
|
||||||
|
| cSECURITY_SQOS_PRESENT
|
||||||
|
| win32file.FILE_FLAG_OVERLAPPED),
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
except win32pipe.error as e:
|
except win32pipe.error as e:
|
||||||
@ -154,11 +159,22 @@ class NpipeSocket(object):
|
|||||||
if not isinstance(buf, memoryview):
|
if not isinstance(buf, memoryview):
|
||||||
readbuf = memoryview(buf)
|
readbuf = memoryview(buf)
|
||||||
|
|
||||||
err, data = win32file.ReadFile(
|
event = win32event.CreateEvent(None, True, True, None)
|
||||||
self._handle,
|
try:
|
||||||
readbuf[:nbytes] if nbytes else readbuf
|
overlapped = pywintypes.OVERLAPPED()
|
||||||
)
|
overlapped.hEvent = event
|
||||||
return len(data)
|
err, data = win32file.ReadFile(
|
||||||
|
self._handle,
|
||||||
|
readbuf[:nbytes] if nbytes else readbuf,
|
||||||
|
overlapped
|
||||||
|
)
|
||||||
|
wait_result = win32event.WaitForSingleObject(event, self._timeout)
|
||||||
|
if wait_result == win32event.WAIT_TIMEOUT:
|
||||||
|
win32file.CancelIo(self._handle)
|
||||||
|
raise TimeoutError
|
||||||
|
return win32file.GetOverlappedResult(self._handle, overlapped, 0)
|
||||||
|
finally:
|
||||||
|
win32api.CloseHandle(event)
|
||||||
|
|
||||||
def _recv_into_py2(self, buf, nbytes):
|
def _recv_into_py2(self, buf, nbytes):
|
||||||
err, data = win32file.ReadFile(self._handle, nbytes or len(buf))
|
err, data = win32file.ReadFile(self._handle, nbytes or len(buf))
|
||||||
@ -168,8 +184,18 @@ class NpipeSocket(object):
|
|||||||
|
|
||||||
@check_closed
|
@check_closed
|
||||||
def send(self, string, flags=0):
|
def send(self, string, flags=0):
|
||||||
err, nbytes = win32file.WriteFile(self._handle, string)
|
event = win32event.CreateEvent(None, True, True, None)
|
||||||
return nbytes
|
try:
|
||||||
|
overlapped = pywintypes.OVERLAPPED()
|
||||||
|
overlapped.hEvent = event
|
||||||
|
win32file.WriteFile(self._handle, string, overlapped)
|
||||||
|
wait_result = win32event.WaitForSingleObject(event, self._timeout)
|
||||||
|
if wait_result == win32event.WAIT_TIMEOUT:
|
||||||
|
win32file.CancelIo(self._handle)
|
||||||
|
raise TimeoutError
|
||||||
|
return win32file.GetOverlappedResult(self._handle, overlapped, 0)
|
||||||
|
finally:
|
||||||
|
win32api.CloseHandle(event)
|
||||||
|
|
||||||
@check_closed
|
@check_closed
|
||||||
def sendall(self, string, flags=0):
|
def sendall(self, string, flags=0):
|
||||||
@ -188,15 +214,12 @@ class NpipeSocket(object):
|
|||||||
def settimeout(self, value):
|
def settimeout(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
# Blocking mode
|
# Blocking mode
|
||||||
self._timeout = win32pipe.NMPWAIT_WAIT_FOREVER
|
self._timeout = win32event.INFINITE
|
||||||
elif not isinstance(value, (float, int)) or value < 0:
|
elif not isinstance(value, (float, int)) or value < 0:
|
||||||
raise ValueError('Timeout value out of range')
|
raise ValueError('Timeout value out of range')
|
||||||
elif value == 0:
|
|
||||||
# Non-blocking mode
|
|
||||||
self._timeout = win32pipe.NMPWAIT_NO_WAIT
|
|
||||||
else:
|
else:
|
||||||
# Timeout mode - Value converted to milliseconds
|
# Timeout mode - Value converted to milliseconds
|
||||||
self._timeout = value * 1000
|
self._timeout = int(value * 1000)
|
||||||
|
|
||||||
def gettimeout(self):
|
def gettimeout(self):
|
||||||
return self._timeout
|
return self._timeout
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import os
|
|||||||
import select
|
import select
|
||||||
import socket as pysocket
|
import socket as pysocket
|
||||||
import struct
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
from ansible.module_utils.six import PY3, binary_type
|
from ansible.module_utils.six import PY3, binary_type
|
||||||
|
|
||||||
@ -42,7 +43,13 @@ def read(socket, n=4096):
|
|||||||
recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
|
recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
|
||||||
|
|
||||||
if PY3 and not isinstance(socket, NpipeSocket):
|
if PY3 and not isinstance(socket, NpipeSocket):
|
||||||
select.select([socket], [], [])
|
if sys.platform == 'win32':
|
||||||
|
# Limited to 1024
|
||||||
|
select.select([socket], [], [])
|
||||||
|
else:
|
||||||
|
poll = select.poll()
|
||||||
|
poll.register(socket, select.POLLIN | select.POLLPRI)
|
||||||
|
poll.poll()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if hasattr(socket, 'recv'):
|
if hasattr(socket, 'recv'):
|
||||||
@ -60,7 +67,7 @@ def read(socket, n=4096):
|
|||||||
if is_pipe_ended:
|
if is_pipe_ended:
|
||||||
# npipes don't support duplex sockets, so we interpret
|
# npipes don't support duplex sockets, so we interpret
|
||||||
# a PIPE_ENDED error as a close operation (0-length read).
|
# a PIPE_ENDED error as a close operation (0-length read).
|
||||||
return 0
|
return ''
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user