Additional changes for purposes of templating
This commit is contained in:
parent
610ef79690
commit
556fe5920e
90
app.py
90
app.py
@ -6,8 +6,7 @@ import threading
|
|||||||
import time
|
import time
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from socketserver import ThreadingMixIn
|
from socketserver import ThreadingMixIn
|
||||||
from queue import Queue
|
import os
|
||||||
import multiprocessing
|
|
||||||
|
|
||||||
# Define the target server to proxy requests to
|
# Define the target server to proxy requests to
|
||||||
class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
||||||
@ -40,26 +39,28 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
def handle_request(self, method):
|
def handle_request(self, method):
|
||||||
#print(self.headers.get('Host').split(":")[0])
|
#print(self.headers.get('Host').split(":")[0])
|
||||||
proxy_host_configuration = next(filter(lambda host: host['domain'] == self.headers.get('Host').split(":")[0], self.configuration['proxy_hosts']))
|
parsed_request_host = self.headers.get('Host')
|
||||||
|
|
||||||
|
if (':' in parsed_request_host):
|
||||||
|
parsed_request_host = parsed_request_host.split(":")[0]
|
||||||
|
|
||||||
|
proxy_host_configuration = next(filter(lambda host: host['domain'] == parsed_request_host, self.configuration['proxy_hosts']))
|
||||||
|
|
||||||
starting = False
|
starting = False
|
||||||
for container in proxy_host_configuration['containers']:
|
for container in proxy_host_configuration['containers']:
|
||||||
container_object = self.docker_client.containers.list(all=True, filters = { 'name' : container['container_name'] })[0]
|
container_objects = self.docker_client.containers.list(all=True, filters = { 'name' : container['container_name'] })
|
||||||
|
if (container_objects == []):
|
||||||
|
self.send_404(proxy_host_configuration['domain'])
|
||||||
|
return
|
||||||
|
|
||||||
|
container_object = container_objects[0]
|
||||||
if (container_object.status != 'running'):
|
if (container_object.status != 'running'):
|
||||||
print("starting container: {0}".format(container['container_name']))
|
print("starting container: {0}".format(container['container_name']))
|
||||||
container_object.start()
|
container_object.start()
|
||||||
starting = True
|
starting = True
|
||||||
|
|
||||||
if (starting == True):
|
if (starting == True):
|
||||||
self.send_response(201)
|
self.send_loading(proxy_host_configuration['proxy_load_seconds'], proxy_host_configuration['domain'])
|
||||||
self.send_header('Content-Type', 'text/plain')
|
|
||||||
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
|
||||||
self.send_header('Pragma', 'no-cache')
|
|
||||||
self.send_header('Expires', '0')
|
|
||||||
self.send_header('refresh', proxy_host_configuration['proxy_timeout_seconds'])
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(bytes("starting container: {0} waiting for {1}s".format(container['container_name'], proxy_host_configuration['proxy_timeout_seconds']),"utf-8"))
|
|
||||||
self.wfile.flush()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
activity[proxy_host_configuration['domain']] = datetime.now(timezone.utc)
|
activity[proxy_host_configuration['domain']] = datetime.now(timezone.utc)
|
||||||
@ -79,6 +80,48 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def send_404(self, service_name):
|
||||||
|
self.send_response(404)
|
||||||
|
self.send_header('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||||
|
self.send_header('Pragma', 'no-cache')
|
||||||
|
self.send_header('Expires', '0')
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
with open(os.path.dirname(os.path.realpath(__file__)) + '/templates/404.html', 'r') as file:
|
||||||
|
html = file.read()
|
||||||
|
html = html.replace("{{SERVICE}}", service_name)
|
||||||
|
self.wfile.write(bytes(html,"utf-8"))
|
||||||
|
|
||||||
|
self.wfile.flush()
|
||||||
|
|
||||||
|
def send_loading(self, wait_time, service_name):
|
||||||
|
self.send_response(201)
|
||||||
|
self.send_header('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||||
|
self.send_header('Pragma', 'no-cache')
|
||||||
|
self.send_header('Expires', '0')
|
||||||
|
self.send_header('refresh', wait_time)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
with open(os.path.dirname(os.path.realpath(__file__)) + '/templates/wait.html', 'r') as file:
|
||||||
|
html = file.read()
|
||||||
|
self.wfile.write(bytes(html,"utf-8"))
|
||||||
|
|
||||||
|
#self.wfile.write(bytes("starting service: {0} waiting for {1}s".format(self.headers.get('Host').split(":")[0], proxy_host_configuration['proxy_timeout_seconds']),"utf-8"))
|
||||||
|
#self.wfile.write(bytes("\nlast started at: {0} ".format(activity[proxy_host_configuration['domain']]),"utf-8"))
|
||||||
|
|
||||||
|
self.wfile.flush()
|
||||||
|
|
||||||
|
def finish(self,*args,**kw):
|
||||||
|
try:
|
||||||
|
if not self.wfile.closed:
|
||||||
|
self.wfile.flush()
|
||||||
|
self.wfile.close()
|
||||||
|
except socket.error:
|
||||||
|
pass
|
||||||
|
self.rfile.close()
|
||||||
|
|
||||||
class ThreadedHTTPServer(ThreadingMixIn, http.server.HTTPServer):
|
class ThreadedHTTPServer(ThreadingMixIn, http.server.HTTPServer):
|
||||||
"""Handle requests in a separate thread."""
|
"""Handle requests in a separate thread."""
|
||||||
|
|
||||||
@ -97,17 +140,20 @@ class BackgroundTasks(threading.Thread):
|
|||||||
sleep_time = apps['proxy_timeout_seconds']
|
sleep_time = apps['proxy_timeout_seconds']
|
||||||
|
|
||||||
for container in apps['containers']:
|
for container in apps['containers']:
|
||||||
container_object = self.docker_client.containers.get(container['container_name'])
|
try:
|
||||||
if (container_object.status == 'running'):
|
container_object = self.docker_client.containers.get(container['container_name'])
|
||||||
|
if (container_object.status == 'running'):
|
||||||
|
|
||||||
dt = datetime.now(timezone.utc)
|
dt = datetime.now(timezone.utc)
|
||||||
if (apps['domain'] in activity):
|
if (apps['domain'] in activity):
|
||||||
dt = activity[apps['domain']]
|
dt = activity[apps['domain']]
|
||||||
|
|
||||||
diff_seconds = (datetime.now(timezone.utc) - dt).total_seconds()
|
diff_seconds = (datetime.now(timezone.utc) - dt).total_seconds()
|
||||||
if(diff_seconds > apps['proxy_timeout_seconds']):
|
if(diff_seconds > apps['proxy_timeout_seconds']):
|
||||||
print("stopping container: {0} ({1}) after {2}s".format(container['container_name'], container_object.id, diff_seconds))
|
print("stopping container: {0} ({1}) after {2}s".format(container['container_name'], container_object.id, diff_seconds))
|
||||||
container_object.stop()
|
container_object.stop()
|
||||||
|
except docker.errors.NotFound:
|
||||||
|
pass
|
||||||
|
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
proxy_port: 8888
|
proxy_port: 80
|
||||||
proxy_hosts:
|
proxy_hosts:
|
||||||
- domain: wp.local
|
- domain: wp.local
|
||||||
containers:
|
containers:
|
||||||
- container_name: wp-dev-db-1
|
- container_name: wp-dev-db-1
|
||||||
- container_name: wp-dev-wordpress-1
|
- container_name: wp-dev-wordpress-1
|
||||||
proxy_host: localhost
|
proxy_host: localhost
|
||||||
proxy_port: 80
|
proxy_port: 8888
|
||||||
proxy_timeout_seconds: 10
|
proxy_timeout_seconds: 10
|
||||||
|
proxy_load_seconds: 5
|
28
templates/404.html
Normal file
28
templates/404.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<style>
|
||||||
|
.loading {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -20px;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="spinner">
|
||||||
|
<h1>Service <b>{{SERVICE}}</b> not found !!!</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
88
templates/wait.html
Normal file
88
templates/wait.html
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<style>
|
||||||
|
.loading {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -20px;
|
||||||
|
margin-left: -25px;
|
||||||
|
width: 50px;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner>div {
|
||||||
|
z-index: 999;
|
||||||
|
background-color: black;
|
||||||
|
height: 100%;
|
||||||
|
width: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
|
||||||
|
animation: sk-stretchdelay 1.2s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .rect2 {
|
||||||
|
-webkit-animation-delay: -1.1s;
|
||||||
|
animation-delay: -1.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .rect3 {
|
||||||
|
-webkit-animation-delay: -1.0s;
|
||||||
|
animation-delay: -1.0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .rect4 {
|
||||||
|
-webkit-animation-delay: -0.9s;
|
||||||
|
animation-delay: -0.9s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .rect5 {
|
||||||
|
-webkit-animation-delay: -0.8s;
|
||||||
|
animation-delay: -0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes sk-stretchdelay {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
40%,
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scaleY(0.4)
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
-webkit-transform: scaleY(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sk-stretchdelay {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
40%,
|
||||||
|
100% {
|
||||||
|
transform: scaleY(0.4);
|
||||||
|
-webkit-transform: scaleY(0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
transform: scaleY(1.0);
|
||||||
|
-webkit-transform: scaleY(1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="spinner">
|
||||||
|
<div class="rect1"></div>
|
||||||
|
<div class="rect2"></div>
|
||||||
|
<div class="rect3"></div>
|
||||||
|
<div class="rect4"></div>
|
||||||
|
<div class="rect5"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user