Commit 8bac3eb6 authored by Daniele Venzano's avatar Daniele Venzano
Browse files

Implement base app shop functionality

Set also the final logo and work on the general web ui refactoring
parent 8aef786d
......@@ -100,6 +100,9 @@ class APIEndpoint:
def execution_delete(self, uid, role, exec_id):
"""Delete an execution."""
if role != "admin":
raise zoe_api.exceptions.ZoeAuthException()
e = self.sql.execution_list(id=exec_id, only_one=True)
assert isinstance(e, zoe_lib.state.sql_manager.Execution)
if e is None:
......
sonar.projectName=zoe_api
sonar.host.url=http://your-sonarqube-server-address
sonar.sources=.
sonar.language=py
sonar.sourceEncoding=UTF-8
......@@ -22,6 +22,7 @@ import tornado.web
import zoe_api.web.start
import zoe_api.web.websockets
import zoe_api.web.executions
import zoe_api.web.zapp_shop
from zoe_lib.version import ZOE_API_VERSION, ZOE_VERSION
......@@ -46,7 +47,11 @@ def web_init(api_endpoint) -> List[tornado.web.URLSpec]:
tornado.web.url(r'/executions/inspect/([0-9]+)', zoe_api.web.executions.ExecutionInspectWeb, route_args, name='execution_inspect'),
tornado.web.url(r'/service/logs/([0-9]+)', zoe_api.web.executions.ServiceLogsWeb, route_args, name='service_logs'),
tornado.web.url(r'/websocket', zoe_api.web.websockets.WebSocketEndpointWeb, route_args, name='websocket')
tornado.web.url(r'/websocket', zoe_api.web.websockets.WebSocketEndpointWeb, route_args, name='websocket'),
tornado.web.url(r'/zapp-shop', zoe_api.web.zapp_shop.ZAppShopHomeWeb, route_args, name='zappshop'),
tornado.web.url(r'/zapp-shop/logo/([a-z\-.]+)', zoe_api.web.zapp_shop.ZAppLogoWeb, route_args, name='zappshop_logo'),
tornado.web.url(r'/zapp-shop/start/([a-z\-.]+)', zoe_api.web.zapp_shop.ZAppStartWeb, route_args, name='zappshop_start')
]
return web_routes
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4147"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="379.92499"
height="271.62421"
viewBox="0 0 379.92499 271.6242"
sodipodi:docname="logo.svg"><metadata
id="metadata4153"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4151"><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4161"><path
d="m 0,1.2207e-4 720,0 0,539.99999793 -720,0 L 0,1.2207e-4 Z"
id="path4163"
inkscape:connector-curvature="0"
style="clip-rule:evenodd" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4179"><path
d="m 0,6.104e-6 720,0 L 720,540.00001 l -720,0 L 0,6.104e-6 Z"
id="path4181"
inkscape:connector-curvature="0"
style="clip-rule:evenodd" /></clipPath><mask
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="1"
height="1"
id="mask4185"><image
width="1"
height="1"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHMAAAA3CAAAAAAa4SpAAAAAAXNCSVQI5gpbmQAABAFJREFUWIW1WTGLE0EU/nYIhysrFzCgQdnG6Gk4hO1SKKw2adOmTp3K5vr8gIBt/kAsLQKKjbCNcFXAQjyLFcTDQ10RQW1ci+zOvDc7M7t7cK+ayew335t5b97Me/FgEm+/dxPAn3f4YRyvly7aQL1omRNJjoaiHZ03XGQ77HIR9xsAglmWV+Ro0JyxN+fY7WTPDRCLKuEOGTVj7G4M4JVL5UFqoczzPAnrGcXcAt4EFoRnQxQy82ooI4fKYyOik7gp8zzxXYyezS47WRnMKmop8zx1kAbb1mBvXU/pIo3qwUlHw2iU2+U0juN5RZHU4vizCoPhyK25QzD3Sadq5iDi3r8xMXorPvlmJAD43WjKvWpJQT06Mtb80z+io7Mq5R53haRHxkLmWdR7if1NRymgkw71UZ8tJh1pw/TQZ8ofpmT5xkNIj26mKdVllOuqwQWJ3wupKIHYzj1xkhUb6DFnmRjBZH/LmK+WubGHGqIsXQqjTG23iPL/dbF2BetaKSGUzcnMA7pIe5wi4B1FLPtTOyUQSNWUXzLKlSMeRxqH1GHrDuIlLjVTGg4REbm7KQCEElV3R860rW1BSSJAH8CEaeCUOM3zxEwZ12ETqpxctdnPuXSVl7WjVF6zBjyJczitQVpSoiM/9tAvm9mFUgLyruiL6+VvL1tRnpDOo9dNIC/KxoHYL5uvLpYSx2VjpN7Lny6WEl/LxjUhXf9vY8reMek0pVScfXG5MZWkPCEe3phSyQ3xrWw2PSrnpfwlW+J92bp7sZS4VDZ+irOy+fB8lCKMe9avqVwpG+9JfGiS8rErOkaRL2xqUi8AwIgEXDlL5XHVgLKIYrZnL5UVwclHx6IWNtAp5QWR1OVPZD9DYCg7zhQIphirLohlDRZjakMhO0duVFyhJJzudw2wJ7doCZCNdi90UqVkj3H3K0M9N4cAcShzMlLIzETJttsVVBRHcTyUsnMbxmO1lFgNkAd+qud6SohqhQEj42xUfJYFsY9ISlZJMEsJlb9nZRQgVjG6QsjyA65Xh4AtpNQTpNVpkryohCOPJ7T6VgREodRgU5+aZa1+pz9nWv7Z44WCaq2nT8G6Rh2WvJJcEB6zVzofyMX2eQqdmeL5iH6xnah590ZrE7pYk/9Z25Vnz0+BsztPHrBfP977beDE/KkGPgWAx/f1725/YN0wbyAbm2O6S0OlxDosNBQ6NJnbA3kTUkOgChyVMxumBanJpYGOsyy1tZUJC5m4wHm+spllbN/fae0FOXQYx1WKFRMz0FoLZeBqMWwnaexWWEyqZm1aMIY/N1XcototAoIxiwObFoVxIJxRcLYwFfPNOnhXD4Fbh/jy5u33f20oAQCdAP6B40+L/3nrWx5j2o+vAAAAAElFTkSuQmCC"
id="image4187" /></mask></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview4149"
showgrid="false"
inkscape:zoom="0.78462664"
inkscape:cx="-10.9329"
inkscape:cy="178.9348"
inkscape:current-layer="g4155"
fit-margin-top="10"
fit-margin-left="10"
fit-margin-right="10"
fit-margin-bottom="10" /><g
id="g4155"
inkscape:groupmode="layer"
inkscape:label="logo"
transform="matrix(1.25,0,0,-1.25,-219.625,427.6)"><path
d="m 273.4,308.82 c 5.56,0 10.36,-1.74 14.4,-5.21 4.03,-3.47 6.05,-7.83 6.05,-13.09 0,-3.21 -2.99,-6.3 -8.97,-9.29 l -1.29,-0.65 c -3.75,-1.87 -22.3,-20.98 -55.65,-57.31 -3.44,-3.7 -9.37,-10.95 -17.79,-21.74 -7.51,-10.74 -11.26,-17.1 -11.26,-19.08 0,-0.4 1.99,-0.61 5.97,-0.61 4.46,0 12.38,0.94 23.76,2.8 9.75,1.72 17.73,2.58 23.94,2.58 5.48,0 11.37,-0.44 17.67,-1.32 10.16,-1.31 15.24,-3.46 15.24,-6.45 0,-3.76 -2.52,-5.63 -7.56,-5.63 -1.35,0 -3.89,0.25 -7.61,0.75 -3.73,0.5 -5.99,0.75 -6.79,0.75 -5.23,0 -13.01,-0.79 -23.32,-2.36 l -21.53,-3.2 c -1.47,-0.14 -5.24,-1.06 -11.28,-2.75 -5.6,-1.62 -9.52,-2.43 -11.76,-2.43 -3.84,0 -6.87,1.75 -9.09,5.27 -1.84,2.3 -2.76,5.28 -2.76,8.95 0,4.24 4.34,12.91 13.01,26 8.29,12.28 15.76,21.88 22.44,28.79 l 33.38,38.67 c 11.4,13.07 17.1,20.16 17.1,21.26 0,0.41 -1.85,0.61 -5.54,0.61 -18.25,0 -36.31,-2.5 -54.17,-7.48 -2.48,-0.77 -4.09,-1.42 -4.83,-1.95 -0.74,-0.53 -1.04,-1.75 -0.9,-3.68 -6.21,0 -9.32,1.88 -9.32,5.63 0,4.66 3.92,8.22 11.75,10.68 4.74,1.42 12.21,3.12 22.43,5.11 22.3,4.25 37.06,6.38 44.28,6.38 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path4167"
inkscape:connector-curvature="0" /><path
d="m 273.4,308.82 c 5.56,0 10.36,-1.74 14.4,-5.21 4.03,-3.47 6.05,-7.83 6.05,-13.09 0,-3.21 -2.99,-6.3 -8.97,-9.29 l -1.29,-0.65 c -3.75,-1.87 -22.3,-20.98 -55.65,-57.31 -3.44,-3.7 -9.37,-10.95 -17.79,-21.74 -7.51,-10.74 -11.26,-17.1 -11.26,-19.08 0,-0.4 1.99,-0.61 5.97,-0.61 4.46,0 12.38,0.94 23.76,2.8 9.75,1.72 17.73,2.58 23.94,2.58 5.48,0 11.37,-0.44 17.67,-1.32 10.16,-1.31 15.24,-3.46 15.24,-6.45 0,-3.76 -2.52,-5.63 -7.56,-5.63 -1.35,0 -3.89,0.25 -7.61,0.75 -3.73,0.5 -5.99,0.75 -6.79,0.75 -5.23,0 -13.01,-0.79 -23.32,-2.36 l -21.53,-3.2 c -1.47,-0.14 -5.24,-1.06 -11.28,-2.75 -5.6,-1.62 -9.52,-2.43 -11.76,-2.43 -3.84,0 -6.87,1.75 -9.09,5.27 -1.84,2.3 -2.76,5.28 -2.76,8.95 0,4.24 4.34,12.91 13.01,26 8.29,12.28 15.76,21.88 22.44,28.79 l 33.38,38.67 c 11.4,13.07 17.1,20.16 17.1,21.26 0,0.41 -1.85,0.61 -5.54,0.61 -18.25,0 -36.31,-2.5 -54.17,-7.48 -2.48,-0.77 -4.09,-1.42 -4.83,-1.95 -0.74,-0.53 -1.04,-1.75 -0.9,-3.68 -6.21,0 -9.32,1.88 -9.32,5.63 0,4.66 3.92,8.22 11.75,10.68 4.74,1.42 12.21,3.12 22.43,5.11 22.3,4.25 37.06,6.38 44.28,6.38 z"
style="fill:none;stroke:#000000;stroke-width:0.14;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4169"
inkscape:connector-curvature="0" /><path
d="m 332.58,285.49 c -7.99,0 -15.44,-9.85 -22.35,-29.56 -4.67,-15.36 -7,-29.45 -7,-42.25 0,-24.27 7.15,-36.41 21.45,-36.41 20.26,0 30.39,22.97 30.39,68.9 0,10.03 -1.46,18.56 -4.36,25.61 -3.83,9.14 -9.87,13.71 -18.13,13.71 z m 115.06,5.22 c 5.48,0 9.3,-0.42 11.45,-1.26 4.88,-1.53 7.32,-4.67 7.32,-9.43 0,-4.6 -1.54,-6.9 -4.63,-6.9 -1.53,1.67 -3.53,3.36 -6,5.08 -1.61,0.85 -4.03,1.28 -7.28,1.28 -12.31,0 -24.47,-1.71 -36.49,-5.11 -16.44,-4.68 -24.66,-11.22 -24.66,-19.61 0,-3.33 2.12,-5.84 6.35,-7.53 4.77,-1.61 9.57,-2.41 14.41,-2.41 1.73,0 7.01,0.33 15.85,1.01 8.83,0.58 14.03,0.79 15.58,0.63 2.22,-1.53 3.25,-3.84 3.12,-6.9 -0.3,-3.11 -1.85,-5.1 -4.68,-5.98 -2.84,1.61 -4.78,2.41 -5.8,2.41 -9.72,0 -20.67,-2.48 -32.86,-7.45 -15.89,-6.57 -23.83,-15.08 -23.83,-25.51 0,-8.49 4.86,-14.66 14.59,-18.53 9.48,-3.22 19.55,-4.82 30.23,-4.82 4.25,0 9.71,0.56 16.37,1.69 7.61,1.23 12.77,2.55 15.47,3.96 5.4,2.86 8.7,4.67 9.9,5.44 l 0,5.58 c 6.34,0 9.52,-1.73 9.52,-5.18 0,-6.72 -7.52,-12.44 -22.55,-17.17 -11.46,-3.59 -21.26,-5.38 -29.39,-5.38 -12.92,0 -24.18,2.4 -33.79,7.21 -12.45,6.28 -18.67,15.57 -18.67,27.88 0,8.43 3.33,15.8 9.99,22.1 4.4,4.18 10.87,8.03 19.4,11.54 -5.08,1.18 -8.9,2.91 -11.46,5.17 -4.04,3.74 -6.07,8.51 -6.07,14.3 0,12.3 9.22,21.5 27.65,27.6 12.69,4.2 26.34,6.29 40.96,6.29 z m -124.85,3.95 c 0.8,0 2.07,-0.4 3.78,-1.2 0.68,0.46 1.39,0.69 2.14,0.69 24.14,-1.58 36.22,-17.86 36.22,-48.84 0,-18.27 -2.16,-33.88 -6.47,-46.81 -6.68,-19.92 -17.54,-29.88 -32.58,-29.88 -11.53,0 -20.5,4.84 -26.91,14.51 -5.57,8.42 -8.36,18.48 -8.36,30.21 0,11.36 1.41,23.32 4.21,35.88 2.98,13 7.27,23.4 12.89,31.19 2.57,3.74 4.48,6.47 5.74,8.19 3.23,4.04 6.35,6.06 9.34,6.06 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path4171"
inkscape:connector-curvature="0" /><path
d="m 332.58,285.49 c -7.99,0 -15.44,-9.85 -22.35,-29.56 -4.67,-15.36 -7,-29.45 -7,-42.25 0,-24.27 7.15,-36.41 21.45,-36.41 20.26,0 30.39,22.97 30.39,68.9 0,10.03 -1.46,18.56 -4.36,25.61 -3.83,9.14 -9.87,13.71 -18.13,13.71 z m 115.06,5.22 c 5.48,0 9.3,-0.42 11.45,-1.26 4.88,-1.53 7.32,-4.67 7.32,-9.43 0,-4.6 -1.54,-6.9 -4.63,-6.9 -1.53,1.67 -3.53,3.36 -6,5.08 -1.61,0.85 -4.03,1.28 -7.28,1.28 -12.31,0 -24.47,-1.71 -36.49,-5.11 -16.44,-4.68 -24.66,-11.22 -24.66,-19.61 0,-3.33 2.12,-5.84 6.35,-7.53 4.77,-1.61 9.57,-2.41 14.41,-2.41 1.73,0 7.01,0.33 15.85,1.01 8.83,0.58 14.03,0.79 15.58,0.63 2.22,-1.53 3.25,-3.84 3.12,-6.9 -0.3,-3.11 -1.85,-5.1 -4.68,-5.98 -2.84,1.61 -4.78,2.41 -5.8,2.41 -9.72,0 -20.67,-2.48 -32.86,-7.45 -15.89,-6.57 -23.83,-15.08 -23.83,-25.51 0,-8.49 4.86,-14.66 14.59,-18.53 9.48,-3.22 19.55,-4.82 30.23,-4.82 4.25,0 9.71,0.56 16.37,1.69 7.61,1.23 12.77,2.55 15.47,3.96 5.4,2.86 8.7,4.67 9.9,5.44 l 0,5.58 c 6.34,0 9.52,-1.73 9.52,-5.18 0,-6.72 -7.52,-12.44 -22.55,-17.17 -11.46,-3.59 -21.26,-5.38 -29.39,-5.38 -12.92,0 -24.18,2.4 -33.79,7.21 -12.45,6.28 -18.67,15.57 -18.67,27.88 0,8.43 3.33,15.8 9.99,22.1 4.4,4.18 10.87,8.03 19.4,11.54 -5.08,1.18 -8.9,2.91 -11.46,5.17 -4.04,3.74 -6.07,8.51 -6.07,14.3 0,12.3 9.22,21.5 27.65,27.6 12.69,4.2 26.34,6.29 40.96,6.29 z m -124.85,3.95 c 0.8,0 2.07,-0.4 3.78,-1.2 0.68,0.46 1.39,0.69 2.14,0.69 24.14,-1.58 36.22,-17.86 36.22,-48.84 0,-18.27 -2.16,-33.88 -6.47,-46.81 -6.68,-19.92 -17.54,-29.88 -32.58,-29.88 -11.53,0 -20.5,4.84 -26.91,14.51 -5.57,8.42 -8.36,18.48 -8.36,30.21 0,11.36 1.41,23.32 4.21,35.88 2.98,13 7.27,23.4 12.89,31.19 2.57,3.74 4.48,6.47 5.74,8.19 3.23,4.04 6.35,6.06 9.34,6.06 z"
style="fill:none;stroke:#000000;stroke-width:0.14;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4173"
inkscape:connector-curvature="0" /><g
id="g4175"><g
id="g4177"
clip-path="url(#clipPath4179)"><g
id="g4183"
transform="matrix(41.4,0,0,19.68,310.92,314.4)"><image
width="1"
height="1"
preserveAspectRatio="none"
transform="matrix(1,0,0,-1,0,1)"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHMAAAA3CAYAAAA/inWcAAAABHNCSVQICAgIfAhkiAAAAJpJREFUeJzt0QEJACAQwMDX/p21hCCMuwSDrZk5Q8L+HcA7ZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoaYGWJmiJkhZoZcVWkBbaTUQzAAAAAASUVORK5CYII="
mask="url(#mask4185)"
id="image4189" /></g></g></g><path
d="m 329.1,327.95 0,4.21"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4191"
inkscape:connector-curvature="0" /><path
d="m 324.1,327.15 4.92,-0.04"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4193"
inkscape:connector-curvature="0" /><text
transform="matrix(1,0,0,-1,221.78,133.03)"
style="font-variant:normal;font-weight:normal;font-size:15.96000004px;font-family:'Times New Roman';-inkscape-font-specification:Times-Roman;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="text4195"><tspan
x="0 13.18296 27.2118 35.000278 45.789242 57.7752 64.11132 75.490799 89.519638 102.7026 108.2088 122.23764 136.26648 150.29532 160.9566 174.98544 187.2108 194.99928 208.18224"
y="0"
sodipodi:role="line"
id="tspan4197">BUILT FOR ANALYTICS</tspan></text>
</g></svg>
\ No newline at end of file
......@@ -133,3 +133,7 @@ textarea.logoutput {
padding-right: 1em;
padding-top: 0.4em;
}
.readable_description {
display: none;
}
function format_bytes(bytes, decimals) {
if(bytes === 0) {
document.write('0 Byte');
return;
}
var k = 1000;
var dm = decimals + 1 || 3;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
document.write((bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i]);
}
......@@ -5,55 +5,15 @@
<meta charset="UTF-8">
<title>{% block title %}{% endblock %} - Zoe</title>
<script src="/static/jquery-2.1.4.min.js" type="application/javascript"></script>
<script src="/static/jquery-ui-1.11.4/jquery-ui.min.js" type="application/javascript"></script>
<script src="/static/jquery.wizard.js" type="application/javascript"></script>
<script src="/static/jquery.validate.min.js" type="application/javascript"></script>
<script src="/static/sorttable.js" type="application/javascript"></script>
<script src="/static/moment.min.js" type="application/javascript"></script>
<script src="/static/zoe.js" type="application/javascript"></script>
<link rel="stylesheet" href="/static/zoe.css" type="text/css">
<link rel="stylesheet" href="/static/jquery-ui-1.11.4/jquery-ui.min.css">
{% endblock %}
{% block custom_head %}
{% endblock %}
</head>
<body>
<script>
/* function update_status() {
$.getJSON("")
.done(function( data ) {
$("#num_nodes").text(data.num_nodes);
$("#num_containers").text(data.num_containers);
}).error(function( data ) {
$("#num_nodes").text("N/A");
$("#num_containers").text("N/A");
});
}
update_status();
window.setInterval(update_status, 5000);
*/
moment.locale(window.navigator.userLanguage || window.navigator.language);
function format_timestamp(ts) {
document.write(moment(ts).calendar())
}
function format_bytes(bytes, decimals) {
if(bytes == 0) {
document.write('0 Byte');
return;
}
var k = 1000;
var dm = decimals + 1 || 3;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
document.write((bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i]);
}
</script>
{% if uid %}
<div id="userinfo">
{{ uid }} ({{ role }}) <a href="{{ reverse_url("logout") }}">logout</a>
</div>
{% endif %}
{% block content_header %}
{% endblock %}
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
......
{% extends "base.html" %}
{% block content_header %}
{% if uid %}
<div id="userinfo">
{{ uid }} ({{ role }}) <a href="{{ reverse_url("logout") }}">logout</a>
</div>
{% endif %}
{% endblock %}
{% block content %}
{{ super() }}
{% endblock %}
{% extends "base_user.html" %}
{% block title %}Home{% endblock %}
{% block custom_head %}
<script src="/static/sorttable.js" type="application/javascript"></script>
<script src="/static/moment.min.js" type="application/javascript"></script>
<script>
moment.locale(window.navigator.userLanguage || window.navigator.language);
function format_timestamp(ts) {
document.write(moment(ts).calendar())
}
</script>
{% endblock %}
{% block content %}
<h1>Zoe - Analytics on demand</h1>
......
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block custom_head %}
<script src="/static/jquery.validate.min.js" type="application/javascript"></script>
{% endblock %}
{% block content %}
<div id="loginbox">
<img alt="ZOE logo" src="{{ static_url("logo.svg") }}">
<img alt="ZOE logo" src="{{ static_url("logo.png") }}">
<div id="login-form">
<form action="/login" method="post" id="login_form">
<fieldset>
......@@ -21,4 +26,8 @@
</div>
</div>
<script>
$("#login_form").validate();
</script>
{% endblock %}
{% extends "base_user.html" %}
{% block title %}ZApp Shop{% endblock %}
{% block content %}
<h2>ZApp shop</h2>
{% for zapp_category in zapps|sort %}
<div class="zapp-category">
<h3>{{ zapp_category[0].category }}</h3>
{% for zapp in zapp_category %}
<div class="zapp">
<img src="{{ reverse_url("zappshop_logo", zapp.id) }}" alt="logo">
<p>{{ zapp.readable_name }}</p>
<button class="zapp-details" value="rd-{{ zapp.id }}">Details</button>
<button class="zapp-start" value="{{ zapp.id }}">Start</button>
<div class="readable_description" id="rd-{{ zapp.id }}">{{ zapp.readable_description|safe }}</div>
</div>
{% endfor %}
</div>
{% endfor %}
<script>
$("button.zapp-details").click(function () {
$('#'+$(this).attr('value')).toggle();
});
$("button.zapp-start").click(function () {
window.location.href = "{{ reverse_url('zappshop_start', '') }}" + $(this).attr('value');
});
</script>
{% endblock %}
# Copyright (c) 2017, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Zoe App shop web pages."""
import logging
from zoe_api import zapp_shop
from zoe_api.api_endpoint import APIEndpoint # pylint: disable=unused-import
from zoe_api.web.utils import get_auth_login, get_auth, catch_exceptions
from zoe_api.web.custom_request_handler import ZoeRequestHandler
log = logging.getLogger(__name__)
class ZAppShopHomeWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self):
"""Home page with authentication."""
uid, role = get_auth(self)
if uid is None:
return self.redirect(self.get_argument('next', u'/login'))
zapp_ids = zapp_shop.zshop_list_apps()
zapps = [zapp_shop.zshop_read_manifest(zapp_id) for zapp_id in zapp_ids]
template_vars = {
"uid": uid,
"role": role,
'zapps': zapps,
}
self.render('zapp_shop.html', **template_vars)
class ZAppLogoWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, zapp_id):
"""Home page with authentication."""
uid, role = get_auth(self)
if uid is None:
return self.redirect(self.get_argument('next', u'/login'))
self.set_header("Content-type", "image/png")
self.write(zapp_shop.get_logo(zapp_id))
class ZAppStartWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, zapp_id):
"""Home page with authentication."""
uid, role = get_auth(self)
if uid is None:
return self.redirect(self.get_argument('next', u'/login'))
zapp_ids = zapp_shop.zshop_list_apps()
zapps = [zapp_shop.zshop_read_manifest(zapp_id) for zapp_id in zapp_ids]
template_vars = {
"uid": uid,
"role": role,
'zapps': zapps,
}
self.render('zapp_shop.html', **template_vars)
# Copyright (c) 2017, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Zoe App shop module."""
import logging
import os
import json
import markdown
from zoe_lib.config import get_conf
log = logging.getLogger(__name__)
class ZAppParameter:
"""A ZApp parameter that should be exposed to the user interface."""
def __init__(self, param_manifest):
self.kind = param_manifest['kind']
self.name = param_manifest['name']
self.type = param_manifest['type']
self.default = param_manifest['default']
class ZApp:
"""A ZApp."""
def __init__(self, zapp_id, manifest, manifest_index):
self.id = zapp_id
self.category = manifest['category']
zapp = manifest['zapps'][manifest_index]
self.readable_name = zapp['name']
self.readable_description = self.read_description()
self.json_file = zapp['description']
self.zoe_description = self.parse_json_description()
self.parameters = []
self.parse_parameters(zapp)
def parse_parameters(self, zapp_manifest):
"""Translates the parameters from the manifest into objects."""
for param in zapp_manifest['parameters']:
self.parameters.append(ZAppParameter(param))
def read_description(self):
"""Reads and renders the README.md file."""
mdown = open(os.path.join(get_conf().zapp_shop_path, self.id, "README.md"), 'r', encoding='utf-8').read()
return markdown.markdown(mdown, extensions=['markdown.extensions.extra', 'markdown.extensions.codehilite'])
def parse_json_description(self):
"""Reads the classic json description."""
return json.load(open(os.path.join(get_conf().zapp_shop_path, self.id, self.json_file), 'r'))
def zshop_list_apps():
"""List the ZApp repos."""
dirs = [d for d in os.listdir(get_conf().zapp_shop_path) if os.path.isdir(os.path.join(get_conf().zapp_shop_path, d)) and os.path.exists(os.path.join(get_conf().zapp_shop_path, d, "manifest.json"))]
return dirs
def zshop_read_manifest(zapp_id):
"""Reads and decodes the manifest file."""
manifest_path = os.path.join(get_conf().zapp_shop_path, zapp_id, "manifest.json")
manifest = json.load(open(manifest_path))
zapps = []
for idx in range(len(manifest['zapps'])):
zapps.append(ZApp(zapp_id, manifest, idx))
return zapps
def get_logo(zapp_id):
"""Return the ZApp PNG logo image file contents."""
logo_path = os.path.join(get_conf().zapp_shop_path, zapp_id, 'logo.png')
return open(logo_path, "rb").read()
......@@ -80,6 +80,12 @@ def exec_list_cmd(auth, args):
print(tabulate(tabular_data, headers))
def exec_rm_cmd(auth, args):
"""Delete an execution and kill it if necessary."""
exec_api = ZoeExecutionsAPI(auth['url'], auth['user'], auth['pass'])
exec_api.delete(args.id)
ENV_HELP_TEXT = '''To authenticate with Zoe you need to define three environment variables:
ZOE_URL: point to the URL of the Zoe Scheduler (ex.: http://localhost:5000/
ZOE_USER: the username used for authentication
......@@ -121,6 +127,10 @@ def process_arguments() -> Tuple[ArgumentParser, Namespace]:
argparser_app_list.add_argument('--later-than-end', help='Show only executions ended later than this timestamp (seconds since UTC epoch)')
argparser_app_list.set_defaults(func=exec_list_cmd)
argparser_execution_rm = subparser.add_parser('exec-rm', help="Deletes an execution")
argparser_execution_rm.add_argument('id', type=int, help="Execution id")
argparser_execution_rm.set_defaults(func=exec_rm_cmd)
return parser, parser.parse_args()
......
......@@ -108,6 +108,8 @@ def load_configuration(test_conf=None):
argparser.add_argument('--kube-config-file', help='Kubernetes configuration file', default='/opt/zoe/kube.conf')
argparser.add_argument('--kube-namespace', help='The namespace that Zoe operates on', default='default')
# other options
argparser.add_argument('--zapp-shop-path', help='Path where ZApp folders are stored', default='/var/lib/zoe-apps')
argparser.add_argument('--cookie-secret', help='secret used to encrypt cookies', default='changeme')
argparser.add_argument('--log-file', help='output logs to a file', default='stderr')
......
sonar.projectName=zoe_lib
sonar.host.url=http://your-sonarqube-server-address
sonar.sources=.
sonar.language=py
sonar.sourceEncoding=UTF-8
......@@ -302,7 +302,10 @@ class SwarmClient:
cont.stop(timeout=5)
if delete:
cont.remove(force=True)
try:
cont.remove(force=True)
except docker.errors.APIError as e:
log.warning(str(e))
def event_listener(self, callback: Callable[[str], bool]) -> None:
"""An infinite loop that listens for events from Swarm."""
......
sonar.projectName=zoe_master
sonar.host.url=http://your-sonarqube-server-address
sonar.sources=.
sonar.language=py
sonar.sourceEncoding=UTF-8
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment