mirror of
https://github.com/avatao-content/baseimage-tutorial-framework
synced 2024-11-22 23:41:33 +00:00
Merge pull request #21 from avatao-content/platform_fixes
Add platform fixes to TFW and implement Geri's feature requests
This commit is contained in:
commit
abeb12858e
23
Dockerfile
23
Dockerfile
@ -34,10 +34,9 @@ RUN curl -fSL -o pyenv-installer ${PYENV_INSTALLER_URL} &&\
|
|||||||
pip install -r /tmp/requirements.txt
|
pip install -r /tmp/requirements.txt
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
WORKDIR /data/
|
|
||||||
COPY src/frontend /data/
|
COPY src/frontend /data/
|
||||||
RUN yarn install --frozen-lockfile
|
RUN cd /data && yarn install --frozen-lockfile
|
||||||
RUN yarn build --no-progress
|
RUN cd /data && yarn build --no-progress
|
||||||
|
|
||||||
ENV TFW_PUBLIC_PORT=8888 \
|
ENV TFW_PUBLIC_PORT=8888 \
|
||||||
TFW_WEB_PORT=4242 \
|
TFW_WEB_PORT=4242 \
|
||||||
@ -55,7 +54,8 @@ ENV PYTHONPATH="/usr/local/lib/" \
|
|||||||
TFW_SUPERVISOR_HTTP_URI="http://localhost:${TFW_SUPERVISOR_HTTP_PORT}" \
|
TFW_SUPERVISOR_HTTP_URI="http://localhost:${TFW_SUPERVISOR_HTTP_PORT}" \
|
||||||
TFW_SUPERVISORD_CONF="/etc/supervisor/supervisord.conf" \
|
TFW_SUPERVISORD_CONF="/etc/supervisor/supervisord.conf" \
|
||||||
TFW_SUPERVISORD_COMPONENTS="/etc/supervisor/conf" \
|
TFW_SUPERVISORD_COMPONENTS="/etc/supervisor/conf" \
|
||||||
TFW_NGINX_CONF="/etc/nginx/sites-enabled/default" \
|
TFW_NGINX_CONF="/etc/nginx/nginx.conf" \
|
||||||
|
TFW_NGINX_DEFAULT="/etc/nginx/sites-enabled/default" \
|
||||||
TFW_NGINX_COMPONENTS="/etc/nginx/components" \
|
TFW_NGINX_COMPONENTS="/etc/nginx/components" \
|
||||||
TFW_LIB_DIR="/usr/local/lib/" \
|
TFW_LIB_DIR="/usr/local/lib/" \
|
||||||
TFW_CONTROLLER_DIR="/srv/controller" \
|
TFW_CONTROLLER_DIR="/srv/controller" \
|
||||||
@ -74,17 +74,18 @@ RUN echo "shopt -s cmdhist\n" \
|
|||||||
>> /home/${AVATAO_USER}/.bashrc
|
>> /home/${AVATAO_USER}/.bashrc
|
||||||
|
|
||||||
COPY nginx/nginx.conf ${TFW_NGINX_CONF}
|
COPY nginx/nginx.conf ${TFW_NGINX_CONF}
|
||||||
|
COPY nginx/default.conf ${TFW_NGINX_DEFAULT}
|
||||||
COPY nginx/components/ ${TFW_NGINX_COMPONENTS}
|
COPY nginx/components/ ${TFW_NGINX_COMPONENTS}
|
||||||
RUN chown -R ${AVATAO_USER} /var/log/nginx /var/lib/nginx &&\
|
RUN chown -R ${AVATAO_USER} /var/log/nginx /var/lib/nginx &&\
|
||||||
sed -i 's#pid /run/nginx.pid;#pid /tmp/nginx.pid;#g' /etc/nginx/nginx.conf &&\
|
for f in "${TFW_NGINX_DEFAULT}" ${TFW_NGINX_COMPONENTS}/*.conf; do \
|
||||||
for f in "${TFW_NGINX_CONF}" ${TFW_NGINX_COMPONENTS}/*.conf; do \
|
envsubst "$(printenv | cut -d= -f1 | grep TFW_ | sed -e 's/^/$/g')" < $f > $f~ && mv $f~ $f ;\
|
||||||
envsubst "$(printenv | cut -d= -f1 | grep TFW_ | sed -e 's/^/$/g')" < $f > $f ;\
|
|
||||||
done
|
done
|
||||||
|
|
||||||
COPY supervisor/supervisord.conf ${TFW_SUPERVISORD_CONF}
|
COPY supervisor/supervisord.conf ${TFW_SUPERVISORD_CONF}
|
||||||
COPY supervisor/components/ ${TFW_SUPERVISORD_COMPONENTS}
|
COPY supervisor/components/ ${TFW_SUPERVISORD_COMPONENTS}
|
||||||
COPY lib ${TFW_LIB_DIR}
|
COPY lib ${TFW_LIB_DIR}
|
||||||
COPY src/controller ${TFW_CONTROLLER_DIR}
|
COPY src/controller ${TFW_CONTROLLER_DIR}
|
||||||
|
RUN mv /data/dist ${TFW_FRONTEND_DIR} && rm -rf /data
|
||||||
|
|
||||||
### TFW internals ^ ### DEMO v ###############################################################
|
### TFW internals ^ ### DEMO v ###############################################################
|
||||||
|
|
||||||
@ -93,17 +94,17 @@ ENV TFW_APP_DIR="/srv/app" \
|
|||||||
TFW_WEBIDE_WD="/home/${AVATAO_USER}/workdir" \
|
TFW_WEBIDE_WD="/home/${AVATAO_USER}/workdir" \
|
||||||
TFW_TERMINADO_WD="/home/${AVATAO_USER}/workdir"
|
TFW_TERMINADO_WD="/home/${AVATAO_USER}/workdir"
|
||||||
|
|
||||||
RUN mv /data/dist ${TFW_FRONTEND_DIR}
|
|
||||||
|
|
||||||
COPY src/demo ${TFW_APP_DIR}/
|
COPY src/demo ${TFW_APP_DIR}/
|
||||||
|
|
||||||
COPY src/demo/source_code_server/server.py ${TFW_LOGIN_APP_DIR}/
|
COPY src/demo/source_code_server/server.py ${TFW_LOGIN_APP_DIR}/
|
||||||
COPY src/demo/source_code_server/users.db ${TFW_LOGIN_APP_DIR}/
|
COPY src/demo/source_code_server/users.db ${TFW_LOGIN_APP_DIR}/
|
||||||
COPY src/demo/source_code_server/login_component.py ${TFW_WEBIDE_WD}/
|
COPY src/demo/source_code_server/login_component.py ${TFW_WEBIDE_WD}/
|
||||||
|
|
||||||
RUN chown -R ${AVATAO_USER} ${TFW_WEBIDE_WD} && chmod -R 755 ${TFW_WEBIDE_WD}
|
RUN chown -R ${AVATAO_USER} ${TFW_WEBIDE_WD} &&\
|
||||||
|
chmod -R 755 ${TFW_WEBIDE_WD}
|
||||||
|
|
||||||
USER ${AVATAO_USER}
|
USER ${AVATAO_USER}
|
||||||
|
VOLUME ["/etc/nginx", "/home/${AVATAO_USER}", "/var/lib/nginx", "/var/log/nginx"]
|
||||||
WORKDIR /home/${AVATAO_USER}
|
WORKDIR /home/${AVATAO_USER}
|
||||||
|
|
||||||
CMD . "$HOME/.pyenvrc" && exec supervisord --nodaemon
|
CMD . "$HOME/.pyenvrc" && exec supervisord --nodaemon
|
||||||
|
@ -106,7 +106,7 @@ class SourceCodeEventHandler(TriggerlessEventHandler):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
data['content'] = 'No files in this directory :('
|
data['content'] = 'No files in this directory :('
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
log.exception('Failed to select directory "{}"'.format(data['directory']))
|
log.error('Failed to select directory "{}"'.format(data['directory']))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def attach_fileinfo(self, data):
|
def attach_fileinfo(self, data):
|
||||||
|
@ -1,18 +1,7 @@
|
|||||||
from itertools import cycle
|
|
||||||
|
|
||||||
from tfw.networking.serialization import deserialize_all
|
from tfw.networking.serialization import deserialize_all
|
||||||
from tfw.networking.event_handlers.server_connector import ServerConnector
|
from tfw.networking.event_handlers.server_connector import ServerConnector
|
||||||
|
|
||||||
|
|
||||||
def cenator():
|
|
||||||
yield from [
|
|
||||||
'**Your time is up**',
|
|
||||||
'`My time is now`',
|
|
||||||
'_You can\'t see me_',
|
|
||||||
'My time is now'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class EventHandlerBase:
|
class EventHandlerBase:
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
self.server_connector = ServerConnector()
|
self.server_connector = ServerConnector()
|
||||||
@ -21,13 +10,9 @@ class EventHandlerBase:
|
|||||||
self.subscribe(self.key)
|
self.subscribe(self.key)
|
||||||
self.subscribe('reset')
|
self.subscribe('reset')
|
||||||
self.server_connector.register_callback(self.event_handler_callback)
|
self.server_connector.register_callback(self.event_handler_callback)
|
||||||
self.cenerator = cycle(cenator())
|
|
||||||
|
|
||||||
def event_handler_callback(self, msg_parts):
|
def event_handler_callback(self, msg_parts):
|
||||||
key, message = deserialize_all(*msg_parts)
|
key, message = deserialize_all(*msg_parts)
|
||||||
from .message_sender import MessageSender
|
|
||||||
ms = MessageSender()
|
|
||||||
ms.send('avataobot', next(self.cenerator))
|
|
||||||
response = self.dispatch_handling(key, message)
|
response = self.dispatch_handling(key, message)
|
||||||
if response is None: return
|
if response is None: return
|
||||||
self.server_connector.send(key, response)
|
self.server_connector.send(key, response)
|
||||||
|
@ -25,6 +25,10 @@ class ServerUplinkConnector(ZMQConnectorBase):
|
|||||||
self._zmq_push_socket = self._zmq_context.socket(zmq.PUSH)
|
self._zmq_push_socket = self._zmq_context.socket(zmq.PUSH)
|
||||||
self._zmq_push_socket.connect('tcp://localhost:{}'.format(tfwenv.RECEIVER_PORT))
|
self._zmq_push_socket.connect('tcp://localhost:{}'.format(tfwenv.RECEIVER_PORT))
|
||||||
|
|
||||||
|
def send_to_eventhandler(self, key, response):
|
||||||
|
response['data']['key'] = key
|
||||||
|
self.send('mirror', response)
|
||||||
|
|
||||||
def send(self, key, response):
|
def send(self, key, response):
|
||||||
response['key'] = key
|
response['key'] = key
|
||||||
self._zmq_push_socket.send_multipart(serialize_all(key, response))
|
self._zmq_push_socket.send_multipart(serialize_all(key, response))
|
||||||
|
@ -21,12 +21,23 @@ class ZMQWebSocketHandler(WebSocketHandler):
|
|||||||
log.debug('WebSocket connection initiated')
|
log.debug('WebSocket connection initiated')
|
||||||
self._event_handler_connector.register_callback(self.zmq_callback)
|
self._event_handler_connector.register_callback(self.zmq_callback)
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def zmq_callback(msg_parts):
|
def zmq_callback(cls, msg_parts):
|
||||||
|
keyhandlers = {'mirror': cls.mirror}
|
||||||
|
|
||||||
key, data = deserialize_all(*msg_parts)
|
key, data = deserialize_all(*msg_parts)
|
||||||
log.debug('Received on pull socket: {}'.format(data))
|
log.debug('Received on pull socket: {}'.format(data))
|
||||||
for instance in ZMQWebSocketHandler.instances:
|
if key not in keyhandlers:
|
||||||
instance.write_message(data)
|
for instance in cls.instances:
|
||||||
|
instance.write_message(data)
|
||||||
|
else:
|
||||||
|
try: keyhandlers[key](data['data'])
|
||||||
|
except KeyError: log.error('Invalid mirror message format! Ignoring.')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mirror(cls, data):
|
||||||
|
key = data['key']
|
||||||
|
cls._event_handler_connector.send_message({'data': data}, key)
|
||||||
|
|
||||||
def on_message(self, message):
|
def on_message(self, message):
|
||||||
log.debug('Received on WebSocket: {}'.format(message))
|
log.debug('Received on WebSocket: {}'.format(message))
|
||||||
|
22
nginx/default.conf
Normal file
22
nginx/default.conf
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
server {
|
||||||
|
listen ${TFW_PUBLIC_PORT};
|
||||||
|
server_name localhost;
|
||||||
|
proxy_connect_timeout 7d;
|
||||||
|
proxy_send_timeout 7d;
|
||||||
|
proxy_read_timeout 7d;
|
||||||
|
|
||||||
|
location = /ws {
|
||||||
|
proxy_pass http://127.0.0.1:${TFW_WEB_PORT};
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
include ${TFW_NGINX_COMPONENTS}/*.conf;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
index index.html;
|
||||||
|
try_files $uri $uri/ /index.html =404;
|
||||||
|
root ${TFW_FRONTEND_DIR};
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,24 @@
|
|||||||
server {
|
worker_processes auto;
|
||||||
listen ${TFW_PUBLIC_PORT};
|
pid /tmp/nginx.pid;
|
||||||
server_name localhost;
|
|
||||||
proxy_connect_timeout 7d;
|
|
||||||
proxy_send_timeout 7d;
|
|
||||||
proxy_read_timeout 7d;
|
|
||||||
|
|
||||||
location = /ws {
|
events
|
||||||
proxy_pass http://127.0.0.1:${TFW_WEB_PORT};
|
{
|
||||||
proxy_http_version 1.1;
|
worker_connections 1024;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
}
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
}
|
http
|
||||||
|
{
|
||||||
include ${TFW_NGINX_COMPONENTS}/*.conf;
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
location / {
|
tcp_nodelay on;
|
||||||
root ${TFW_FRONTEND_DIR};
|
keepalive_timeout 65;
|
||||||
try_files $uri $uri/ index.html;
|
|
||||||
}
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
access_log /dev/stdout;
|
||||||
|
error_log /dev/stderr;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
include /etc/nginx/sites-enabled/*;
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,32 @@ from tfw.components.source_code_event_handler import SourceCodeEventHandler
|
|||||||
from tfw.components.terminado_event_handler import TerminadoEventHandler
|
from tfw.components.terminado_event_handler import TerminadoEventHandler
|
||||||
from tfw.components.process_managing_event_handler import ProcessManagingEventHandler
|
from tfw.components.process_managing_event_handler import ProcessManagingEventHandler
|
||||||
from tfw.config import tfwenv
|
from tfw.config import tfwenv
|
||||||
|
from tfw.message_sender import MessageSender
|
||||||
|
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector
|
||||||
from tfw.config.logs import logging
|
from tfw.config.logs import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def cenator(history):
|
||||||
|
log.debug('User executed command: "{}"'.format(history[-1]))
|
||||||
|
MessageSender().send('JOHN CENA', 'You\'ve executed "{}"'.format(history[-1]))
|
||||||
|
|
||||||
|
|
||||||
|
def selectdir(history):
|
||||||
|
try:
|
||||||
|
cmd = history[-1].split()
|
||||||
|
if cmd[0] == 'selectdir':
|
||||||
|
ServerUplinkConnector().send_to_eventhandler('webide',
|
||||||
|
{'data': {'command': 'selectdir',
|
||||||
|
'directory': cmd[1]}})
|
||||||
|
except Exception:
|
||||||
|
log.exception('Selectdir failed!')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ide = SourceCodeEventHandler(key='webide', directory=tfwenv.WEBIDE_WD, exclude=['__pycache__'])
|
ide = SourceCodeEventHandler(key='webide', directory=tfwenv.WEBIDE_WD, exclude=['__pycache__'])
|
||||||
terminado = TerminadoEventHandler(key='shell')
|
terminado = TerminadoEventHandler(key='shell')
|
||||||
terminado.historymonitor.subscribe_callback(callback=lambda hist: log.debug('User executed command: "{}"'.format(hist[-1])))
|
terminado.historymonitor.subscribe_callback(cenator)
|
||||||
|
terminado.historymonitor.subscribe_callback(selectdir)
|
||||||
processmanager = ProcessManagingEventHandler(key='processmanager', dirmonitor=ide.monitor)
|
processmanager = ProcessManagingEventHandler(key='processmanager', dirmonitor=ide.monitor)
|
||||||
|
|
||||||
eventhandlers = {ide, terminado, processmanager}
|
eventhandlers = {ide, terminado, processmanager}
|
||||||
|
Loading…
Reference in New Issue
Block a user