def _run(command: Union[str, List[str]], container: ContainerisedIrodsServer) -> str: """ Run the given commend on the containerised server. :param command: the command to run :param container: the containerised server to run the command in """ container_id = container.native_object["Id"] docker_client = create_client() id = docker_client.exec_create(container_id, cmd=command) chunks = [] for chunk in docker_client.exec_start(id, stream=True): logging.debug(chunk) chunks.append(chunk.decode("utf-8")) return "".join(chunks)
def test_baton_can_connect_to_irods_with_setting_parameters(self): irods_server = type(self).get_irods_server(self._irods_version) host_config = create_client().create_host_config(links={ irods_server.host: irods_server.host }) user = irods_server.users[0] response = self._run(command="ils", environment={ "IRODS_HOST": irods_server.host, "IRODS_PORT": irods_server.port, "IRODS_USERNAME": user.username, "IRODS_ZONE": user.zone, "IRODS_PASSWORD": user.password }, host_config=host_config) self.assertEqual(response, "/%s/home/%s:" % (user.zone, user.username))
def _run(command: Union[str, List[str]], service: IrodsDockerisedService) -> str: """ Run the given commend on the containerised server. :param command: the command to run :param service: the containerised service managing the iCAT """ container_id = service.container["Id"] docker_client = create_client() id = docker_client.exec_create(container_id, cmd=command) chunks = [] for chunk in docker_client.exec_start(id, stream=True): logging.debug(chunk) chunks.append(chunk.decode("utf-8")) return "".join(chunks)
def _run(self, stderr: bool=True, **kwargs) -> str: """ Run the containerised baton image that is been tested. :param stderr: whether content written to stderr should be included in the return :param kwargs: named arguments that are binded to corresponding parameters in docker-py's `create_container` method :return: what the command put onto stdout and stderr (if applicable) """ client = create_client() tag = self._top_level_image[1][0] container = client.create_container(tag, **kwargs) id = container.get("Id") client.start(id) client.wait(id) responses = client.logs(id, stderr=stderr).decode("utf-8") return "".join(responses).strip()
def _build_image(top_level_image: Tuple[Optional[Tuple], Tuple[str, str]]): """ Builds images bottom up, building the top level image last. :param top_level_image: representation of the top level image """ image = top_level_image images = [] # type: List[Tuple[str, str]] while image is not None: images.insert(0, image[1]) image = image[0] docker_client = create_client() for image in images: tag = image[0] directory = "%s/%s" % (_PROJECT_ROOT, image[1]) for line in docker_client.build(tag=tag, path=directory): logging.debug(line)
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 test_baton_can_connect_to_irods_with_settings_file(self): irods_server = type(self).get_irods_server(self._irods_version) settings_directory = create_temp_docker_mountable_directory() IrodsController = get_static_irods_server_controller(self._irods_version) # XXX: This is rather hacky - it should be possible to get the name from the iRODS controller if self._irods_version == IrodsVersion.v3_3_1: IrodsController.write_connection_settings("%s/.irodsEnv" % settings_directory, irods_server) else: IrodsController.write_connection_settings("%s/irods_environment.json" % settings_directory, irods_server) host_config = create_client().create_host_config(binds={ settings_directory: { "bind": "/root/.irods", "mode": "rw" } }, links={ irods_server.host: irods_server.host }) user = irods_server.users[0] response = self._run(command="ils", environment={"IRODS_PASSWORD": user.password}, host_config=host_config) self.assertEqual(response, "/%s/home/%s:" % (user.zone, user.username))
def setup(self): """ Sets up the setup: builds the baton Docker image, starts the iRODS test server (if required) and creates the proxies. """ if self._state != TestWithBaton._SetupState.INIT: raise RuntimeError("Already been setup") self._state = TestWithBaton._SetupState.RUNNING docker_client = create_client() if self._baton_docker_build.docker_file is not None: # baton Docker image is to be built from a local Dockerfile logging.debug("Building baton Docker") build_baton_docker(docker_client, self._baton_docker_build) else: # Ensuring Docker image is pulled - not waiting until `docker run` to prevent Docker from polluting the # stderr if ":" in self._baton_docker_build.tag: repository, tag = self._baton_docker_build.tag.split(":") else: repository = self._baton_docker_build.tag tag = "" docker_image = docker_client.images("%s:%s" % (repository, tag), quiet=True) if len(docker_image) == 0: # Docker image doesn't exist locally: getting from DockerHub docker_client.pull(repository, tag) if self._irods_version_to_start: logging.debug("Starting iRODS test server") self.irods_server = get_static_irods_server_controller(self._irods_version_to_start).start_server() logging.debug("iRODS test server has started") else: logging.debug("Using pre-existing iRODS server") self._setup_proxies() logging.debug("Setup complete")
def __init__(self): """ Build and start the containerised instance """ self._client = client = create_client() 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))