-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathapp.py
More file actions
144 lines (115 loc) · 4.35 KB
/
app.py
File metadata and controls
144 lines (115 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print("***********************************")
print("*** Docker Monitor APP STARTING ***")
print("***********************************")
import threading
import time
import warnings
from flask import Flask
try:
from waitress import serve
HAS_WAITRESS = True
except ImportError: # waitress not installed
serve = None
HAS_WAITRESS = False
from config import (
APP_HOST,
APP_PORT,
APP_SECRET_KEY,
APP_SECRET_KEY_EPHEMERAL,
APP_VERSION,
AUTH_ENABLED,
AUTH_PASSWORD,
AUTH_USER,
CADVISOR_URL,
DOCKER_SOCKET_URL,
LOGIN_MODE,
MAX_SECONDS,
SAMPLE_INTERVAL,
STREAM_HEARTBEAT_SECONDS,
WAITRESS_THREADS,
)
from docker_client import get_docker_status, initialize_docker_clients
from routes import main_routes
from sampler import sample_metrics
from users_db import count_users, init_db
def create_app(test_config=None):
"""Application factory used by runtime and tests."""
flask_app = Flask(__name__, static_url_path='/static', static_folder='static')
flask_app.config.from_mapping(
SECRET_KEY=APP_SECRET_KEY,
APP_VERSION=APP_VERSION,
APP_SECRET_KEY_EPHEMERAL=APP_SECRET_KEY_EPHEMERAL,
AUTH_ENABLED=AUTH_ENABLED,
AUTH_USER=AUTH_USER,
AUTH_PASSWORD=AUTH_PASSWORD,
CADVISOR_URL=CADVISOR_URL,
DOCKER_SOCKET_URL=DOCKER_SOCKET_URL,
LOGIN_MODE=LOGIN_MODE,
SAMPLE_INTERVAL=SAMPLE_INTERVAL,
MAX_SECONDS=MAX_SECONDS,
STREAM_HEARTBEAT_SECONDS=STREAM_HEARTBEAT_SECONDS,
)
if test_config:
flask_app.config.update(test_config)
flask_app.secret_key = flask_app.config["SECRET_KEY"]
flask_app.register_blueprint(main_routes)
@flask_app.context_processor
def inject_template_globals():
return {
"app_version": flask_app.config.get("APP_VERSION", "dev"),
}
return flask_app
app = create_app()
def start_sampler_thread():
print("Starting metrics sampling thread...")
sampler_thread = threading.Thread(target=sample_metrics, daemon=True)
sampler_thread.start()
print("Sampling thread started.")
def initialize_runtime():
"""Prepare auth DB and Docker connectivity without failing the whole app."""
bootstrap_user = app.config.get("AUTH_USER", "")
bootstrap_password = app.config.get("AUTH_PASSWORD", "")
auth_enabled = bool(app.config.get("AUTH_ENABLED", True))
if bootstrap_user and bootstrap_password:
init_db(bootstrap_user, bootstrap_password)
user_count = count_users()
if auth_enabled and user_count == 0:
raise RuntimeError(
"AUTH_ENABLED is true but no users exist. Set AUTH_USER/AUTH_PASSWORD (or *_FILE) for the first startup."
)
if app.config.get("APP_SECRET_KEY_EPHEMERAL"):
warnings.warn(
"APP_SECRET_KEY is not set. A temporary secret key was generated for this process; sessions will be reset on restart.",
RuntimeWarning,
)
docker_ready = initialize_docker_clients(force=True)
docker_status = get_docker_status()
if docker_ready:
print(f"Docker connection established via: {DOCKER_SOCKET_URL}")
else:
print("WARN: Docker client not available at startup. The UI will run in degraded mode.")
if docker_status.get("error"):
print(f" {docker_status['error']}")
print(f"Sampler interval: {SAMPLE_INTERVAL} seconds")
print(f"History retention: {MAX_SECONDS / 3600} hours")
print(f"App version: {app.config.get('APP_VERSION')}")
return docker_ready
if __name__ == '__main__':
print("-------------------------------------")
print(" Docker Monitor ")
print("-------------------------------------")
print("Starting Flask server...")
docker_ready = initialize_runtime()
start_sampler_thread()
if docker_ready:
time.sleep(1)
print(f"Access the monitor at: http://{APP_HOST}:{APP_PORT} (or your machine's IP:{APP_PORT})")
print("-------------------------------------")
if HAS_WAITRESS:
print(f"Using Waitress server with {WAITRESS_THREADS} threads...")
serve(app, host=APP_HOST, port=APP_PORT, threads=WAITRESS_THREADS)
else:
print("Waitress not found, using Flask development server (WARNING: Not recommended for production).")
app.run(host=APP_HOST, port=APP_PORT, debug=False)