Additional Work Done on requests
This commit is contained in:
parent
ae3530f2dd
commit
6d5d037f44
99
index.py
99
index.py
@ -1,87 +1,136 @@
|
|||||||
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
|
||||||
|
|
||||||
cpu_count = len(stats["cpu_stats"]["cpu_usage"]["percpu_usage"])
|
cpu_count = len(stats["cpu_stats"]["cpu_usage"]["percpu_usage"])
|
||||||
cpu_percent = 0.0
|
cpu_percent = 0.0
|
||||||
cpu_delta = float(stats["cpu_stats"]["cpu_usage"]["total_usage"]) - \
|
cpu_delta = float(stats["cpu_stats"]["cpu_usage"]["total_usage"]) - \
|
||||||
float(stats["precpu_stats"]["cpu_usage"]["total_usage"])
|
float(stats["precpu_stats"]["cpu_usage"]["total_usage"])
|
||||||
system_delta = float(stats["cpu_stats"]["system_cpu_usage"]) - \
|
system_delta = float(stats["cpu_stats"]["system_cpu_usage"]) - \
|
||||||
float(stats["precpu_stats"]["system_cpu_usage"])
|
float(stats["precpu_stats"]["system_cpu_usage"])
|
||||||
|
|
||||||
if system_delta > 0.0:
|
if system_delta > 0.0:
|
||||||
cpu_percent = cpu_delta / system_delta * 100.0 * cpu_count
|
cpu_percent = cpu_delta / system_delta * 100.0 * cpu_count
|
||||||
|
|
||||||
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 _:
|
||||||
return 'False'
|
return 'False'
|
||||||
|
|
||||||
container = client.containers.get(container_id)
|
container = client.containers.get(container_id)
|
||||||
return container.status
|
return container.status
|
||||||
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)
|
||||||
|
@ -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
72
templates/login.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user