This commit is contained in:
Your Name
2026-04-11 18:12:42 -03:00
parent b14d2f4fc1
commit 73090ddaa1
12 changed files with 346 additions and 128 deletions
Regular → Executable
View File
+169 -69
View File
@@ -1,30 +1,27 @@
#!/usr/bin/env python3
from fastapi import FastAPI, HTTPException, Depends, Response
from fastapi.security.api_key import APIKeyHeader
from fastapi.responses import RedirectResponse, PlainTextResponse
from pydantic import BaseModel
import psutil
import json
import os
import re
import sqlite3
import subprocess
import os
import uvicorn
from typing import Dict, Any, Optional
from datetime import datetime
import json
import re
from collections import deque
import time
from collections import deque
from datetime import datetime
from pathlib import Path
from pathlib import Path
from typing import Any, Dict, Optional
import psutil
import uvicorn
from fastapi import Depends, FastAPI, HTTPException, Response
from fastapi.responses import PlainTextResponse, RedirectResponse
from fastapi.security.api_key import APIKeyHeader
from pydantic import BaseModel
# ---------------------- 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.8"
VERSION = "API: 0.0.9"
# ---------------------- FastAPI App ----------------------
app = FastAPI()
@@ -57,7 +54,7 @@ def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
cursor.execute("""
CREATE TABLE IF NOT EXISTS containers (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
UUID CHAR(50) UNIQUE,
@@ -74,9 +71,19 @@ def init_db():
created DATE,
bump DATE,
secret TEXT,
contract TEXT
contract TEXT,
git integer,
backup_slots integer,
hdd integer,
workers integer,
utm_source text,
utm_medium text,
utm_campaign text,
domains_slots integer,
secret_list TEXT,
env_list TEXT
)
''')
""")
conn.commit()
conn.close()
@@ -101,13 +108,12 @@ class ContractItem(BaseModel):
product_id: int
features: Dict[str, Any]
class ContainerModel(BaseModel):
UUID: str
email: Optional[str] = None
expires: Optional[str] = None
tags: Optional[str] = None
env: Optional[Dict[str, Any]] = None
affiliate: Optional[str] = None
image: Optional[str] = None
history: Optional[str] = None
comment: Optional[str] = None
@@ -115,37 +121,56 @@ class ContainerModel(BaseModel):
status: Optional[str] = None
created: Optional[str] = None
bump: Optional[str] = None
secret: Optional[Dict[str, Any]] = None
contract: Optional[str] = None
git: Optional[int] = None
backup_slots: Optional[int] = None
hdd: Optional[int] = None
workers: Optional[int] = None
utm_source: Optional[str] = None
utm_medium: Optional[str] = None
utm_campaign: Optional[str] = None
domains_slots: Optional[int] = None
env_list: Optional[str] = None
class UUIDRequest(BaseModel):
UUID: str
class CommandRequest(BaseModel):
uuid: str
method: int
class ImportRequest(BaseModel):
filename: str
class MoveRequest(BaseModel):
source: str
destination: str
class AddKeyRequest(BaseModel):
key: str
uuid: str
class ImageRequest(BaseModel):
image: str
# ---------------------- Routes ----------------------
@app.get("/", include_in_schema=False)
def redirect_to_odoo():
return RedirectResponse(url="https://ODOO4PROJECTS.com")
from fastapi import FastAPI, Depends
import json
from typing import Any, Dict, Optional
from fastapi import Depends, FastAPI
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from typing import Optional, Dict, Any
import json
app = FastAPI()
@@ -158,25 +183,42 @@ def redirect_to_odoo():
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
def update_container(request: ContainerModel):
# Convert dict fields to JSON strings
env_str = json.dumps(request.env) if isinstance(request.env, dict) else None
secret_str = json.dumps(request.secret) if isinstance(request.secret, dict) else None
contract_str = json.dumps(request.contract) if isinstance(request.contract, dict) else None
# Fetch existing record
existing = execute_db("SELECT * FROM containers WHERE UUID = ?", (request.UUID,), fetch=True)
existing = execute_db(
"SELECT * FROM containers WHERE UUID = ?", (request.UUID,), fetch=True
)
if not existing:
# If record does not exist, insert a new one with all given fields
execute_db("""
INSERT INTO containers (UUID, email, expires, tags, env, affiliate, image, history,
comment, domains, status, created, bump, secret, contract)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
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, secret_str, contract_str
))
execute_db(
"""
INSERT INTO containers (UUID, email, expires, tags, image, history,
comment, domains, status, created, bump, git, backup_slots, hdd, workers,
utm_source, utm_medium, utm_campaign, domains_slots, env_list)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
request.UUID,
request.email,
request.expires,
request.tags,
request.image,
request.history,
request.comment,
request.domains,
request.status,
request.created,
request.bump,
request.git,
request.backup_slots,
request.hdd,
request.workers,
request.utm_source,
request.utm_medium,
request.utm_campaign,
request.domains_slots,
request.env_list,
),
)
return {"UUID": request.UUID, "status": "created"}
# Existing record found, do partial update
@@ -190,9 +232,6 @@ def update_container(request: ContainerModel):
continue
value = getattr(request, field)
if value is not None:
if field in ["env", "secret", "contract"]:
value = json.dumps(value)
updates[field] = value
params.append(value)
@@ -201,7 +240,11 @@ def update_container(request: ContainerModel):
set_clause = ", ".join(f"{k}=?" for k in updates.keys())
params.append(request.UUID) # UUID for WHERE clause
execute_db(f"UPDATE containers SET {set_clause} WHERE UUID=?", tuple(params))
return {"UUID": request.UUID, "status": "updated", "fields_updated": list(updates.keys())}
return {
"UUID": request.UUID,
"status": "updated",
"fields_updated": list(updates.keys()),
}
return {"UUID": request.UUID, "status": "no_change"}
@@ -211,6 +254,11 @@ def start_container(request: UUIDRequest):
return {"message": run_command([f"{BIN_PATH}/startContainer", request.UUID])}
@app.post("/container/restartAllContainers", dependencies=[Depends(verify_api_key)])
def start_container(request: ImageRequest):
return {"message": run_command([f"{BIN_PATH}/restartContainers", request.image])}
@app.post("/container/stop", dependencies=[Depends(verify_api_key)])
def stop_container(request: UUIDRequest):
try:
@@ -222,7 +270,9 @@ def stop_container(request: UUIDRequest):
@app.post("/container/nuke", dependencies=[Depends(verify_api_key)])
def nuke_container(request: UUIDRequest):
status = execute_db("SELECT status FROM containers WHERE UUID=?", (request.UUID,), fetch=True)
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.UUID])}
@@ -232,8 +282,26 @@ def nuke_container(request: UUIDRequest):
def info_container(request: Optional[UUIDRequest] = None):
# Fields to select
fields = [
"ID", "UUID", "email", "expires", "tags", "env", "affiliate",
"image", "history", "comment", "domains", "status", "created", "contract"
"ID",
"UUID",
"email",
"expires",
"tags",
"image",
"history",
"comment",
"domains",
"status",
"created",
"git",
"backup_slots",
"hdd",
"workers",
"utm_source",
"utm_medium",
"utm_campaign",
"domains_slots",
"env_list",
]
field_str = ", ".join(fields)
@@ -242,13 +310,10 @@ def info_container(request: Optional[UUIDRequest] = None):
rows = execute_db(
f"SELECT {field_str} FROM containers WHERE UUID=?",
(str(request.UUID),),
fetch=True
fetch=True,
)
else:
rows = execute_db(
f"SELECT {field_str} FROM containers",
fetch=True
)
rows = execute_db(f"SELECT {field_str} FROM containers", fetch=True)
# Map rows to dicts safely
containers = []
@@ -265,6 +330,7 @@ def info_container(request: Optional[UUIDRequest] = None):
return n8n_items
@app.post("/container/bump", dependencies=[Depends(verify_api_key)])
def bump_container(request: UUIDRequest):
today = datetime.utcnow().strftime("%Y-%m-%d")
@@ -275,10 +341,16 @@ def bump_container(request: UUIDRequest):
@app.post("/container/quota", dependencies=[Depends(verify_api_key)])
def container_quota(request: UUIDRequest):
output = run_command([
"docker", "stats", request.UUID, "--no-stream",
"--format", "{{.MemUsage}},{{.BlockIO}}"
])
output = run_command(
[
"docker",
"stats",
request.UUID,
"--no-stream",
"--format",
"{{.MemUsage}},{{.BlockIO}}",
]
)
mem_usage, disk_usage = output.split(",")
return {"memory_usage": mem_usage, "disk_io": disk_usage}
@@ -286,7 +358,10 @@ def container_quota(request: UUIDRequest):
# ---------------------- SYSTEM ----------------------
@app.get("/system/containers", dependencies=[Depends(verify_api_key)])
def get_containers():
return Response(content=run_command([f"{BIN_PATH}/getContainers"]), media_type="application/json")
return Response(
content=run_command([f"{BIN_PATH}/getContainers"]),
media_type="application/json",
)
@app.get("/system/images", dependencies=[Depends(verify_api_key)])
@@ -294,6 +369,7 @@ def list_images():
images = run_command(["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"])
return {"images": images.split("\n")}
@app.get("/system/cpu", dependencies=[Depends(verify_api_key)])
def get_cpu_log():
CPU_LOG_PATH = Path("/4server/data/log/cpu.log")
@@ -307,12 +383,15 @@ def get_cpu_log():
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error reading CPU log: {e}")
@app.get("/system/info", dependencies=[Depends(verify_api_key)])
def get_system_info():
try:
alpine_version = None
last_update = None
bump_dates = execute_db("SELECT MAX(bump) AS latest_bump FROM containers", fetch=True)[0]["latest_bump"]
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()
@@ -328,10 +407,14 @@ def get_system_info():
"latest_bump": bump_dates,
"version": VERSION,
"resources": {
"memory": {"total": mem.total, "available": mem.available, "used": mem.used},
"memory": {
"total": mem.total,
"available": mem.available,
"used": mem.used,
},
"disk": {"total": disk.total, "used": disk.used, "free": disk.free},
"cpu_count": cpu_count
}
"cpu_count": cpu_count,
},
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@@ -342,6 +425,13 @@ def pull_all_images():
return {"message": run_command([f"{BIN_PATH}/pullAllContainers"])}
@app.post("/system/restartAllContainers", dependencies=[Depends(verify_api_key)])
def restart_all_containers(request: ImageRequest):
if not request.image:
raise HTTPException(status_code=400, detail="Image name is required")
return {"message": run_command([f"{BIN_PATH}/restartContainers", request.image])}
@app.post("/client/git", dependencies=[Depends(verify_api_key)])
def git_tool(request: CommandRequest):
if request.method == 1:
@@ -382,7 +472,10 @@ def audit_odoo(uuid: str):
@app.get("/client/logs/{uuid}", dependencies=[Depends(verify_api_key)])
async def get_odoo_log_summary(uuid: str):
if not re.fullmatch(r"[0-9a-fA-F\-]+", uuid):
raise HTTPException(status_code=400, detail="Invalid UUID format. Only numbers, letters a-f, and '-' are allowed.")
raise HTTPException(
status_code=400,
detail="Invalid UUID format. Only numbers, letters a-f, and '-' are allowed.",
)
BASE_LOG_DIR = "/4server/data"
@@ -424,7 +517,9 @@ async def get_odoo_log_summary(uuid: str):
try:
# Last 500 lines from Odoo log
last_500_lines = read_last_lines(odoo_log_file, 500)
important_odoo_lines = [line for line in last_500_lines if is_important_line(line)]
important_odoo_lines = [
line for line in last_500_lines if is_important_line(line)
]
# Last 50 lines from git.log
last_50_git_lines = read_last_lines(git_log_file, 50)
@@ -437,6 +532,7 @@ async def get_odoo_log_summary(uuid: str):
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error reading log files: {e}")
# ------------------------ BACKUP HANDLING -------------------------------------
@app.post("/backup/import", dependencies=[Depends(verify_api_key)])
def backup_import(request: ImportRequest):
@@ -447,10 +543,13 @@ def backup_import(request: ImportRequest):
output = run_command(command)
return {"message": output}
@app.post("/backup/move", dependencies=[Depends(verify_api_key)])
def backup_move(request: MoveRequest):
if not request.source or not request.destination:
raise HTTPException(status_code=400, detail="Source and destination are required")
raise HTTPException(
status_code=400, detail="Source and destination are required"
)
if not os.path.exists(request.source):
raise HTTPException(status_code=404, detail="Source file does not exist")
@@ -460,7 +559,10 @@ def backup_move(request: MoveRequest):
# For Windows, use: command = ["move", request.source, request.destination]
output = run_command(command)
return {"message": f"Moved {request.source} to {request.destination}", "output": output}
return {
"message": f"Moved {request.source} to {request.destination}",
"output": output,
}
# ---------------------- Entry Point ----------------------
@@ -469,5 +571,3 @@ if __name__ == "__main__":
init_db()
time.sleep(25)
uvicorn.run(app, host="10.5.0.1", port=8888)
+30 -17
View File
@@ -5,34 +5,47 @@ POSTGRES_PORT="${POSTGRES_PORT:-5432}"
POSTGRES_ADMIN_USER="${POSTGRES_ADMIN_USER:-1gtT0sf8klB9lDbYZD9}"
POSTGRES_ADMIN_PASSWORD="${POSTGRES_ADMIN_PASSWORD:-ZpSwWNafyy9GhY2gzHw}"
DB_PATH="/4server/data/contracts.db"
get_contract_info() {
DB_PATH="/4server/data/contracts.db"
echo "get_contract_info $UUID"
# Single CTE: the table is scanned once and all projections come from it
while IFS="=" read -r key value; do
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'
UNION ALL SELECT 'EXPIRES=' || expires FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'TAGS=' || replace(replace(tags, char(10), ''), char(13), '') FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'ENV=' || replace(replace(env, char(10), ''), char(13), '') FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'IMAGE=' || image FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'DOMAINS=' || domains FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'STATUS=' || status FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'CREATED=' || created FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'SECRET=' || secret FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'CONTAINERDBID=' || id FROM containers WHERE UUID='$UUID'
UNION ALL SELECT 'BUMP=' || bump FROM containers WHERE UUID='$UUID';
WITH c AS (SELECT * FROM containers WHERE UUID='$UUID' LIMIT 1)
SELECT 'UUID=' || COALESCE(UUID, '') FROM c UNION ALL
SELECT 'EXPIRES=' || COALESCE(expires, '') FROM c UNION ALL
SELECT 'IMAGE=' || COALESCE(image, '') FROM c UNION ALL
SELECT 'STATUS=' || COALESCE(status, '') FROM c UNION ALL
SELECT 'CREATED=' || COALESCE(created, '') FROM c UNION ALL
SELECT 'SECRET_LIST=' || COALESCE(secret_list, '') FROM c UNION ALL
SELECT 'CONTAINERDBID=' || COALESCE(id, '') FROM c UNION ALL
SELECT 'GIT=' || COALESCE(git, '') FROM c UNION ALL
SELECT 'BACKUP_SLOTS=' || COALESCE(backup_slots, '') FROM c UNION ALL
SELECT 'HDD=' || COALESCE(hdd, '') FROM c UNION ALL
SELECT 'WORKERS=' || COALESCE(workers, '') FROM c UNION ALL
SELECT 'DOMAINS_SLOTS=' || COALESCE(domains_slots, '') FROM c;
")
eval $(echo "$ENV" | jq -r 'to_entries | .[] | "export \(.key | ascii_upcase)=\(.value)"')
# Parse SECRET_LIST: backslash-separated key=value pairs (e.g. worex1=1\pswl=22)
# - printf avoids echo interpreting escape sequences
# - tr -d '\r\n' strips any embedded newlines the DB value may contain
# - tr '\\' '\n' turns each backslash separator into a real newline
# - %%=* / #*= split on the FIRST = only, so base64 values like tok=ab== are safe
if [ -n "$SECRET_LIST" ]; then
while IFS= read -r pair || [ -n "$pair" ]; do
_key="${pair%%=*}"
_value="${pair#*=}"
if [ -n "$_key" ]; then
export "$_key=$_value"
fi
done < <(printf '%s' "$SECRET_LIST" | tr -d '\r\n' | tr '\\' '\n')
fi
export ODOO_DB_PASSWORD=$psql
}
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
sqlite3 /4server/data/contracts.db <<EOF
ALTER TABLE containers ADD COLUMN env_list TEXT;
UPDATE containers
SET env_list = (
SELECT group_concat(key || '=' || value, ', ')
FROM json_each(containers.env)
);
ALTER TABLE containers ADD COLUMN secret_list TEXT;
UPDATE containers
SET secret_list = (
SELECT group_concat(key || '=' || value, ', ')
FROM json_each(containers.secret)
);
EOF
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
# Usage: ./odoo_passwd.sh <container_name>
CONTAINER=$1
if [ -z "$CONTAINER" ]; then
echo "Usage: $0 <docker_container>"
exit 1
fi
# Step 1: Get users list
echo "Fetching users..."
USERS=$(doas docker exec -i "$CONTAINER" bash -c \
'PGPASSWORD="$PASSWORD" psql -h "$HOST" -U "$USER" -At -F"," -c "SELECT id, login FROM res_users ORDER BY id;"')
# Step 2: Display users
echo "Select a user:"
IFS=$'\n'
select USER_LINE in $USERS; do
if [ -n "$USER_LINE" ]; then
break
fi
done
USER_ID=$(echo "$USER_LINE" | cut -d',' -f1)
USER_LOGIN=$(echo "$USER_LINE" | cut -d',' -f2)
echo "Selected user: $USER_LOGIN (ID: $USER_ID)"
# Step 3: Ask for new password
read -s -p "Enter new password: " NEW_PASS
echo
read -s -p "Confirm password: " CONFIRM_PASS
echo
if [ "$NEW_PASS" != "$CONFIRM_PASS" ]; then
echo "Passwords do not match!"
exit 1
fi
# Step 4: Generate Odoo-compatible hash using Python inside container
HASH=$(doas docker exec -i "$CONTAINER" python3 - <<EOF
from passlib.context import CryptContext
ctx = CryptContext(schemes=['pbkdf2_sha512'])
print(ctx.hash("$NEW_PASS"))
EOF
)
echo "Updating password..."
# Step 5: Update DB
doas docker exec -i "$CONTAINER" bash -c \
"PGPASSWORD=\"$PASSWORD\" psql -h \"$HOST\" -U \"$USER\" -c \"UPDATE res_users SET password='$HASH' WHERE id=$USER_ID;\""
echo "Password updated successfully for $USER_LOGIN"
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
doas docker exec -it $1 bash -c 'PGPASSWORD="$PASSWORD" psql -h "$HOST" -U "$USER"'
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
# Check that a search string was provided
if [ -z "$1" ]; then
echo "Usage: $0 <search_string>"
exit 1
fi
SEARCH="$1"
DB_PATH="/4server/data/contracts.db"
# Get all UUIDs where tags include the search string
uuids=$(sqlite3 "$DB_PATH" "SELECT UUID FROM containers WHERE tags LIKE '%$SEARCH%';")
# Loop through each UUID
for uuid in $uuids; do
# Check if a container with this name is running
if doas docker ps --format '{{.Names}}' | grep -qx "$uuid"; then
echo "Restarting $uuid"
/4server/sbin/startContainer $uuid
fi
done
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
doas docker exec -it $1 bash -c 'PGPASSWORD="$PASSWORD" psql -h "$HOST" -U "$USER"'
+3 -3
View File
@@ -10,10 +10,10 @@ UUID="${UUID:-default}"
BRANCH="${BRANCH:-release}"
ODOO_DB_USER="${UUID}"
export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
#export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
echo "ENV: $HDD $DOMAIN_COUNT $BACKUP_SLOTS $CONTAINERDBID"
echo "ENV: $HDD $DOMAIN_SLOTS $BACKUP_SLOTS $CONTAINERDBID"
echo "DBID: $CONTAINERDBID"
BASEURL="${BASEURL:-/4server/data/$UUID}"
@@ -101,7 +101,7 @@ docker run -d --name "$UUID" \
-e PASSWORD="$ODOO_DB_PASSWORD" \
-e UUID="$UUID" \
-e HDD="$HDD" \
-e DOMAIN_COUNT="$DOMAIN_COUNT" \
-e DOMAIN_SLOTS="$DOMAIN_SLOTS" \
-e BACKUP_SLOTS="$BACKUP_SLOTS" \
-e WORKER="$WORKER" \
-e GIT="$GIT" \
+3 -3
View File
@@ -10,10 +10,10 @@ UUID="${UUID:-default}"
BRANCH="${BRANCH:-release}"
ODOO_DB_USER="${UUID}"
export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
#export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
echo "ENV: $HDD $DOMAIN_COUNT $BACKUP_SLOTS $CONTAINERDBID"
echo "ENV: $HDD $DOMAIN_SLOTS $BACKUP_SLOTS $CONTAINERDBID"
echo "DBID: $CONTAINERDBID"
BASEURL="${BASEURL:-/4server/data/$UUID}"
@@ -101,7 +101,7 @@ docker run -d --name "$UUID" \
-e PASSWORD="$ODOO_DB_PASSWORD" \
-e UUID="$UUID" \
-e HDD="$HDD" \
-e DOMAIN_COUNT="$DOMAIN_COUNT" \
-e DOMAIN_SLOTS="$DOMAIN_SLOTS" \
-e BACKUP_SLOTS="$BACKUP_SLOTS" \
-e WORKER="$WORKER" \
-e GIT="$GIT" \
+4 -4
View File
@@ -10,10 +10,10 @@ UUID="${UUID:-default}"
BRANCH="${BRANCH:-release}"
ODOO_DB_USER="${UUID}"
export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
#export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
echo "***** $ODOO_DB_PASSWORD"
echo "ENV: $HDD $DOMAIN_COUNT $BACKUP_SLOTS $CONTAINERDBID"
echo "ENV: $HDD $DOMAIN_SLOTS $BACKUP_SLOTS $CONTAINERDBID"
echo "DBID: $CONTAINERDBID"
BASEURL="${BASEURL:-/4server/data/$UUID}"
@@ -104,7 +104,7 @@ docker run -d --name "$UUID" \
-e PASSWORD="$ODOO_DB_PASSWORD" \
-e UUID="$UUID" \
-e HDD="$HDD" \
-e DOMAIN_COUNT="$DOMAIN_COUNT" \
-e DOMAIN_SLOTS="$DOMAIN_SLOTS" \
-e BACKUP_SLOTS="$BACKUP_SLOTS" \
-e WORKER="$WORKER" \
-e GIT="$GIT" \
+9 -6
View File
@@ -15,16 +15,20 @@ if [[ -z "$UUID" ]]; then
exit 1
fi
if [[ ! "$UUID" =~ ^[0-9a-fA-F-]+$ ]]; then
echo "ERROR: Invalid UUID format: $UUID"
exit 1
fi
DOMAIN_FILE="/4server/data/$UUID/etc/domain"
DB_FILE="/4server/data/contracts.db"
if [ -f "$DOMAIN_FILE" ]; then
DOMAINS=$(paste -sd "," "$DOMAIN_FILE")
sqlite3 "$DB_FILE" <<SQL
UPDATE containers
SET domains='$DOMAINS'
WHERE UUID='$UUID';
SQL
# Escape single quotes for SQLite ('' is the standard SQLite escape for ')
DOMAINS_SAFE="${DOMAINS//\'/\'\'}"
UUID_SAFE="${UUID//\'/\'\'}"
sqlite3 "$DB_FILE" "UPDATE containers SET domains='$DOMAINS_SAFE' WHERE UUID='$UUID_SAFE';"
fi
@@ -59,4 +63,3 @@ case "$SECOND_PART" in
exit 2
;;
esac