1
0
mirror of https://github.com/avatao-content/test-tutorial-framework synced 2025-06-28 16:45:11 +00:00

Merge branch 'ocicat', the unrealized dream. Ocicat will return...

This commit is contained in:
Kristóf Tóth
2019-05-15 17:26:02 +02:00
13 changed files with 86 additions and 50 deletions

View File

@ -7,9 +7,9 @@ RUN pip3 install Flask==1.0 \
git+https://github.com/avatao-content/tfwconnector.git#subdirectory=python3
# Define variables to use later
ENV TFW_EHMAIN_DIR="/srv/.tfw_builtin_ehs" \
TFW_WEBSERVICE_DIR="/srv/webservice" \
TFW_IDE_WD="/home/${AVATAO_USER}/workdir" \
ENV TFW_EHMAIN_DIR="${TFW_DIR}/builtin_event_handlers" \
TFW_WEBSERVICE_DIR="/srv/webservice" \
TFW_IDE_WD="/home/${AVATAO_USER}/workdir" \
TFW_TERMINADO_WD="/home/${AVATAO_USER}/workdir"
# Copy TFW related stuff to a dedicated directory
@ -26,7 +26,8 @@ RUN mkdir -p ${TFW_IDE_WD} &&\
chmod -R 755 "${TFW_IDE_WD}" "${TFW_WEBSERVICE_DIR}"
# Hide TFW related code from user
RUN chown -R root:root ${TFW_SERVER_DIR} && chmod -R 700 ${TFW_SERVER_DIR}
RUN chown -R root:root ${TFW_SERVER_DIR} ${TFW_DIR} &&\
chmod -R 700 ${TFW_SERVER_DIR} ${TFW_DIR}
# Make AVATAO_USER's home writeable and set it as WORKDIR
# Make webservice directory writable

View File

@ -4,11 +4,12 @@ from signal import signal, SIGTERM, SIGINT
from tornado.ioloop import IOLoop
from tfw import YamlFSM, FSMAwareEventHandler, EventHandlerBase
from tfw.fsm import YamlFSM
from tfw.event_handler_base import EventHandlerBase, FSMAwareEventHandler
from tfw.components import IdeEventHandler, TerminalEventHandler
from tfw.components import ProcessManagingEventHandler, BashMonitor
from tfw.components import TerminalCommands, LogMonitoringEventHandler
from tfw.components import FSMManagingEventHandler
from tfw.components import FSMManagingEventHandler, DirectorySnapshottingEventHandler
from tfw.networking import MessageSender, TFWServerConnector
from tfw.config import TFWENV
from tfw.config.logs import logging
@ -87,22 +88,29 @@ class MessageFSMStepsEventHandler(FSMAwareEventHandler):
def handle_event(self, message):
pass
def handle_fsm_step(self, from_state, to_state, trigger):
def handle_fsm_step(self, **kwargs):
"""
When the FSM steps this method is invoked.
Receives a 'data' field from an fsm_update message as kwargs.
"""
MessageSender().send(
'FSM info',
f'FSM has stepped from state "{from_state}" '
f'to state "{to_state}" in response to trigger "{trigger}"'
f'FSM has stepped from state "{kwargs["last_event"]["from_state"]}" '
f'to state "{kwargs["current_state"]}" in response to trigger "{kwargs["last_event"]["trigger"]}"'
)
if __name__ == '__main__':
def main():
# pylint: disable=unused-variable
#
# TFW component EventHandlers (builtins, required for their respective functionalities)
fsm = FSMManagingEventHandler( # TFW FSM
fsm = FSMManagingEventHandler( # TFW FSM
key='fsm',
fsm_type=partial(YamlFSM, 'test_fsm.yml')
fsm_type=partial(
YamlFSM,
'test_fsm.yml',
{} # jinja2 variables, use empty dict to enable jinja2 parsing without any variables
)
)
ide = IdeEventHandler( # Web IDE backend
key='ide',
@ -124,17 +132,22 @@ if __name__ == '__main__':
process_name='webservice',
log_tail=2000
)
snapshot = DirectorySnapshottingEventHandler( # Manages filesystem snapshots of directories
key='snapshot',
directories=[
TFWENV.IDE_WD,
TFWENV.WEBSERVICE_DIR
]
)
# Your custom event handlers
message_fsm_steps = MessageFSMStepsEventHandler(
message_fsm_steps_eh = MessageFSMStepsEventHandler(
key='test'
)
# Terminal command handlers
commands = TestCommands(bashrc=f'/home/{TAOENV.USER}/.bashrc')
terminal.historymonitor.subscribe_callback(commands.callback)
# Example terminal command callback
terminal.historymonitor.subscribe_callback(cenator)
event_handlers = EventHandlerBase.get_local_instances()
@ -146,3 +159,7 @@ if __name__ == '__main__':
signal(SIGINT, cleanup)
IOLoop.instance().start()
if __name__ == '__main__':
main()

View File

@ -2,7 +2,7 @@ from signal import signal, SIGTERM, SIGINT
from tornado.ioloop import IOLoop
from tfw import EventHandlerBase
from tfw.event_handler_base import EventHandlerBase
from tfw.components import PipeIOEventHandler

View File

@ -2,7 +2,7 @@
from os.path import exists
from tfw import LinearFSM
from tfw.fsm import LinearFSM
from tfw.networking import MessageSender

View File

@ -41,3 +41,8 @@ transitions:
- trigger: step_5
source: '4'
dest: '5'
{% for i in range(5) %} # you can also use jinja2 in this config file
- trigger: 'step_next'
source: '{{i}}'
dest: '{{i+1}}'
{% endfor %}

View File

@ -13,18 +13,29 @@ session_factory = sessionmaker(
)
@contextmanager
def Session(factory=session_factory):
session = factory()
try:
yield session
session.commit()
except:
session.rollback()
raise
# session is closed by flask
# finally:
# session.close()
class SessionWrapper:
def __init__(self):
self._session_factory = session_factory
self._session_handle = None
@contextmanager
def session(self):
try:
yield self._session
self._session.commit()
except:
self._session.rollback()
raise
@property
def _session(self):
if self._session_handle is None:
self._session_handle = self._session_factory()
return self._session_handle
def teardown(self):
if self._session_handle is not None:
self._session_handle.close()
Base = declarative_base()

View File

@ -1,9 +1,8 @@
from os import urandom, getenv
from functools import partial
from flask import Flask, render_template, request, session, url_for, g
from model import init_db, session_factory, Session
from model import init_db, SessionWrapper
from user_ops import UserOps
from errors import InvalidCredentialsError, UserExistsError
@ -16,25 +15,24 @@ app.jinja_env.globals.update( # pylint: disable=no-member
)
def get_db_session():
if not hasattr(g, 'db_session'):
g.db_session = session_factory()
return g.db_session
Session = partial(Session, get_db_session)
@app.before_request
def setup_db():
# pylint: disable=protected-access
g._db_session_wrapper = SessionWrapper()
g.db_session = g._db_session_wrapper.session
@app.teardown_appcontext
def close_db_session(err): # pylint: disable=unused-argument
if hasattr(g, 'db_session'):
g.db_session.close()
def close_db_session(_):
# pylint: disable=protected-access
g._db_session_wrapper.teardown()
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
try:
with Session() as db_session:
with g.db_session() as db_session:
UserOps(
request.form.get('username'),
request.form.get('password'),
@ -67,7 +65,7 @@ def register():
return render_template('register.html', alert='Passwords do not match! Please try again.')
try:
with Session() as db_session:
with g.db_session() as db_session:
UserOps(
request.form.get('username'),
request.form.get('password'),