Download logs, improved output, css fixes for medium screen size
This commit is contained in:
parent
2b45e00347
commit
c305611b9c
5 changed files with 53 additions and 15 deletions
22
warp/hook.py
22
warp/hook.py
|
@ -4,6 +4,7 @@ import argparse
|
||||||
|
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from multiprocessing import Queue
|
from multiprocessing import Queue
|
||||||
|
from os import fdopen, path
|
||||||
|
|
||||||
from . import argparser_wrapper
|
from . import argparser_wrapper
|
||||||
from . import views
|
from . import views
|
||||||
|
@ -31,7 +32,6 @@ class QueuedOut(io.StringIO):
|
||||||
self.seek(0)
|
self.seek(0)
|
||||||
self.truncate(0)
|
self.truncate(0)
|
||||||
|
|
||||||
|
|
||||||
class FlaskThread(Thread):
|
class FlaskThread(Thread):
|
||||||
def __init__(self, port, host):
|
def __init__(self, port, host):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -41,15 +41,29 @@ class FlaskThread(Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
views.app.run(port=self.port, threaded=True, host=self.host)
|
views.app.run(port=self.port, threaded=True, host=self.host)
|
||||||
|
|
||||||
|
class Output():
|
||||||
|
def __init__(self, queue, restart):
|
||||||
|
self._queue = queue
|
||||||
|
self._restart = restart
|
||||||
|
self.cache = []
|
||||||
|
|
||||||
|
def get_output(self):
|
||||||
|
def gen_output():
|
||||||
|
while not self._restart.is_set():
|
||||||
|
msg_type, line = self._queue.get()
|
||||||
|
self.cache.append((msg_type, line))
|
||||||
|
yield (msg_type, line)
|
||||||
|
return gen_output()
|
||||||
|
|
||||||
def start_module(name, is_module):
|
def start_module(name, is_module):
|
||||||
views.app.restart.clear()
|
views.app.restart.clear()
|
||||||
views.app.name = ""
|
views.app.name = path.basename(name)
|
||||||
views.app.desc = ""
|
views.app.desc = ""
|
||||||
views.app.actions = []
|
views.app.actions = []
|
||||||
views.app.queue = Queue()
|
views.app.queue = Queue()
|
||||||
ioout = QueuedOut("out", views.app.queue)
|
ioout = QueuedOut("out", views.app.queue)
|
||||||
ioerr = QueuedOut("err", views.app.queue)
|
ioerr = QueuedOut("err", views.app.queue)
|
||||||
|
views.app.output = Output(views.app.queue, views.app.restart)
|
||||||
|
|
||||||
views.app.actionQueue = Queue() # This holds only one Argparser Object
|
views.app.actionQueue = Queue() # This holds only one Argparser Object
|
||||||
views.app.namespaceQueue = Queue() # This hold only one Namespace Object
|
views.app.namespaceQueue = Queue() # This hold only one Namespace Object
|
||||||
|
@ -65,6 +79,10 @@ def start_module(name, is_module):
|
||||||
is_module = is_module
|
is_module = is_module
|
||||||
)
|
)
|
||||||
views.app.module_process.start()
|
views.app.module_process.start()
|
||||||
|
views.app.mutex_groups, views.app.actions, name, views.app.desc = views.app.actionQueue.get()
|
||||||
|
if name:
|
||||||
|
app.name = name
|
||||||
|
|
||||||
views.app.module_process.join()
|
views.app.module_process.join()
|
||||||
|
|
||||||
ioerr.write("Process stopped ({})\n".format(views.app.module_process.exitcode))
|
ioerr.write("Process stopped ({})\n".format(views.app.module_process.exitcode))
|
||||||
|
|
|
@ -18,6 +18,11 @@ li.action{
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li.subparser {
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
#arguments {
|
#arguments {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +59,7 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
li.action {
|
li.action {
|
||||||
padding: 1rem 1rem 1rem 1rem;
|
padding: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unlock-button {
|
.unlock-button {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
function createSubparserAction(action) {
|
function createSubparserAction(action) {
|
||||||
var column = $("<li/>").addClass("action");//.addClass("column small-12 medium-12")
|
var column = $("<li/>").addClass("action subparser");//.addClass("column small-12 medium-12")
|
||||||
//var card = $("<div/>").addClass("card action").appendTo(column);
|
//var card = $("<div/>").addClass("card action").appendTo(column);
|
||||||
var label = $("<label/>", {for: action['uuid']}).appendTo(column);
|
var label = $("<label/>", {for: action['uuid']}).appendTo(column);
|
||||||
var center = $("<center/>").appendTo(label);
|
var center = $("<center/>").appendTo(label);
|
||||||
|
|
|
@ -24,15 +24,16 @@
|
||||||
<button type="button" style="display: none;" class="button secondary" id="resumeButton" onclick="resumeProcess()"> <i class="fi-play"></i> </button>
|
<button type="button" style="display: none;" class="button secondary" id="resumeButton" onclick="resumeProcess()"> <i class="fi-play"></i> </button>
|
||||||
<button type="button" class="button alert disabled" disabled id="stopButton" onclick="stopProcess()"> <i class="fi-stop"></i> </button>
|
<button type="button" class="button alert disabled" disabled id="stopButton" onclick="stopProcess()"> <i class="fi-stop"></i> </button>
|
||||||
<button type="button" class="button disabled" disabled id="reloadButton" onclick="reloadProcess()"> <i class="fi-refresh"></i> </button>
|
<button type="button" class="button disabled" disabled id="reloadButton" onclick="reloadProcess()"> <i class="fi-refresh"></i> </button>
|
||||||
|
<button type="button" class="button" onclick="window.open('/download')"> <i class="fi-download"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns large-3 medium-4 small-12" id="arguments">
|
<div class="columns large-3 medium-5 small-12" id="arguments">
|
||||||
<ul id="actions" class="vertical menu">
|
<ul id="actions" class="vertical menu">
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns large-9 medium-8 small-12" id="output_wrap">
|
<div class="columns large-9 medium-7 small-12" id="output_wrap">
|
||||||
<div id="output"></div>
|
<div id="output"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,10 @@ import signal
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import argparse
|
import argparse
|
||||||
from flask import Flask, render_template, request, Response, jsonify
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import Flask, render_template, request, Response, \
|
||||||
|
jsonify, send_file, make_response
|
||||||
|
|
||||||
# Initialize global variables
|
# Initialize global variables
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -30,10 +33,8 @@ def parse_argument(name, json, action):
|
||||||
def fill_namespace():
|
def fill_namespace():
|
||||||
json = dict(request.form)
|
json = dict(request.form)
|
||||||
namespace = argparse.Namespace()
|
namespace = argparse.Namespace()
|
||||||
if app.actions == []:
|
|
||||||
if not app.actionQueue.empty():
|
|
||||||
app.mutex_groups, app.actions, app.name, app.desc = app.actionQueue.get()
|
|
||||||
all_actions = app.actions
|
all_actions = app.actions
|
||||||
|
|
||||||
for group in app.mutex_groups:
|
for group in app.mutex_groups:
|
||||||
all_actions.extend(group.actions)
|
all_actions.extend(group.actions)
|
||||||
|
|
||||||
|
@ -47,9 +48,6 @@ def fill_namespace():
|
||||||
|
|
||||||
@app.route("/arguments", methods=['GET'])
|
@app.route("/arguments", methods=['GET'])
|
||||||
def get_arguments():
|
def get_arguments():
|
||||||
if app.actions == []:
|
|
||||||
if not app.actionQueue.empty():
|
|
||||||
app.mutex_groups, app.actions, app.name, app.desc = app.actionQueue.get()
|
|
||||||
return jsonify({'actions': [a.as_dict() for a in app.actions],
|
return jsonify({'actions': [a.as_dict() for a in app.actions],
|
||||||
'groups': [g.as_dict() for g in app.mutex_groups]})
|
'groups': [g.as_dict() for g in app.mutex_groups]})
|
||||||
|
|
||||||
|
@ -77,16 +75,32 @@ def reload():
|
||||||
app.restart.set()
|
app.restart.set()
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
|
@app.route("/download", methods=['GET'])
|
||||||
|
def download():
|
||||||
|
output = "\n".join([line for msg_type, line in app.output.cache])
|
||||||
|
response = make_response(output)
|
||||||
|
response.headers["Content-Disposition"] = \
|
||||||
|
"attachment; filename=%s_%s.log" \
|
||||||
|
% (app.name, datetime.now().strftime('%Y%m%d-%H%M%S'))
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.route("/output.json", methods=['GET'])
|
@app.route("/output.json", methods=['GET'])
|
||||||
def output():
|
def output():
|
||||||
def generate():
|
def generate():
|
||||||
yield '{"output":['
|
yield '{"output":['
|
||||||
while not app.restart.is_set():
|
cache = app.output.cache
|
||||||
msg_type, line = app.queue.get()
|
for msg_type, line in cache:
|
||||||
|
yield json.dumps({'type' : msg_type, 'line': line})
|
||||||
|
yield ','
|
||||||
|
|
||||||
|
output = app.output.get_output()
|
||||||
|
for msg_type, line in output:
|
||||||
print("Send ({}): {} (length: {})".format(msg_type, line, len(line)), file=sys.__stdout__)
|
print("Send ({}): {} (length: {})".format(msg_type, line, len(line)), file=sys.__stdout__)
|
||||||
yield json.dumps({'type' : msg_type, 'line': line})
|
yield json.dumps({'type' : msg_type, 'line': line})
|
||||||
yield ','
|
yield ','
|
||||||
yield '\{\}]}'
|
yield '\{\}]}'
|
||||||
|
|
||||||
return Response(generate(), mimetype="application/json")
|
return Response(generate(), mimetype="application/json")
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue