fixes backup slots
This commit is contained in:
@@ -4,5 +4,5 @@
|
|||||||
|
|
||||||
rex "doas sqlite3 /4server/data/contracts.db <<'EOF'
|
rex "doas sqlite3 /4server/data/contracts.db <<'EOF'
|
||||||
ALTER TABLE containers
|
ALTER TABLE containers
|
||||||
ADD COLUMN secret TEXT NOT NULL DEFAULT '';
|
ADD COLUMN config TEXT NOT NULL DEFAULT '';
|
||||||
EOF"
|
EOF"
|
||||||
|
|||||||
@@ -17,17 +17,17 @@ export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
|
|||||||
|
|
||||||
echo "PASSWORD $ODOO_DB_PASSWORD"
|
echo "PASSWORD $ODOO_DB_PASSWORD"
|
||||||
|
|
||||||
echo "Restoring $FILENAME to $1"
|
echo "Restoring $FILENAME to $UUID"
|
||||||
echo "status of container"
|
echo "status of container"
|
||||||
doas docker ps -a --filter "id=$UUID"
|
doas docker ps -a --filter "id=$UUID"
|
||||||
echo "POSTGRES HOST: $POSTGRES_HOST"
|
echo "POSTGRES HOST: $POSTGRES_HOST"
|
||||||
BACKUP="/mnt/backup/$2"
|
BACKUP="/mnt/backup/$2"
|
||||||
TEMPLATE="/mnt/db_images/$2"
|
TEMPLATE="/mnt/db_images/$2"
|
||||||
doas docker exec "${1%}" /bin/bash -c "[ -f $TEMPLATE ]"
|
doas docker exec "$UUID" /bin/bash -c "[ -f $TEMPLATE ]"
|
||||||
|
|
||||||
if doas docker exec "${1%}" /bin/bash -c "[ -f $BACKUP ]"; then
|
if doas docker exec "$UUID" /bin/bash -c "[ -f $BACKUP ]"; then
|
||||||
FILENAME="$BACKUP"
|
FILENAME="$BACKUP"
|
||||||
elif doas docker exec "${1%}" /bin/bash -c "[ -f $TEMPLATE ]"; then
|
elif doas docker exec "$UUID" /bin/bash -c "[ -f $TEMPLATE ]"; then
|
||||||
FILENAME="$TEMPLATE"
|
FILENAME="$TEMPLATE"
|
||||||
else
|
else
|
||||||
echo "File not exists"
|
echo "File not exists"
|
||||||
@@ -46,19 +46,19 @@ DROP DATABASE IF EXISTS \"$UUID\";
|
|||||||
|
|
||||||
PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \
|
PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \
|
||||||
-h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \
|
-h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \
|
||||||
-c "ALTER ROLE \"$1\" CREATEDB;"
|
-c "ALTER ROLE \"$UUID\" CREATEDB;"
|
||||||
|
|
||||||
|
|
||||||
doas docker exec "${1%}" rm -rf /home/odoo/.local/share/Odoo/filestore
|
doas docker exec "$UUID" rm -rf /home/odoo/.local/share/Odoo/filestore
|
||||||
|
|
||||||
doas docker exec "${1%}" odoo db --db_host beedb -w "$ODOO_DB_PASSWORD" -r "$1" load "$1" $FILENAME -f
|
doas docker exec "$UUID" odoo db --db_host beedb -w "$ODOO_DB_PASSWORD" -r "$UUID" load "$UUID" $FILENAME -f
|
||||||
|
|
||||||
PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \
|
PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \
|
||||||
-h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \
|
-h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \
|
||||||
-c "ALTER ROLE \"$1\" NOCREATEDB;"
|
-c "ALTER ROLE \"$UUID\" NOCREATEDB;"
|
||||||
|
|
||||||
|
|
||||||
doas docker exec "${1%}" cp -r /root/.local/share/Odoo/filestore /home/odoo/.local/share/Odoo/filestore
|
doas docker exec "$UUID" cp -r /root/.local/share/Odoo/filestore /home/odoo/.local/share/Odoo/filestore
|
||||||
doas docker exec "${1%}" chown -R odoo:odoo /home/odoo/.local/share/Odoo/filestore
|
doas docker exec "$UUID" chown -R odoo:odoo /home/odoo/.local
|
||||||
|
|
||||||
docker restart "${1%}"
|
docker restart "$UUID"
|
||||||
|
|||||||
77
app/sbin/api
77
app/sbin/api
@@ -108,6 +108,36 @@ class UUIDRequest(BaseModel):
|
|||||||
UUID: str
|
UUID: str
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------- Routes ----------------------
|
||||||
|
@app.get("/", include_in_schema=False)
|
||||||
|
def redirect_to_odoo():
|
||||||
|
return RedirectResponse(url="https://ODOO4PROJECTS.com")
|
||||||
|
|
||||||
|
from fastapi import FastAPI, Depends
|
||||||
|
from fastapi.responses import RedirectResponse
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Optional, Dict, Any
|
||||||
|
import json
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
# ---------------------- Models ----------------------
|
||||||
|
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
|
||||||
|
domains: Optional[str] = None
|
||||||
|
status: Optional[str] = None
|
||||||
|
created: Optional[str] = None
|
||||||
|
bump: Optional[str] = None
|
||||||
|
secret: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
# ---------------------- Routes ----------------------
|
# ---------------------- Routes ----------------------
|
||||||
@app.get("/", include_in_schema=False)
|
@app.get("/", include_in_schema=False)
|
||||||
def redirect_to_odoo():
|
def redirect_to_odoo():
|
||||||
@@ -116,20 +146,14 @@ def redirect_to_odoo():
|
|||||||
|
|
||||||
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
|
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
|
||||||
def update_container(request: ContainerModel):
|
def update_container(request: ContainerModel):
|
||||||
env_str = json.dumps(request.env) if isinstance(request.env, dict) else request.env
|
# Convert dict fields to JSON strings
|
||||||
secret_str = json.dumps(request.secret) if isinstance(request.secret, dict) else request.secret
|
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
|
||||||
|
|
||||||
|
# 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 existing:
|
if not existing:
|
||||||
execute_db("""
|
# If record does not exist, insert a new one with all given fields
|
||||||
UPDATE containers SET email=?, expires=?, tags=?, env=?, affiliate=?, image=?,
|
|
||||||
history=?, comment=?, domains=?, status=?, created=?, bump=?, secret=?
|
|
||||||
WHERE 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, request.UUID
|
|
||||||
))
|
|
||||||
else:
|
|
||||||
execute_db("""
|
execute_db("""
|
||||||
INSERT INTO containers (UUID, email, expires, tags, env, affiliate, image, history,
|
INSERT INTO containers (UUID, email, expires, tags, env, affiliate, image, history,
|
||||||
comment, domains, status, created, bump, secret)
|
comment, domains, status, created, bump, secret)
|
||||||
@@ -139,7 +163,32 @@ def update_container(request: ContainerModel):
|
|||||||
request.affiliate, request.image, request.history, request.comment,
|
request.affiliate, request.image, request.history, request.comment,
|
||||||
request.domains, request.status, request.created, request.bump, secret_str
|
request.domains, request.status, request.created, request.bump, secret_str
|
||||||
))
|
))
|
||||||
return {"message": "Container updated or created"}
|
return {"UUID": request.UUID, "status": "created"}
|
||||||
|
|
||||||
|
# Existing record found, do partial update
|
||||||
|
existing = existing[0] # Assuming fetch returns list of dicts
|
||||||
|
updates = {}
|
||||||
|
params = []
|
||||||
|
|
||||||
|
# Only add fields that are not None in the request
|
||||||
|
for field in ContainerModel.__fields__:
|
||||||
|
if field == "UUID":
|
||||||
|
continue
|
||||||
|
value = getattr(request, field)
|
||||||
|
if value is not None:
|
||||||
|
if field in ["env", "secret"]:
|
||||||
|
value = json.dumps(value)
|
||||||
|
updates[field] = value
|
||||||
|
params.append(value)
|
||||||
|
|
||||||
|
if updates:
|
||||||
|
# Build SQL dynamically
|
||||||
|
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": "no_change"}
|
||||||
|
|
||||||
|
|
||||||
@app.post("/container/start", dependencies=[Depends(verify_api_key)])
|
@app.post("/container/start", dependencies=[Depends(verify_api_key)])
|
||||||
|
|||||||
@@ -1,15 +1,48 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Backup Odoo database script
|
||||||
|
# Author: Your Name
|
||||||
|
# Description: Dumps Odoo DB, manages backups, and sets permissions
|
||||||
|
|
||||||
|
set -euo pipefail # Fail on error, undefined variables, and pipe errors
|
||||||
|
|
||||||
|
# Load helper functions
|
||||||
source /4server/sbin/helpers
|
source /4server/sbin/helpers
|
||||||
|
|
||||||
|
# Get contract info
|
||||||
get_contract_info
|
get_contract_info
|
||||||
export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
|
|
||||||
echo "PASSWORD $ODOO_DB_PASSWORD UUID $UUID"
|
# Export Odoo database password
|
||||||
|
export ODOO_DB_PASSWORD
|
||||||
|
ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
|
||||||
|
|
||||||
|
# Display basic info
|
||||||
|
echo "UUID: $UUID"
|
||||||
|
echo "Backup slots: $BACKUP_SLOTS"
|
||||||
|
|
||||||
|
# Create backup filename
|
||||||
|
FILENAME="$(date +"%Y%m%d_%H%M").zip"
|
||||||
|
BACKUP_DIR="/BACKUP/$UUID"
|
||||||
|
|
||||||
|
# Ensure backup directory exists
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Perform database dump using docker
|
||||||
|
doas docker exec "$UUID" odoo db \
|
||||||
|
--db_host beedb \
|
||||||
|
-r "$UUID" \
|
||||||
|
-w "$ODOO_DB_PASSWORD" \
|
||||||
|
--data-dir /home/odoo/.local/share/Odoo/ \
|
||||||
|
dump "$UUID" "/mnt/backup/$FILENAME"
|
||||||
|
|
||||||
|
# Set permissions for backup files
|
||||||
|
doas chmod 600 "$BACKUP_DIR"/*
|
||||||
|
doas docker exec "$UUID" chown odoo:odoo -R /mnt/backup
|
||||||
|
|
||||||
|
|
||||||
FILENAME=$(date +"%Y%m%d_%H:%M")".zip"
|
# Remove old backups beyond the configured slots
|
||||||
|
ls -t "$BACKUP_DIR"/[0-9]*.zip 2>/dev/null | tail -n +$((BACKUP_SLOTS + 1)) | while read -r file; do
|
||||||
doas docker exec "$UUID" odoo db --db_host beedb -r "$UUID" -w "$ODOO_DB_PASSWORD" --data-dir /home/odoo/.local/share/Odoo/ dump "$UUID" /mnt/backup/$FILENAME
|
echo "Deleting old backup: $file"
|
||||||
|
rm -f "$file"
|
||||||
doas chmod 666 /BACKUP/$UUID/*
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
app/sbin/contractInfo
Executable file
14
app/sbin/contractInfo
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
export PATH=/4PROJECTS/bin:$PATH
|
||||||
|
if [ ! -n "$1" ]; then
|
||||||
|
echo "Missing Parameters <UUID>"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
UUID=$1
|
||||||
|
echo "UUID: $UUID"
|
||||||
|
|
||||||
|
source /4server/sbin/helpers
|
||||||
|
|
||||||
|
get_contract_info
|
||||||
|
|
||||||
|
env
|
||||||
@@ -31,12 +31,13 @@ done < <(sqlite3 "$DB_PATH" "
|
|||||||
UNION ALL SELECT 'STATUS=' || status 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 'CREATED=' || created FROM containers WHERE UUID='$UUID'
|
||||||
UNION ALL SELECT 'SECRET=' || secret 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';
|
UNION ALL SELECT 'BUMP=' || bump FROM containers WHERE UUID='$UUID';
|
||||||
")
|
")
|
||||||
|
|
||||||
|
|
||||||
# Debug: print loaded environment variables
|
# Debug: print loaded environment variables
|
||||||
env | grep -E 'UUID|EMAIL|EXPIRES|TAGS|ENV|AFFILIATE|IMAGE|HISTORY|COMMENT|DOMAINS|STATUS|CREATED|BUMP|SECRET'
|
env | grep -E 'UUID|EMAIL|EXPIRES|TAGS|ENV|AFFILIATE|IMAGE|HISTORY|COMMENT|DOMAINS|STATUS|CREATED|BUMP|SECRET'
|
||||||
|
eval $(echo "$ENV" | jq -r 'to_entries | .[] | "export \(.key | ascii_upcase)=\(.value)"')
|
||||||
|
|
||||||
eval $(echo "$ENV" | jq -r 'to_entries | .[] | "export \(.key)=\(.value)"')
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ BRANCH="${BRANCH:-release}"
|
|||||||
ODOO_DB_USER="${UUID}"
|
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"
|
||||||
|
|
||||||
|
|
||||||
BASEURL="${BASEURL:-/4server/data/$UUID}"
|
BASEURL="${BASEURL:-/4server/data/$UUID}"
|
||||||
DATA_DIR="$BASEURL/odoo/"
|
DATA_DIR="$BASEURL/odoo/"
|
||||||
@@ -23,6 +25,7 @@ BACKUP_DIR="/BACKUP/$UUID"
|
|||||||
GIT_DIR="$BASEURL/git-server/"
|
GIT_DIR="$BASEURL/git-server/"
|
||||||
INSTALL_DIR="$BASEURL/install/"
|
INSTALL_DIR="$BASEURL/install/"
|
||||||
SSH_DIR="$BASEURL/.ssh/"
|
SSH_DIR="$BASEURL/.ssh/"
|
||||||
|
ETC_DIR="$BASEURL/etc/"
|
||||||
|
|
||||||
SERVER_IP=$(ip -4 addr show eth0 | awk '/inet/ {print $2}' | cut -d/ -f1)
|
SERVER_IP=$(ip -4 addr show eth0 | awk '/inet/ {print $2}' | cut -d/ -f1)
|
||||||
|
|
||||||
@@ -31,9 +34,11 @@ DOMAIN_LABEL="traefik.http.routers.$UUID.rule=Host(\`$UUID.odoo4projects.com\`)"
|
|||||||
|
|
||||||
|
|
||||||
doas find "$BASEURL" -type d -exec chmod 777 {} \;
|
doas find "$BASEURL" -type d -exec chmod 777 {} \;
|
||||||
doas chmod 777 $BACKUP_DIR
|
|
||||||
|
|
||||||
PORT=$((RANDOM%1000+2200))
|
PORT=$($CONTAINERDBID+2200)
|
||||||
|
echo "PORT $PORT"
|
||||||
|
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > "${ETC_DIR}/gitpath"
|
||||||
|
|
||||||
|
|
||||||
doas docker stop "$UUID" 2>/dev/null
|
doas docker stop "$UUID" 2>/dev/null
|
||||||
doas docker rm "$UUID" 2>/dev/null
|
doas docker rm "$UUID" 2>/dev/null
|
||||||
@@ -53,12 +58,18 @@ doas docker run -d --name "$UUID" \
|
|||||||
-v "$GIT_DIR:/git-server" \
|
-v "$GIT_DIR:/git-server" \
|
||||||
-v "$INSTALL_DIR:/mnt/install" \
|
-v "$INSTALL_DIR:/mnt/install" \
|
||||||
-v "$SSH_DIR:/etc/sshkey" \
|
-v "$SSH_DIR:/etc/sshkey" \
|
||||||
|
-v "$ETC_DIR:/mnt/etc" \
|
||||||
-p "$PORT:22" \
|
-p "$PORT:22" \
|
||||||
-e HOST="beedb" \
|
-e HOST="beedb" \
|
||||||
-e USER="$ODOO_DB_USER" \
|
-e USER="$ODOO_DB_USER" \
|
||||||
-e PASSWORD="$ODOO_DB_PASSWORD" \
|
-e PASSWORD="$ODOO_DB_PASSWORD" \
|
||||||
-e UUID="$UUID" \
|
-e UUID="$UUID" \
|
||||||
--label "$DOMAIN_LABEL" \
|
-e HDD="$HDD" \
|
||||||
|
-e DOMAIN_COUNT="$DOMAIN_COUNT" \
|
||||||
|
-e BACKUP_SLOTS="$BACKUP_SLOTS" \
|
||||||
|
-e WORKER="$WORKER" \
|
||||||
|
-e GIT="$GIT" \
|
||||||
|
--label "$DOMAIN_LABEL" \
|
||||||
--label "traefik.http.services.$UUID.loadbalancer.server.port=8069" \
|
--label "traefik.http.services.$UUID.loadbalancer.server.port=8069" \
|
||||||
--label "traefic.http.routers.$UUID.entrypoints=web, websecure" \
|
--label "traefic.http.routers.$UUID.entrypoints=web, websecure" \
|
||||||
--label "traefik.http.routers.$UUID.tls.certresolver=production" \
|
--label "traefik.http.routers.$UUID.tls.certresolver=production" \
|
||||||
@@ -67,4 +78,9 @@ doas docker run -d --name "$UUID" \
|
|||||||
docker.odoo4projects.com/4projects/odoo_19:$BRANCH
|
docker.odoo4projects.com/4projects/odoo_19:$BRANCH
|
||||||
|
|
||||||
|
|
||||||
|
doas docker exec $UUID chown -R odoo:odoo /home/odoo/.local
|
||||||
|
doas docker exec $UUID chown -R odoo:odoo /mnt/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
check_and_create_db
|
check_and_create_db
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
#--label "traefik.http.routers.${UUID}.middlewares=cors-headers@file" \
|
||||||
|
|
||||||
echo "Start N8N container ${UUID}"
|
echo "Start N8N container ${UUID}"
|
||||||
|
|
||||||
# Get the hostname of the machine
|
# Get the hostname of the machine
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ http:
|
|||||||
address: http://bouncer-traefik:8080/api/v1/forwardAuth
|
address: http://bouncer-traefik:8080/api/v1/forwardAuth
|
||||||
trustForwardHeader: true
|
trustForwardHeader: true
|
||||||
|
|
||||||
|
cors-headers:
|
||||||
|
headers:
|
||||||
|
accessControlAllowCredentials: true
|
||||||
|
|
||||||
|
|
||||||
routers:
|
routers:
|
||||||
api-router:
|
api-router:
|
||||||
|
|||||||
9
app/update_sbin
Executable file
9
app/update_sbin
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Running prsync ./sbin"
|
||||||
|
prsync -h "/app/host_vars/hosts" -avz ./sbin/ /4server/sbin/
|
||||||
|
|
||||||
|
rex doas rc-service api restart
|
||||||
|
|
||||||
|
rex doas rc-service checkCalls restart
|
||||||
|
|
||||||
Binary file not shown.
Reference in New Issue
Block a user