PKh|mJXq' dockerctx.py""" A context manager for a docker container. """ from __future__ import division, print_function import socket from contextlib import contextmanager import uuid import logging import time import typing import docker __version__ = '2017.3.3' __all__ = ['new_container'] logger = logging.getLogger('dockerctx') @contextmanager def new_container( image_name, new_container_name=lambda: uuid.uuid4().hex, ports=None, ready_test=None): """Start a docker container, and kill+remove when done. :param new_container_name: The container name. By default, a UUID will be used. If a callable, the result must be a str. :type new_container_name: str | callable :param ports: The list of port mappings to configure on the docker container. The format is the same as that used in the `docker` package, e.g. `ports={'5432/tcp': 60011}` :type ports: typing.Dict[str, int] :param ready_test: A function to run to verify whether the container is "ready" (in some sense) before yielding the container back to the caller. An example of such a test is the `accepting_connections` function in the this module, which will try repeatedly to connect to a socket, until either successfuly, or a max timeout is reached. Use functools.partial to wrap up the args. :type ready_test: typing.Callable[[], bool] """ _ = new_container_name name = str(_() if callable(_) else _) client = docker.from_env() logger.info('New postgres container: %s', name) container = client.containers.run(image_name, name=name, detach=True, ports=ports) try: logger.info('Waiting for postgres to be ready') if ready_test and not ready_test(): raise ConnectionError( 'Container {} not ready fast enough.'.format(name) ) yield container finally: logger.info('Stopping container %s', name) # TODO: container.stop() does not seem to work here (e.g. for postgres) container.kill() logger.info('Removing container %s', name) container.remove() def accepting_connections(host, port, timeout=20): """Try to make a socket connection to `(host, port)` I'll try every 200 ms, and eventually give up after `timeout`. :type host: str :type port: int :type timeout: int :return: True for successful connection, False otherwise :rtype: bool """ t0 = time.time() while time.time() - t0 < timeout: try: # s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.create_connection((host, port)) logger.debug('Connected!') s.close() return True except socket.error as ex: logger.debug("Connection failed with errno %s: %s", ex.errno, ex.strerror) time.sleep(0.2) return False PK!H|&Ub"dockerctx-2017.3.3.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,Q034 /, (-JLR()*M ILR(4KM̫#DPK!HE %dockerctx-2017.3.3.dist-info/METADATAVQo6~ׯ+d6芩3РE`I%Pb#*IEݑl'yÐǻ}(GR^'oK` !߼z.9NiYpV4B(1lB*4 DtRkm:,u3Ͽjuy.sTT˟I*mR(jT8'ժGYbR V,eZX+Kda0 i _mǂ/n6{[航 rc[͞WWF4 EB::1]SO=ʜ׺t0 AX~.3#DcB]64h>I6?uK]qmQZl( -19^w>jY .#Lݐ!#rAdXCׂEYO^2RZggWH Zz\duA2EA]%vJpY瀒fBq/5H:a>XἋF*)dr{3$|vIJX>0,ʼn6y)D]GGr]QVSL*-7TprSZ{}^K26YF*L<-DL` -ldFӍpj^a._AQkH6zj^  TD9q3}欁ᴲi!1w  hYfFAalX.;$P *0SYerGEOV%Kd:.E?-f y10`]AY1'nL hPP(jݟRv,2CU ;?&2Bv~O`?oqmȆRQ,b4 =Qew?])nӰE" HlN^%o@ޘ 鞥ĺ's*6xp% @`u8s |i,iD31dt[hp NJ_JH3/{JS6.d4c!};|aH4$.+۲V&1IMCv󀤱6ʹ$8rSV $#w>J_bj"x)$A-^XHhjMRkR3a w6*SX, jQt `Pų}>/|IG<4yWCfz#ږR~4< -plTl~JT<Q= ^ss]<5lKAyftSI4@SmHx[&A[6 +b -Cx&.A{~W%1MC0 spIWجbvH;0GVu|>CmG)Y^a5OZpsPK!H "#dockerctx-2017.3.3.dist-info/RECORD}̱r0o ( PbiKM#\$XJ, UOmnK}c]?xIB3KZ|U՗Aw*(p#/X9\y^ 9KgDS_}1"֕գ3;Я;M!1$NbHP^=Ψkw' 绎\7/B_ُw 79NXPKh|mJXq' dockerctx.pyPK!H|&Ub" dockerctx-2017.3.3.dist-info/WHEELPK!HE %A dockerctx-2017.3.3.dist-info/METADATAPK!H "#!dockerctx-2017.3.3.dist-info/RECORDPK.,