fixes
This commit is contained in:
79
app/sbin/api
79
app/sbin/api
@@ -8,16 +8,19 @@ import sqlite3
|
||||
import subprocess
|
||||
import os
|
||||
import uvicorn
|
||||
from typing import Optional
|
||||
from typing import Dict, Any, Optional
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
# Constants
|
||||
|
||||
|
||||
# ---------------------- Constants ----------------------
|
||||
DB_PATH = "/4server/data/contracts.db"
|
||||
BIN_PATH = "/4server/sbin"
|
||||
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
|
||||
VERSION = "API: 0.0.7"
|
||||
|
||||
# FastAPI app
|
||||
# ---------------------- FastAPI App ----------------------
|
||||
app = FastAPI()
|
||||
api_key_header = APIKeyHeader(name="X-API-Key")
|
||||
|
||||
@@ -44,7 +47,7 @@ def init_db():
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS containers (
|
||||
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
UUID CHAR(50),
|
||||
UUID CHAR(50) UNIQUE,
|
||||
email CHAR(100),
|
||||
expires DATE,
|
||||
tags TEXT,
|
||||
@@ -65,27 +68,24 @@ def init_db():
|
||||
|
||||
def execute_db(query: str, params: tuple = (), fetch: bool = False):
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.row_factory = sqlite3.Row # <-- Add this line
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(query, params)
|
||||
conn.commit()
|
||||
data = cursor.fetchall() if fetch else None
|
||||
conn.close()
|
||||
if data and fetch:
|
||||
return [dict(row) for row in data] # Convert each row to dict
|
||||
return data
|
||||
|
||||
|
||||
|
||||
return [dict(row) for row in data]
|
||||
return None
|
||||
|
||||
|
||||
# ---------------------- Models ----------------------
|
||||
class ContainerModel(BaseModel):
|
||||
UUID: Optional[str] = None
|
||||
UUID: str
|
||||
email: Optional[str] = None
|
||||
expires: Optional[str] = None
|
||||
tags: Optional[str] = None
|
||||
env: Optional[str] = None
|
||||
env: Optional[Dict[str, Any]] = None
|
||||
affiliate: Optional[str] = None
|
||||
image: Optional[str] = None
|
||||
history: Optional[str] = None
|
||||
@@ -96,16 +96,8 @@ class ContainerModel(BaseModel):
|
||||
bump: Optional[str] = None
|
||||
|
||||
|
||||
class ContainerIDRequest(BaseModel):
|
||||
container_id: Optional[str] = None
|
||||
|
||||
|
||||
class UpdateContainerRequest(ContainerModel):
|
||||
pass
|
||||
|
||||
|
||||
class InfoContainerRequest(BaseModel):
|
||||
container_id: Optional[str] = None
|
||||
class UUIDRequest(BaseModel):
|
||||
UUID: str
|
||||
|
||||
|
||||
# ---------------------- Routes ----------------------
|
||||
@@ -115,7 +107,9 @@ def redirect_to_odoo():
|
||||
|
||||
|
||||
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
|
||||
def update_container(request: UpdateContainerRequest):
|
||||
def update_container(request: ContainerModel):
|
||||
env_str = json.dumps(request.env) if isinstance(request.env, dict) else request.env
|
||||
|
||||
existing = execute_db("SELECT * FROM containers WHERE UUID = ?", (request.UUID,), fetch=True)
|
||||
if existing:
|
||||
execute_db("""
|
||||
@@ -123,7 +117,7 @@ def update_container(request: UpdateContainerRequest):
|
||||
history=?, comment=?, domains=?, status=?, created=?, bump=?
|
||||
WHERE UUID=?
|
||||
""", (
|
||||
request.email, request.expires, request.tags, request.env, request.affiliate,
|
||||
request.email, request.expires, request.tags, env_str, request.affiliate,
|
||||
request.image, request.history, request.comment, request.domains, request.status,
|
||||
request.created, request.bump, request.UUID
|
||||
))
|
||||
@@ -133,7 +127,7 @@ def update_container(request: UpdateContainerRequest):
|
||||
comment, domains, status, created, bump)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
request.UUID, request.email, request.expires, request.tags, request.env,
|
||||
request.UUID, request.email, request.expires, request.tags, env_str,
|
||||
request.affiliate, request.image, request.history, request.comment,
|
||||
request.domains, request.status, request.created, request.bump
|
||||
))
|
||||
@@ -141,44 +135,44 @@ def update_container(request: UpdateContainerRequest):
|
||||
|
||||
|
||||
@app.post("/container/start", dependencies=[Depends(verify_api_key)])
|
||||
def start_container(request: ContainerIDRequest):
|
||||
return {"message": run_command([f"{BIN_PATH}/startContainer", request.container_id])}
|
||||
def start_container(request: UUIDRequest):
|
||||
return {"message": run_command([f"{BIN_PATH}/startContainer", request.UUID])}
|
||||
|
||||
|
||||
@app.post("/container/stop", dependencies=[Depends(verify_api_key)])
|
||||
def stop_container(request: ContainerIDRequest):
|
||||
return {"message": run_command([f"{BIN_PATH}/stopContainer", request.container_id])}
|
||||
def stop_container(request: UUIDRequest):
|
||||
return {"message": run_command([f"{BIN_PATH}/stopContainer", request.UUID])}
|
||||
|
||||
|
||||
@app.post("/container/nuke", dependencies=[Depends(verify_api_key)])
|
||||
def nuke_container(request: ContainerIDRequest):
|
||||
status = execute_db("SELECT status FROM containers WHERE UUID=?", (request.container_id,), fetch=True)
|
||||
if not status or status[0][0] != "nuke":
|
||||
def nuke_container(request: UUIDRequest):
|
||||
status = execute_db("SELECT status FROM containers WHERE UUID=?", (request.UUID,), fetch=True)
|
||||
if not status or status[0]["status"] != "nuke":
|
||||
raise HTTPException(400, "Container status is not 'nuke'")
|
||||
return {"message": run_command([f"{BIN_PATH}/nukeContainer", request.container_id])}
|
||||
return {"message": run_command([f"{BIN_PATH}/nukeContainer", request.UUID])}
|
||||
|
||||
|
||||
@app.post("/container/info", dependencies=[Depends(verify_api_key)])
|
||||
def info_container(request: InfoContainerRequest):
|
||||
if request.container_id:
|
||||
rows = execute_db("SELECT * FROM containers WHERE UUID=?", (request.container_id,), fetch=True)
|
||||
def info_container(request: Optional[UUIDRequest] = None):
|
||||
if request:
|
||||
rows = execute_db("SELECT * FROM containers WHERE UUID=?", (request.UUID,), fetch=True)
|
||||
else:
|
||||
rows = execute_db("SELECT * FROM containers", fetch=True)
|
||||
return {"containers": rows}
|
||||
|
||||
|
||||
@app.post("/container/bump", dependencies=[Depends(verify_api_key)])
|
||||
def bump_container(request: ContainerIDRequest):
|
||||
def bump_container(request: UUIDRequest):
|
||||
today = datetime.utcnow().strftime("%Y-%m-%d")
|
||||
execute_db("UPDATE containers SET bump=? WHERE UUID=?", (today, request.container_id))
|
||||
msg = run_command([f"{BIN_PATH}/bumpContainer", request.container_id])
|
||||
execute_db("UPDATE containers SET bump=? WHERE UUID=?", (today, request.UUID))
|
||||
msg = run_command([f"{BIN_PATH}/bumpContainer", request.UUID])
|
||||
return {"message": msg, "bump_date": today}
|
||||
|
||||
|
||||
@app.post("/container/quota", dependencies=[Depends(verify_api_key)])
|
||||
def container_quota(request: ContainerIDRequest):
|
||||
def container_quota(request: UUIDRequest):
|
||||
output = run_command([
|
||||
"docker", "stats", request.container_id, "--no-stream",
|
||||
"docker", "stats", request.UUID, "--no-stream",
|
||||
"--format", "{{.MemUsage}},{{.BlockIO}}"
|
||||
])
|
||||
mem_usage, disk_usage = output.split(",")
|
||||
@@ -202,7 +196,7 @@ def get_system_info():
|
||||
try:
|
||||
alpine_version = None
|
||||
last_update = None
|
||||
bump_dates = execute_db("SELECT MAX(bump) FROM containers", fetch=True)[0][0]
|
||||
bump_dates = execute_db("SELECT MAX(bump) AS latest_bump FROM containers", fetch=True)[0]["latest_bump"]
|
||||
if os.path.exists("/4server/data/update"):
|
||||
with open("/4server/data/update") as f:
|
||||
last_update = f.read().strip()
|
||||
@@ -238,3 +232,4 @@ if __name__ == "__main__":
|
||||
init_db()
|
||||
uvicorn.run(app, host="10.5.0.1", port=8888)
|
||||
|
||||
|
||||
|
||||
@@ -28,16 +28,16 @@ docker run -d \
|
||||
--cap-add=SYS_ADMIN \
|
||||
--security-opt seccomp=unconfined \
|
||||
--restart=always \
|
||||
-e N8N_HOST="${UUID}.od8n.com" \
|
||||
-e N8N_HOST="${UUID}.odoo4projects.com" \
|
||||
-e N8N_PORT=5678 \
|
||||
-e N8N_PROTOCOL=https \
|
||||
-e NODE_ENV=production \
|
||||
-e WEBHOOK_URL="https://${UUID}.od8n.com/" \
|
||||
-e WEBHOOK_URL="https://${UUID}.odoo4projects.com/" \
|
||||
-e GENERIC_TIMEZONE="UTC-3" \
|
||||
-v "/4server/data/${UUID}/n8n:/home/node/.n8n" \
|
||||
-v "/4server/data/${UUID}/data:/data" \
|
||||
--label "traefik.enable=true" \
|
||||
--label "traefik.http.routers.${UUID}.rule=Host(\`${UUID}.od8n.com\`)" \
|
||||
--label "traefik.http.routers.${UUID}.rule=Host(\`${UUID}.odoo4projects.com\`)" \
|
||||
--label "traefik.http.routers.${UUID}.entrypoints=web,websecure" \
|
||||
--label "traefik.http.routers.${UUID}.tls=true" \
|
||||
--label "traefik.http.routers.${UUID}.tls.certresolver=production" \
|
||||
|
||||
@@ -16,7 +16,9 @@ if [[ -z "$UUID" ]]; then
|
||||
fi
|
||||
|
||||
while IFS="=" read -r key value; do
|
||||
export "$key=$value"
|
||||
if [ -n "$key" ]; then
|
||||
export "$key=$value"
|
||||
fi
|
||||
done < <(sqlite3 "$DB_PATH" "
|
||||
SELECT 'UUID=' || UUID FROM containers WHERE UUID='$UUID'
|
||||
UNION ALL SELECT 'EMAIL=' || email FROM containers WHERE UUID='$UUID'
|
||||
@@ -37,8 +39,7 @@ done < <(sqlite3 "$DB_PATH" "
|
||||
# Debug: print loaded environment variables
|
||||
env | grep -E 'UUID|EMAIL|EXPIRES|TAGS|ENV|AFFILIATE|IMAGE|HISTORY|COMMENT|DOMAINS|STATUS|CREATED|BUMP'
|
||||
|
||||
echo "UUID ${UUID}"
|
||||
|
||||
eval $(echo "$ENV" | jq -r 'to_entries | .[] | "export \(.key)=\(.value)"')
|
||||
|
||||
# Extract the second part of UUID (split by "-")
|
||||
SECOND_PART=$(echo "$UUID" | cut -d'-' -f2)
|
||||
@@ -59,5 +60,3 @@ case "$SECOND_PART" in
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user