GamerC0der commited on
Commit
1be5b26
·
verified ·
1 Parent(s): 2d669cb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -0
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import psutil
3
+ import psycopg2
4
+ from flask import Flask, jsonify, request
5
+
6
+ app = Flask(__name__)
7
+
8
+ DB_CONFIG = {
9
+ "host": os.getenv("DB_HOST", "localhost"),
10
+ "port": int(os.getenv("DB_PORT", 5432)),
11
+ "dbname": os.getenv("DB_NAME", "mydb"),
12
+ "user": os.getenv("DB_USER", "myuser"),
13
+ "password": os.getenv("DB_PASSWORD", "mypassword"),
14
+ }
15
+
16
+ EXPECTED_LIMITS = {
17
+ "cpu_cores": 1,
18
+ "ram_gb": 8,
19
+ "storage_gb": 20,
20
+ "max_db_connections": 50,
21
+ }
22
+
23
+
24
+ def get_db_connection():
25
+ return psycopg2.connect(**DB_CONFIG)
26
+
27
+
28
+ def get_system_stats():
29
+ cpu_percent = psutil.cpu_percent(interval=0.1)
30
+ cpu_count = psutil.cpu_count(logical=False) or psutil.cpu_count()
31
+
32
+ vm = psutil.virtual_memory()
33
+ ram_total_gb = vm.total / (1024**3)
34
+ ram_used_gb = (vm.total - vm.available) / (1024**3)
35
+ ram_percent = vm.percent
36
+
37
+ disk = psutil.disk_usage("/")
38
+ disk_total_gb = disk.total / (1024**3)
39
+ disk_used_gb = disk.used / (1024**3)
40
+ disk_percent = disk.percent
41
+
42
+ return {
43
+ "cpu": {
44
+ "usage_percent": cpu_percent,
45
+ "cores_detected": cpu_count,
46
+ "expected_cores": EXPECTED_LIMITS["cpu_cores"],
47
+ },
48
+ "ram": {
49
+ "total_gb": ram_total_gb,
50
+ "used_gb": ram_used_gb,
51
+ "usage_percent": ram_percent,
52
+ "expected_gb": EXPECTED_LIMITS["ram_gb"],
53
+ },
54
+ "disk": {
55
+ "total_gb": disk_total_gb,
56
+ "used_gb": disk_used_gb,
57
+ "usage_percent": disk_percent,
58
+ "expected_gb": EXPECTED_LIMITS["storage_gb"],
59
+ },
60
+ }
61
+
62
+
63
+ def get_db_stats():
64
+ try:
65
+ conn = get_db_connection()
66
+ cur = conn.cursor()
67
+ cur.execute("SELECT COUNT(*) FROM pg_stat_activity;")
68
+ current_connections = cur.fetchone()[0]
69
+ cur.execute("SHOW max_connections;")
70
+ max_connections = int(cur.fetchone()[0])
71
+ cur.close()
72
+ conn.close()
73
+
74
+ return {
75
+ "current_connections": current_connections,
76
+ "max_connections": max_connections,
77
+ "expected_max_connections": EXPECTED_LIMITS["max_db_connections"],
78
+ }
79
+ except Exception as e:
80
+ return {
81
+ "error": str(e),
82
+ "current_connections": None,
83
+ "max_connections": None,
84
+ }
85
+
86
+
87
+ @app.route("/")
88
+ def index():
89
+ system_stats = get_system_stats()
90
+ db_stats = get_db_stats()
91
+
92
+ doc = {
93
+ "description": "PostgreSQL + Flask service exposed on /api",
94
+ "endpoints": {
95
+ "/": {
96
+ "method": "GET",
97
+ "description": "System + DB stats and endpoint documentation",
98
+ },
99
+ "/api": {
100
+ "method": "GET",
101
+ "description": "Simple API root, returns health and DB connectivity",
102
+ },
103
+ "/api/query": {
104
+ "method": "POST",
105
+ "description": "Execute an arbitrary SQL query. Body: JSON {\"query\": \"SELECT ...\"}",
106
+ },
107
+ },
108
+ "expected_resources": EXPECTED_LIMITS,
109
+ "system_stats": system_stats,
110
+ "db_stats": db_stats,
111
+ }
112
+
113
+ return jsonify(doc)
114
+
115
+
116
+ @app.route("/api")
117
+ def api_root():
118
+ try:
119
+ conn = get_db_connection()
120
+ cur = conn.cursor()
121
+ cur.execute("SELECT 1;")
122
+ result = cur.fetchone()[0]
123
+ cur.close()
124
+ conn.close()
125
+ db_status = "ok" if result == 1 else "unexpected_result"
126
+ except Exception as e:
127
+ db_status = f"error: {e}"
128
+
129
+ return jsonify({
130
+ "status": "ok",
131
+ "db_status": db_status,
132
+ })
133
+
134
+
135
+ @app.route("/api/query", methods=["POST"])
136
+ def api_query():
137
+ data = request.get_json(silent=True) or {}
138
+ query = data.get("query")
139
+
140
+ if not query:
141
+ return jsonify({"status": "error", "error": "Missing 'query' in JSON body"}), 400
142
+
143
+ try:
144
+ conn = get_db_connection()
145
+ cur = conn.cursor()
146
+ cur.execute(query)
147
+
148
+ rows = None
149
+ if cur.description is not None:
150
+ cols = [d[0] for d in cur.description]
151
+ rows = [dict(zip(cols, r)) for r in cur.fetchall()]
152
+
153
+ try:
154
+ conn.commit()
155
+ except Exception:
156
+ conn.rollback()
157
+
158
+ cur.close()
159
+ conn.close()
160
+
161
+ return jsonify({
162
+ "status": "ok",
163
+ "rows": rows,
164
+ })
165
+ except Exception as e:
166
+ return jsonify({
167
+ "status": "error",
168
+ "error": str(e),
169
+ }), 500
170
+
171
+
172
+ if __name__ == "__main__":
173
+ app.run(host="0.0.0.0", port=7860)