def setUp(self): """ Test set up: * Build, if necessary, and start a CouchDB container and connect as a BiscuitTin instance * Start the HTTP API service on a free port, with the necessary dependencies injected * Create an HTTP client connection to the API service """ self.couchdb_container = CouchDBContainer() # Configuration for Cookie Jar self.HOST = self.couchdb_container.couchdb_fqdn self.DB = 'elmo-test' self.jar = BiscuitTin(self.HOST, self.DB, 1, timedelta(0)) # Configuration for HTTP service self.API_PORT = get_open_port() self.api = HTTP_API() self.api.inject(APIDependency.CookieJar, self.jar) self.api.inject(APIDependency.System, None) self.api.listen(self.API_PORT) self.http = HTTPConnection('localhost', self.API_PORT) self.REQ_HEADER = {'Accept': 'application/json'} # Block until service is up (or timeout) start_time = finish_time = datetime.now() service_up = False while finish_time - start_time < timedelta(seconds=5): response = None try: self.http.request('HEAD', '/') response = self.http.getresponse() except: sleep(0.1) finally: self.http.close() finish_time = datetime.now() if isinstance(response, HTTPResponse): service_up = True break if not service_up: self.tearDown() raise ConnectionError('Couldn\'t start API service in a reasonable amount of time')
def setup_influxdb_in_docker(repository: str, tag: str) -> Tuple[str, int, Callable]: """ Setup an InfluxDB instance in docker using the given Docker Hub repository and tag. :param repository: the Docker Hub repository URL :param tag: the Docker Hub repository tag :return: tuple where the first element is the location of the database, the second is the port the HTTP API runs on and the third is a method to tear down the database """ docker_client = create_client() response = docker_client.pull(repository, tag) logging.debug(response) http_api_port = get_open_port() container = docker_client.create_container( name="influxdb-%s" % uuid4(), image="%s:%s" % (repository, tag), ports=[http_api_port], host_config=docker_client.create_host_config( port_bindings={ 8086: http_api_port } ) ) # Ensure that, no matter what, the container gets killed def tear_down(): docker_client.kill(container) atexit.unregister(tear_down) atexit.register(tear_down) docker_client.start(container) logging.info("Waiting for InfluxDB server to setup") for line in docker_client.logs(container, stream=True): logging.debug(line) if "Listening for signals" in str(line): break url = urlparse(docker_client.base_url) host = url.hostname if url.scheme in ["http", "https"] else "localhost" return host, http_api_port, tear_down
def __init__(self): """ Build and start the containerised instance """ docker_environment = kwargs_from_env(assert_hostname=False) if 'base_url' not in docker_environment: raise ConnectionError('Cannot connect to Docker') self._client = client = Client(**docker_environment) self._url = url = urlparse(self._client.base_url) self._host = url.hostname if url.scheme in ['http', 'https'] else 'localhost' self._port = get_open_port() # Exposed interface for CouchDB self.couchdb_fqdn = 'http://{host}:{port}'.format(host=self._host, port=self._port) # Build image # n.b., This will take a while, the first time through logging.info('Building CouchDB image...') logging.debug([ line for line in client.build( path = _DOCKERFILE_PATH, tag = _COUCHDB_IMAGE ) ]) # Create container self.container = client.create_container( image = _COUCHDB_IMAGE, ports = [self._port], host_config = client.create_host_config( port_bindings = {5984: self._port} ) ) # Start container logging.info('Starting CouchDB container {Id}...'.format(**self.container)) logging.debug('Warnings: {Warnings}'.format(**self.container)) atexit.register(self.tear_down) client.start(self.container['Id']) # Block 'til 200 OK response received (or timeout) test_connection = HTTPConnection(self._host, self._port) start_time = finish_time = datetime.now() couchdb_started = False while finish_time - start_time < timedelta(minutes=1): response = None try: test_connection.request('HEAD', '/') response = test_connection.getresponse() except: sleep(0.1) finally: test_connection.close() finish_time = datetime.now() if isinstance(response, HTTPResponse) and response.status == 200: couchdb_started = True break if not couchdb_started: self.tear_down() raise ConnectionError('Couldn\'t start CouchDB in a reasonable amount of time') logging.info('CouchDB container available on {fqdn}'.format(fqdn=self.couchdb_fqdn))