def shell_out(self, *cmd: str, stderr=True) -> str: exit_code, output = self.exec_run(cmd, stderr=stderr) if exit_code != 0: raise NonZeroExitCodeError(command=cmd, exit_code=exit_code, output=output) return output
def invoke_client(self, command: str, decode_stdout: bool = True, add_host: bool = True) -> str: volumes = { self.node.host_mount_dir: { "bind": "/data", "mode": "ro" }, "/tmp": { "bind": "/tmp", "mode": "rw" }, } if add_host: command = f"--host {self.node.container_name} {command}" if self.node.cl_network.grpc_encryption: node_id = extract_common_name( self.node.config.tls_certificate_local_path()) command = f"--node-id {node_id} {command}" self.logger.info(f"COMMAND {command}") status_code = None container = None try: container = self.docker_client.containers.run( image=f"casperlabs/client:{self.node.docker_tag}", name=f"client-{self.node.config.number}-{random_string(5)}", command=command, network=self.node.config.network, volumes=volumes, detach=True, stderr=True, stdout=True, ) r = container.wait() status_code = r["StatusCode"] stdout_raw = container.logs(stdout=True, stderr=False) stdout = decode_stdout and stdout_raw.decode("utf-8") or stdout_raw stderr = container.logs(stdout=False, stderr=True).decode("utf-8") # TODO: I don't understand why but if I just call `self.logger.debug` then # it doesn't print anything, even though the level is clearly set. if self.log_level == "DEBUG" or status_code != 0: self.logger.info( f"EXITED exit_code: {status_code} STDERR: {stderr} STDOUT: {stdout}" ) if status_code: raise NonZeroExitCodeError(command=(command, status_code), exit_code=status_code, output=stderr) return stdout finally: try: if container: container.remove() except docker.errors.APIError as e: self.logger.warning( f"Exception while removing docker client container: {str(e)}" )