mirror of
				https://github.com/avatao-content/baseimage-tutorial-framework
				synced 2025-11-04 16:02:54 +00:00 
			
		
		
		
	Adjust the whole framework to event handler dependency inversion
This commit is contained in:
		@@ -1,7 +1,5 @@
 | 
			
		||||
from .directory_snapshotting_event_handler import DirectorySnapshottingEventHandler
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
from .frontend_event_handler import FrontendEventHandler
 | 
			
		||||
from .fsm_aware_event_handler import FSMAwareEventHandler
 | 
			
		||||
from .fsm_managing_event_handler import FSMManagingEventHandler
 | 
			
		||||
from .ide_event_handler import IdeEventHandler
 | 
			
		||||
from .log_monitoring_event_handler import LogMonitoringEventHandler
 | 
			
		||||
@@ -10,4 +8,3 @@ from .pipe_io_event_handler import TransformerPipeIOEventHandler, CommandEventHa
 | 
			
		||||
from .process_managing_event_handler import ProcessManagingEventHandler
 | 
			
		||||
from .terminal_commands_event_handler import TerminalCommandsEventHandler
 | 
			
		||||
from .terminal_event_handler import TerminalEventHandler
 | 
			
		||||
from .tfw_server_connector import TFWServerUplinkConnector, TFWServerConnector
 | 
			
		||||
 
 | 
			
		||||
@@ -10,14 +10,14 @@ from tfw.components.snapshot_provider import SnapshotProvider
 | 
			
		||||
from tfw.config import TFWENV
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DirectorySnapshottingEventHandler(EventHandler):
 | 
			
		||||
    def __init__(self, key, directories, exclude_unix_patterns=None):
 | 
			
		||||
        super().__init__(key, scope=Scope.WEBSOCKET)
 | 
			
		||||
class DirectorySnapshottingEventHandler:
 | 
			
		||||
    keys = ['snapshot']
 | 
			
		||||
 | 
			
		||||
    def __init__(self, directories, exclude_unix_patterns=None):
 | 
			
		||||
        self.snapshot_providers = {}
 | 
			
		||||
        self._exclude_unix_patterns = exclude_unix_patterns
 | 
			
		||||
        self.init_snapshot_providers(directories)
 | 
			
		||||
@@ -46,11 +46,11 @@ class DirectorySnapshottingEventHandler(EventHandler):
 | 
			
		||||
        makedirs(git_dir, exist_ok=True)
 | 
			
		||||
        return git_dir
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, server_connector):
 | 
			
		||||
        try:
 | 
			
		||||
            data = message['data']
 | 
			
		||||
            message['data'] = self.command_handlers[data['command']](data)
 | 
			
		||||
            self.send_message(message)
 | 
			
		||||
            server_connector.send_message(message, scope=Scope.WEBSOCKET)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
from tfw.event_handlers import EventHandlerBase
 | 
			
		||||
 | 
			
		||||
from .tfw_server_connector import TFWServerConnector
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EventHandler(EventHandlerBase):
 | 
			
		||||
    # pylint: disable=abstract-method
 | 
			
		||||
    def _build_server_connector(self):
 | 
			
		||||
        return TFWServerConnector()
 | 
			
		||||
@@ -1,16 +1,19 @@
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
from tfw.components import FrontendMessageStorage
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
class FrontendEventHandler:
 | 
			
		||||
    keys = ['message', 'queueMessages', 'dashboard', 'console']
 | 
			
		||||
 | 
			
		||||
class FrontendEventHandler(EventHandler):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        frontend_keys = ('message', 'queueMessages', 'dashboard', 'console')
 | 
			
		||||
        self._frontend_message_storage = FrontendMessageStorage(frontend_keys)
 | 
			
		||||
        super().__init__((*frontend_keys, 'recover'), scope=Scope.WEBSOCKET)
 | 
			
		||||
        self.server_connector = None
 | 
			
		||||
        self.keys = [*type(self).keys, 'recover']
 | 
			
		||||
        self._frontend_message_storage = FrontendMessageStorage(type(self).keys)
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def send_message(self, message):
 | 
			
		||||
        self.server_connector.send_message(message, scope=Scope.WEBSOCKET)
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        self._frontend_message_storage.save_message(message)
 | 
			
		||||
        if message['key'] == 'recover':
 | 
			
		||||
            self.recover_frontend()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
from tfw.components import FSMAware
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FSMAwareEventHandler(EventHandler, FSMAware):
 | 
			
		||||
    # pylint: disable=abstract-method
 | 
			
		||||
    """
 | 
			
		||||
    Abstract base class for EventHandlers which automatically
 | 
			
		||||
    keep track of the state of the TFW FSM.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, scope=Scope.ZMQ):
 | 
			
		||||
        EventHandler.__init__(self, key, scope=scope)
 | 
			
		||||
        FSMAware.__init__(self)
 | 
			
		||||
        self.subscribe('fsm_update')
 | 
			
		||||
 | 
			
		||||
    def dispatch_handling(self, message):
 | 
			
		||||
        if not self.refresh_on_fsm_update(message):
 | 
			
		||||
            super().dispatch_handling(message)
 | 
			
		||||
@@ -4,12 +4,12 @@ from tfw.crypto import KeyManager, sign_message, verify_message
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
from tfw.components import FSMUpdater
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FSMManagingEventHandler(EventHandler):
 | 
			
		||||
class FSMManagingEventHandler:
 | 
			
		||||
    keys = ['fsm']
 | 
			
		||||
    """
 | 
			
		||||
    EventHandler responsible for managing the state machine of
 | 
			
		||||
    the framework (TFW FSM).
 | 
			
		||||
@@ -24,8 +24,7 @@ class FSMManagingEventHandler(EventHandler):
 | 
			
		||||
    An 'fsm_update' message is broadcasted after every successful
 | 
			
		||||
    command.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, fsm_type, require_signature=False):
 | 
			
		||||
        super().__init__(key, scope=Scope.WEBSOCKET)
 | 
			
		||||
    def __init__(self, fsm_type, require_signature=False):
 | 
			
		||||
        self.fsm = fsm_type()
 | 
			
		||||
        self._fsm_updater = FSMUpdater(self.fsm)
 | 
			
		||||
        self.auth_key = KeyManager().auth_key
 | 
			
		||||
@@ -36,15 +35,14 @@ class FSMManagingEventHandler(EventHandler):
 | 
			
		||||
            'update':  self.handle_update
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, server_connector):
 | 
			
		||||
        try:
 | 
			
		||||
            message = self.command_handlers[message['data']['command']](message)
 | 
			
		||||
            if message:
 | 
			
		||||
                fsm_update_message = self._fsm_updater.fsm_update
 | 
			
		||||
                sign_message(self.auth_key, message)
 | 
			
		||||
                sign_message(self.auth_key, fsm_update_message)
 | 
			
		||||
                self.server_connector.send_message(fsm_update_message, Scope.BROADCAST)
 | 
			
		||||
                self.send_message(message)
 | 
			
		||||
                server_connector.send_message(fsm_update_message, Scope.BROADCAST)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ from tfw.networking import Scope
 | 
			
		||||
from tfw.components import FileManager
 | 
			
		||||
from tfw.components.inotify import InotifyObserver
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +31,8 @@ BUILD_ARTIFACTS = (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IdeEventHandler(EventHandler):
 | 
			
		||||
class IdeEventHandler:
 | 
			
		||||
    keys = ['ide']
 | 
			
		||||
    # pylint: disable=too-many-arguments,anomalous-backslash-in-string
 | 
			
		||||
    """
 | 
			
		||||
    Event handler implementing the backend of our browser based IDE.
 | 
			
		||||
@@ -47,7 +47,7 @@ class IdeEventHandler(EventHandler):
 | 
			
		||||
 | 
			
		||||
    The API of each command is documented in their respective handler.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, directory, allowed_directories, selected_file=None, exclude=None):
 | 
			
		||||
    def __init__(self, directory, allowed_directories, selected_file=None, exclude=None):
 | 
			
		||||
        """
 | 
			
		||||
        :param key: the key this instance should listen to
 | 
			
		||||
        :param directory: working directory which the EventHandler should serve files from
 | 
			
		||||
@@ -55,7 +55,7 @@ class IdeEventHandler(EventHandler):
 | 
			
		||||
        :param selected_file: file that is selected by default
 | 
			
		||||
        :param exclude: list of filenames that should not appear between files (for .o, .pyc, etc.)
 | 
			
		||||
        """
 | 
			
		||||
        super().__init__(key, scope=Scope.WEBSOCKET)
 | 
			
		||||
        self.server_connector = None
 | 
			
		||||
        try:
 | 
			
		||||
            self.filemanager = FileManager(
 | 
			
		||||
                allowed_directories=allowed_directories,
 | 
			
		||||
@@ -84,10 +84,13 @@ class IdeEventHandler(EventHandler):
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def _reload_frontend(self, event):  # pylint: disable=unused-argument
 | 
			
		||||
        self.server_connector.send_message({
 | 
			
		||||
        self.send_message({
 | 
			
		||||
            'key': 'ide',
 | 
			
		||||
            'data': {'command': 'reload'}
 | 
			
		||||
        }, Scope.WEBSOCKET)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    def send_message(self, message):
 | 
			
		||||
        self.server_connector.send_message(message, scope=Scope.WEBSOCKET)
 | 
			
		||||
 | 
			
		||||
    def read(self, data):
 | 
			
		||||
        """
 | 
			
		||||
@@ -179,7 +182,7 @@ class IdeEventHandler(EventHandler):
 | 
			
		||||
        data['files'] = self.filemanager.files
 | 
			
		||||
        data['directory'] = self.filemanager.workdir
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        try:
 | 
			
		||||
            data = message['data']
 | 
			
		||||
            message['data'] = self.commands[data['command']](data)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,14 @@
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from tfw.config import TFWENV
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
from tfw.components import LogInotifyObserver
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LogMonitoringEventHandler(EventHandler):
 | 
			
		||||
class LogMonitoringEventHandler:
 | 
			
		||||
    keys = ['logmonitor']
 | 
			
		||||
    """
 | 
			
		||||
    Monitors the output of a supervisor process (stdout, stderr) and
 | 
			
		||||
    sends the results to the frontend.
 | 
			
		||||
@@ -19,23 +18,27 @@ class LogMonitoringEventHandler(EventHandler):
 | 
			
		||||
 | 
			
		||||
    The API of each command is documented in their respective handler.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, process_name, log_tail=0):
 | 
			
		||||
        super().__init__(key, scope=Scope.WEBSOCKET)
 | 
			
		||||
    def __init__(self, process_name, log_tail=0):
 | 
			
		||||
        self.server_connector = None
 | 
			
		||||
        self.process_name = process_name
 | 
			
		||||
        self._monitor = LogInotifyObserver(
 | 
			
		||||
            server_connector=self.server_connector,
 | 
			
		||||
            supervisor_uri=TFWENV.SUPERVISOR_HTTP_URI,
 | 
			
		||||
            process_name=process_name,
 | 
			
		||||
            log_tail=log_tail
 | 
			
		||||
        )
 | 
			
		||||
        self._monitor.start()
 | 
			
		||||
        self._initial_log_tail = log_tail
 | 
			
		||||
        self._monitor = None
 | 
			
		||||
 | 
			
		||||
        self.command_handlers = {
 | 
			
		||||
            'process_name': self.handle_process_name,
 | 
			
		||||
            'log_tail':     self.handle_log_tail
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def start(self):
 | 
			
		||||
        self._monitor = LogInotifyObserver(
 | 
			
		||||
            server_connector=self.server_connector,
 | 
			
		||||
            supervisor_uri=TFWENV.SUPERVISOR_HTTP_URI,
 | 
			
		||||
            process_name=self.process_name,
 | 
			
		||||
            log_tail=self._initial_log_tail
 | 
			
		||||
        )
 | 
			
		||||
        self._monitor.start()
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        try:
 | 
			
		||||
            data = message['data']
 | 
			
		||||
            self.command_handlers[data['command']](data)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,15 +12,16 @@ from contextlib import suppress
 | 
			
		||||
 | 
			
		||||
from tfw.components.pipe_io_server import PipeIOServer, terminate_process_on_failure
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
DEFAULT_PERMISSIONS = 0o600
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PipeIOEventHandlerBase(EventHandler):
 | 
			
		||||
    def __init__(self, key, in_pipe_path, out_pipe_path, permissions=DEFAULT_PERMISSIONS):
 | 
			
		||||
        super().__init__(key)
 | 
			
		||||
class PipeIOEventHandlerBase:
 | 
			
		||||
    keys = ['']
 | 
			
		||||
 | 
			
		||||
    def __init__(self, in_pipe_path, out_pipe_path, permissions=DEFAULT_PERMISSIONS):
 | 
			
		||||
        self.server_connector = None
 | 
			
		||||
        self.pipe_io = CallbackPipeIOServer(
 | 
			
		||||
            in_pipe_path,
 | 
			
		||||
            out_pipe_path,
 | 
			
		||||
@@ -50,25 +51,25 @@ class CallbackPipeIOServer(PipeIOServer):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PipeIOEventHandler(PipeIOEventHandlerBase):
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        json_bytes = dumps(message).encode()
 | 
			
		||||
        self.pipe_io.send_message(json_bytes)
 | 
			
		||||
 | 
			
		||||
    def handle_pipe_event(self, message_bytes):
 | 
			
		||||
        json = loads(message_bytes)
 | 
			
		||||
        self.send_message(json)
 | 
			
		||||
        self.server_connector.send_message(json)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TransformerPipeIOEventHandler(PipeIOEventHandlerBase):
 | 
			
		||||
    # pylint: disable=too-many-arguments
 | 
			
		||||
    def __init__(
 | 
			
		||||
            self, key, in_pipe_path, out_pipe_path,
 | 
			
		||||
            self, in_pipe_path, out_pipe_path,
 | 
			
		||||
            transform_in_cmd, transform_out_cmd,
 | 
			
		||||
            permissions=DEFAULT_PERMISSIONS
 | 
			
		||||
    ):
 | 
			
		||||
        self._transform_in = partial(self._transform_message, transform_in_cmd)
 | 
			
		||||
        self._transform_out = partial(self._transform_message, transform_out_cmd)
 | 
			
		||||
        super().__init__(key, in_pipe_path, out_pipe_path, permissions)
 | 
			
		||||
        super().__init__(in_pipe_path, out_pipe_path, permissions)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _transform_message(transform_cmd, message):
 | 
			
		||||
@@ -83,7 +84,7 @@ class TransformerPipeIOEventHandler(PipeIOEventHandlerBase):
 | 
			
		||||
            return proc.stdout
 | 
			
		||||
        raise ValueError(f'Transforming message {message} failed!')
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        json_bytes = dumps(message).encode()
 | 
			
		||||
        transformed_bytes = self._transform_out(json_bytes)
 | 
			
		||||
        if transformed_bytes:
 | 
			
		||||
@@ -93,13 +94,12 @@ class TransformerPipeIOEventHandler(PipeIOEventHandlerBase):
 | 
			
		||||
        transformed_bytes = self._transform_in(message_bytes)
 | 
			
		||||
        if transformed_bytes:
 | 
			
		||||
            json_message = loads(transformed_bytes)
 | 
			
		||||
            self.send_message(json_message)
 | 
			
		||||
            self.server_connector.send_message(json_message)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CommandEventHandler(PipeIOEventHandler):
 | 
			
		||||
    def __init__(self, key, command, permissions=DEFAULT_PERMISSIONS):
 | 
			
		||||
    def __init__(self, command, permissions=DEFAULT_PERMISSIONS):
 | 
			
		||||
        super().__init__(
 | 
			
		||||
            key,
 | 
			
		||||
            self._generate_tempfilename(),
 | 
			
		||||
            self._generate_tempfilename(),
 | 
			
		||||
            permissions
 | 
			
		||||
 
 | 
			
		||||
@@ -5,12 +5,12 @@ from tfw.config import TFWENV
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
from tfw.components import ProcessManager, LogManager
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProcessManagingEventHandler(EventHandler, ProcessManager, LogManager):
 | 
			
		||||
class ProcessManagingEventHandler(ProcessManager, LogManager):
 | 
			
		||||
    keys = ['processmanager']
 | 
			
		||||
    """
 | 
			
		||||
    Event handler that can manage processes managed by supervisor.
 | 
			
		||||
 | 
			
		||||
@@ -23,8 +23,7 @@ class ProcessManagingEventHandler(EventHandler, ProcessManager, LogManager):
 | 
			
		||||
    Commands available: start, stop, restart, readlog
 | 
			
		||||
    (the names are as self-documenting as it gets)
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, log_tail=0):
 | 
			
		||||
        EventHandler.__init__(self, key, scope=Scope.WEBSOCKET)
 | 
			
		||||
    def __init__(self, log_tail=0):
 | 
			
		||||
        ProcessManager.__init__(self, TFWENV.SUPERVISOR_HTTP_URI)
 | 
			
		||||
        LogManager.__init__(self, TFWENV.SUPERVISOR_HTTP_URI)
 | 
			
		||||
        self.log_tail = log_tail
 | 
			
		||||
@@ -34,7 +33,7 @@ class ProcessManagingEventHandler(EventHandler, ProcessManager, LogManager):
 | 
			
		||||
            'restart': self.restart_process
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, server_connector):
 | 
			
		||||
        try:
 | 
			
		||||
            data = message['data']
 | 
			
		||||
            try:
 | 
			
		||||
@@ -50,6 +49,6 @@ class ProcessManagingEventHandler(EventHandler, ProcessManager, LogManager):
 | 
			
		||||
                    data['process_name'],
 | 
			
		||||
                    self.log_tail
 | 
			
		||||
                )
 | 
			
		||||
            self.send_message(message)
 | 
			
		||||
            server_connector.send_message(message, scope=Scope.WEBSOCKET)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,9 @@
 | 
			
		||||
from tfw.components import TerminalCommands
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TerminalCommandsEventHandler(EventHandler, TerminalCommands):
 | 
			
		||||
    def __init__(self, key, scope=Scope.ZMQ, bashrc=None):
 | 
			
		||||
        EventHandler.__init__(self, key, scope)
 | 
			
		||||
        TerminalCommands.__init__(self, bashrc)
 | 
			
		||||
class TerminalCommandsEventHandler(TerminalCommands):
 | 
			
		||||
    keys = ['history.bash']
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        command = message['value']
 | 
			
		||||
        self.callback(command)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,15 @@
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from tfw.networking import Scope
 | 
			
		||||
from tfw.components import BashMonitor, TerminadoMiniServer
 | 
			
		||||
from tfw.config import TFWENV
 | 
			
		||||
from tao.config import TAOENV
 | 
			
		||||
 | 
			
		||||
from .event_handler import EventHandler
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TerminalEventHandler(EventHandler):
 | 
			
		||||
class TerminalEventHandler:
 | 
			
		||||
    keys = ['shell']
 | 
			
		||||
    """
 | 
			
		||||
    Event handler responsible for managing terminal sessions for frontend xterm
 | 
			
		||||
    sessions to connect to. You need to instanciate this in order for frontend
 | 
			
		||||
@@ -20,13 +19,13 @@ class TerminalEventHandler(EventHandler):
 | 
			
		||||
    a command to be executed.
 | 
			
		||||
    The API of each command is documented in their respective handler.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        """
 | 
			
		||||
        :param key: key this EventHandler listens to
 | 
			
		||||
        :param monitor: tfw.components.HistoryMonitor instance to read command history from
 | 
			
		||||
        """
 | 
			
		||||
        super().__init__(key, scope=Scope.WEBSOCKET)
 | 
			
		||||
        self._historymonitor = BashMonitor(self.server_connector, TFWENV.HISTFILE)
 | 
			
		||||
        self.server_connector = None
 | 
			
		||||
        self._historymonitor = None
 | 
			
		||||
        bash_as_user_cmd = ['sudo', '-u', TAOENV.USER, 'bash']
 | 
			
		||||
 | 
			
		||||
        self.terminado_server = TerminadoMiniServer(
 | 
			
		||||
@@ -41,18 +40,20 @@ class TerminalEventHandler(EventHandler):
 | 
			
		||||
            'read': self.read
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self._historymonitor.start()
 | 
			
		||||
        self.terminado_server.listen()
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        self._historymonitor = BashMonitor(self.server_connector, TFWENV.HISTFILE)
 | 
			
		||||
        self._historymonitor.start()
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def historymonitor(self):
 | 
			
		||||
        return self._historymonitor
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        try:
 | 
			
		||||
            data = message['data']
 | 
			
		||||
            message['data'] = self.commands[data['command']](data)
 | 
			
		||||
            self.send_message(message)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
from tfw.networking import ServerUplinkConnector, ServerConnector
 | 
			
		||||
from tfw.config import TFWENV
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ConnAddrMixin:
 | 
			
		||||
    @property
 | 
			
		||||
    def uplink_conn_addr(self):
 | 
			
		||||
        return f'tcp://localhost:{TFWENV.PULL_PORT}'
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def downlink_conn_addr(self):
 | 
			
		||||
        return f'tcp://localhost:{TFWENV.PUB_PORT}'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TFWServerUplinkConnector(ServerUplinkConnector, ConnAddrMixin):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__(self.uplink_conn_addr)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TFWServerConnector(ServerConnector, ConnAddrMixin):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__(
 | 
			
		||||
            self.downlink_conn_addr,
 | 
			
		||||
            self.uplink_conn_addr
 | 
			
		||||
        )
 | 
			
		||||
		Reference in New Issue
	
	Block a user