def test_open_missing_file(self, tail_engine): lines = [] listener = FileListener("/tmp/does/not/exist", lines.append) listener.use_tail_command = tail_engine != "tailer" with pytest.raises(FileNotFoundError): listener.start()
def cmd_logs(follow: bool): from localstack import config from localstack.utils.bootstrap import LocalstackContainer from localstack.utils.common import FileListener from localstack.utils.docker_utils import DOCKER_CLIENT container_name = config.MAIN_CONTAINER_NAME logfile = LocalstackContainer(container_name).logfile if not DOCKER_CLIENT.is_container_running(container_name): console.print("localstack container not running") sys.exit(1) if not os.path.exists(logfile): console.print("localstack container logfile not found at %s" % logfile) sys.exit(1) if follow: listener = FileListener(logfile, print) listener.start() try: listener.join() except KeyboardInterrupt: pass finally: listener.close() else: with open(logfile) as fd: for line in fd: print(line.rstrip("\n\r"))
def test_basic_usage(self, tail_engine, tmp_path): lines = [] file = tmp_path / "log.txt" file.touch() fd = open(file, "a") listener = FileListener(str(file), lines.append) listener.use_tail_command = tail_engine != "tailer" try: listener.start() assert listener.started.is_set() fd.write("hello" + os.linesep) fd.write("pytest" + os.linesep) fd.flush() assert poll_condition( lambda: len(lines) == 2, timeout=3), ("expected two lines to appear. %s" % lines) assert lines[0] == "hello" assert lines[1] == "pytest" finally: listener.close() try: fd.write("foobar" + os.linesep) time.sleep(0.5) assert len( lines ) == 2, "expected listener.stop() to stop listening on new " finally: fd.close()
def test_callback_exception_ignored(self, tail_engine, tmp_path): lines = [] def callback(line): if "throw" in line: raise ValueError("oh noes") lines.append(line) file = tmp_path / "log.txt" file.touch() fd = open(file, "a") listener = FileListener(str(file), callback) listener.use_tail_command = tail_engine != "tailer" try: listener.start() assert listener.started.is_set() fd.write("hello" + os.linesep) fd.flush() fd.write("throw" + os.linesep) fd.write("pytest" + os.linesep) fd.flush() assert poll_condition( lambda: len(lines) == 2, timeout=3), ("expected two lines to appear. %s" % lines) assert lines[0] == "hello" assert lines[1] == "pytest" finally: fd.close() listener.close()
def start_infra_in_docker(): prepare_docker_start() container = LocalstackContainer() # create and prepare container configure_container(container) container.truncate_log() # printing the container log is the current way we're occupying the terminal log_printer = FileListener(container.logfile, print) log_printer.start() # Set up signal handler, to enable clean shutdown across different operating systems. # There are subtle differences across operating systems and terminal emulators when it # comes to handling of CTRL-C - in particular, Linux sends SIGINT to the parent process, # whereas MacOS sends SIGINT to the process group, which can result in multiple SIGINT signals # being received (e.g., when running the localstack CLI as part of an "npm run .." script). # Hence, using a shutdown handler and synchronization event here, to avoid inconsistencies. def shutdown_handler(*args): with shutdown_event_lock: if shutdown_event.is_set(): return shutdown_event.set() print("Shutting down...") server.shutdown() log_printer.close() shutdown_event = threading.Event() shutdown_event_lock = threading.RLock() signal.signal(signal.SIGINT, shutdown_handler) # start the Localstack container as a Server server = LocalstackContainerServer(container) try: server.start() server.join() except KeyboardInterrupt: print("ok, bye!") shutdown_handler()
def wait_container_is_ready(timeout: Optional[float] = None): """Blocks until the localstack main container is running and the ready marker has been printed.""" container_name = config.MAIN_CONTAINER_NAME def is_container_running(): return DOCKER_CLIENT.is_container_running(container_name) if not poll_condition(is_container_running, timeout=timeout): return False logfile = LocalstackContainer(container_name).logfile ready = threading.Event() def set_ready_if_marker_found(_line: str): if _line == constants.READY_MARKER_OUTPUT: ready.set() # start a tail on the logfile listener = FileListener(logfile, set_ready_if_marker_found) listener.start() try: # but also check the existing log in case the container has been running longer with open(logfile, "r") as fd: for line in fd: if constants.READY_MARKER_OUTPUT == line.strip(): return True # TODO: calculate remaining timeout return ready.wait(timeout) finally: listener.close()
def start_infra_in_docker(): prepare_docker_start() container = LocalstackContainer() # create and prepare container configure_container(container) container.truncate_log() # printing the container log is the current way we're occupying the terminal log_printer = FileListener(container.logfile, print) log_printer.start() # start the Localstack container as a Server server = LocalstackContainerServer(container) try: server.start() server.join() except KeyboardInterrupt: print("ok, bye!") finally: server.shutdown() log_printer.close()