Additional Work Done on requests

This commit is contained in:
Václav Španinger 2023-08-07 13:35:27 +02:00
parent ae3530f2dd
commit 6d5d037f44
3 changed files with 156 additions and 27 deletions

View File

@ -1,14 +1,18 @@
from dotenv import load_dotenv from dotenv import load_dotenv
from flask import Flask, render_template from flask import Flask, render_template, request, session, redirect, url_for, abort
from flask_apscheduler import APScheduler from flask_apscheduler import APScheduler
from flask_login import LoginManager from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
import docker import docker
import pyjokes
import time import time
import os import os
from datetime import timedelta
#DEBUG # DEBUG
from pprint import pprint from pprint import pprint
def calculate_cpu_percent(stats, status): def calculate_cpu_percent(stats, status):
if (status != "running"): if (status != "running"):
return 0 return 0
@ -25,47 +29,94 @@ def calculate_cpu_percent(stats, status):
return round(cpu_percent, 2) return round(cpu_percent, 2)
def calculate_ram_percent(stats, status): def calculate_ram_percent(stats, status):
if (status != "running"): if (status != "running"):
return 0 return 0
mem_used = stats["memory_stats"]["usage"] - stats["memory_stats"]["stats"]["cache"] + stats["memory_stats"]["stats"]["active_file"] mem_used = stats["memory_stats"]["usage"] - stats["memory_stats"]["stats"]["cache"] + \
stats["memory_stats"]["stats"]["active_file"]
limit = stats['memory_stats']['limit'] limit = stats['memory_stats']['limit']
return round(mem_used / limit * 100, 2) return round(mem_used / limit * 100, 2)
client = docker.from_env()
#login_manager = LoginManager()
app = Flask(__name__)
scheduler = APScheduler()
load_dotenv() load_dotenv()
#login_manager.init_app(app) scheduler = APScheduler()
#https://flask-login.readthedocs.io/en/latest/ app = Flask(__name__)
app.secret_key = "sdasdsadasdasdasdadadaasd53563da"
app.permanent_session_lifetime = timedelta(days=1)
client = docker.from_env()
# db = SQLAlchemy(app)
# migrate = Migrate(app, db)
# login_manager.init_app(app)
# https://flask-login.readthedocs.io/en/latest/
@app.route("/login", methods=["POST", "GET"])
def login():
if (request.method == "POST"):
user = request.form["email"]
#TODO: Validation
session.permanent = True
session['user'] = user
return redirect(url_for("index"))
else:
if "user" in session:
return redirect(url_for("index"))
return render_template("login.html")
@app.route("/logout", methods=['GET', 'POST'])
def logout():
session.pop("user", None)
return redirect(url_for("login"))
@app.route("/", methods=['GET']) @app.route("/", methods=['GET'])
def index(): def index():
if "user" not in session:
return redirect(url_for("login"))
containers = client.containers.list(all=True) containers = client.containers.list(all=True)
return render_template("index.html", title="test", containers_len=len(containers), containers=containers) punchline = pyjokes.get_joke(language="en", category="neutral")
return render_template("index.html", title="test", subtitle=punchline, containers_len=len(containers), containers=containers)
@app.route("/parts/modal/container/<container_id>", methods=['GET']) @app.route("/parts/modal/container/<container_id>", methods=['GET'])
def parts_container_modal(container_id): def parts_container_modal(container_id):
if "user" not in session:
abort(401)
container = client.containers.get(container_id) container = client.containers.get(container_id)
stats = container.stats(stream=False) stats = container.stats(stream=False)
#com.docker.extension.detailed-description # com.docker.extension.detailed-description
project = '' project = ''
if('com.docker.compose.project' in container.attrs['Config']['Labels']):
pprint(container.attrs)
if ('com.docker.compose.project' in container.attrs['Config']['Labels']):
project = container.attrs['Config']['Labels']['com.docker.compose.project'] project = container.attrs['Config']['Labels']['com.docker.compose.project']
return render_template("container_modal.html", name=container.name, project=project, ports=container.attrs['NetworkSettings']['Ports'], status=container.status, CPU=calculate_cpu_percent(stats, container.status) ,RAM =calculate_ram_percent(stats, container.status) ) return render_template("container_modal.html", name=container.name, project=project, ports=container.attrs['NetworkSettings']['Ports'], status=container.status, CPU=calculate_cpu_percent(stats, container.status), RAM=calculate_ram_percent(stats, container.status))
@app.route("/api/<container_id>/<action>", methods=['DELETE', 'POST']) @app.route("/api/<container_id>/<action>", methods=['DELETE', 'POST'])
def api_stop_container(container_id, action): def api_stop_container(container_id, action):
if "user" not in session:
abort(401)
container = client.containers.get(container_id) container = client.containers.get(container_id)
#pprint(vars(container))
try: try:
match action: match action:
case 'stop': case 'stop':
container.stop() container.stop()
case 'restart':
container.restart()
case 'start': case 'start':
container.start() container.start()
case _: case _:
@ -76,12 +127,10 @@ def api_stop_container(container_id, action):
except: except:
return 'False' return 'False'
def scheduleTasks(): def scheduleTasks():
print("This test runs every 3 seconds") print("This test runs every 3 seconds")
if __name__ == '__main__': if __name__ == '__main__':
#scheduler.add_job(id = 'scheduled_tasks', func=scheduleTasks, trigger="interval", seconds=3) # scheduler.add_job(id = 'scheduled_tasks', func=scheduleTasks, trigger="interval", seconds=60)
#scheduler.start() # scheduler.start()
app.run(host=os.getenv('IP'), port=os.getenv('port'), debug=True) app.run(host=os.getenv('IP'), port=os.getenv('port'), debug=True)

View File

@ -7,13 +7,20 @@
<title>{{title}}</title> <title>{{title}}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous"> integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<style> <style>
</style> </style>
</head> </head>
<body data-bs-theme="dark"> <body data-bs-theme="dark">
<div class="container-fluid"> <div class="container-fluid">
<h1>Containers</h1> <a href="/" class="d-flex text-decoration-none text-primary">
<i style="font-size: 3rem;" class="bi bi-stack me-2"></i>
<div class="mb-2">
<h2 class="mb-0">Containers</h2>
<small>{{subtitle}}</small>
</div>
</a>
<div class="row row-cols-auto g-2"> <div class="row row-cols-auto g-2">
{% for container in containers %} {% for container in containers %}
<div class="col-6 col-sm-4 col-md-4 col-lg-3 col-xxl-2"> <div class="col-6 col-sm-4 col-md-4 col-lg-3 col-xxl-2">
@ -28,7 +35,8 @@
<input class="form-check-input" type="checkbox" id="flexSwitchCheckReverse" <input class="form-check-input" type="checkbox" id="flexSwitchCheckReverse"
onclick="toggleContainer('{{container.id}}', '{{container.status}}', this, event);" {% if onclick="toggleContainer('{{container.id}}', '{{container.status}}', this, event);" {% if
container.status=="running" %} checked {% endif %}> container.status=="running" %} checked {% endif %}>
<label class="form-check-label d-none d-md-block " for="flexSwitchCheckReverse">isRunning</label> <label class="form-check-label d-none d-md-block "
for="flexSwitchCheckReverse">{{container.status}}</label>
</div> </div>
</div> </div>
<h4 class="text-truncate">{{container.attrs['Config']['Labels']['com.docker.compose.project']}}</h4> <h4 class="text-truncate">{{container.attrs['Config']['Labels']['com.docker.compose.project']}}</h4>

72
templates/login.html Normal file
View File

@ -0,0 +1,72 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Signin Template for Bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<style>
html,
body {
height: 100%;
}
body {
display: -ms-flexbox;
display: -webkit-box;
display: flex;
-ms-flex-align: center;
-ms-flex-pack: center;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
width: 100%;
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .checkbox {
font-weight: 400;
}
.form-signin .form-control {
position: relative;
box-sizing: border-box;
height: auto;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
}
</style>
</head>
<body class="text-center">
<form class="form-signin" method="post">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail" class="">Email address</label>
<input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="">Password</label>
<input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body>
</html>