This commit is contained in:
Oliver
2025-08-16 07:37:53 +02:00
parent 140a712abf
commit c18187f407
11 changed files with 615 additions and 92 deletions

View File

@@ -1,5 +1,5 @@
Host dev
Hostname 192.168.111.209
Hostname dev
User oliver
Port 2222

View File

@@ -1,9 +0,0 @@
127.0.0.1 dev
::1 dev
192.168.111.209 dev n8n
192.168.9.11 saopaulo
192.168.9.17 mumbai
192.168.9.15 london
192.168.9.16 boston

View File

@@ -11,3 +11,7 @@
192.168.9.16 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCLzyfVrbCNJW9tNTkxMy8IDLGyQoqkxlGN+TirLoNyw5GD1XpJgvHIBy//6tDEIuAfL5ouqp0T+PM00nSj6gEjGeTQtjrzAeSXJ5D3Q3+Vl92j1uSPPhnChRnidI2mrjvNuaukaDxBMwIvr9sagTvtZwCupKbuYeW0kQqCwnSIjTS7OwcrCRm3RtzC8bOPpOIHYaLxV6OnyoRXKLv9Lu987nuNoTcZu61jyCHhFTzzN3Y3KRpioshUoHiukgJbJQVnRuVkxQRknWa5gS4ATLLUG70taTs0Ld4Canyrym4aVV9pw5rDwH0rkidvkz8OLX049mIeGhv/QPRH8x5bgtPezKkiOcPW22HG0+z+7zHgbkTKlcvGr1JdhkTN6jqL4HyYdhMj04v7miv8LnxjaBNb3iNFQiAs5aV5LmPevYP+/94TGBIlTVCh5oTyeDJ1OKmZKL9ZUUfu0Ozz+v3O3en4hNMOI8P+uujfIxfvn/Pasxh4r7pTGYQV9nseCmrsl0k=
192.168.9.16 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLtNCuNwiidC4IdZci3J0s/vbcTtFZod47BKd8GKyGrucOS402fuZ03F1elrEKjA0PcFNZQR7MbEvF6zDjEfoPY=
[dev]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILf8g96UGmWCLf5C5qfGgir3ned83s5HXNpM231A0rUu
[dev]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC45Aw7jQXh3/QOMOCkM4wvz4/yXxpjQU5C2ZMJ/76lTPB/DsvP9C+DGKqO3zzznOhdaYzTb5lipMguWRyH0RYlwYtR7TnYKTZgioXC/+kSdVzgAUeqcUCUIoNH5CSp/lgsAp1XxQTPk3ooZJc57cTnHo78Y+oOj7bF8u8Nin/q+uTTrgXVkbMCZYSX+CA/fHtmatH9vMdAbPv/Bx9M72vijMMZWOP/6hwRhn3C0s2o1rgz/nXe5u3HYIodwzItqdceF3k6hLuZP8Bb+kKz42wXstke5SXivnUm3uDdkLNKjKWnSWoD7TAIA9w6MuFbLBLL6QRBmfcx74F6aeuV55ItzRPVAz0XEqQU55r3nS9r7zLyT0HGvu4Wt+Zf97nHKfWucaf/5UFWoTC9pijYEYbNyhYockyzM+QAx3/n6cfwIjlc/wFkU8nd7fUjfkymTlIX6UiT/12b+TrFuOLBk4mylDGkPge7zfslvH/LOyokzCRsz75Sh3bc7bxB1ppPrjc=
[dev]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK+WCqjyl6CKaDnMAcfqGYty8KoWqh95T0lQK3RFcNfHom4rsZljS2tPlicfRSHT/2zWH7HfQ9T2t/2PYjWjxrc=

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
from fastapi import FastAPI, HTTPException, Depends, Response
from fastapi.security.api_key import APIKeyHeader
from fastapi.responses import RedirectResponse
@@ -8,9 +7,9 @@ import psutil
import sqlite3
import subprocess
import os
import sys
import uvicorn
from typing import Optional
from datetime import datetime
# Constants
DB_PATH = "/4server/data/contracts.db"
@@ -20,8 +19,6 @@ VERSION = "API: 0.0.5"
# FastAPI app
app = FastAPI()
# Security
api_key_header = APIKeyHeader(name="X-API-Key")
@@ -29,7 +26,16 @@ def verify_api_key(key: str = Depends(api_key_header)):
if key != API_KEY:
raise HTTPException(status_code=403, detail="Unauthorized")
# ---------------------- Database ----------------------
# ---------------------- Helpers ----------------------
def run_command(cmd: list[str]) -> str:
"""Run a shell command and return stdout or raise HTTPException on error."""
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise HTTPException(status_code=500, detail=result.stderr.strip() or "Unknown error")
return result.stdout.strip()
def init_db():
"""Initialize the database with containers table."""
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
@@ -43,12 +49,12 @@ def init_db():
expires DATE,
tags TEXT,
env TEXT,
affiliate char(30),
image char(50),
history text,
comment text,
domains text,
status char (20).
affiliate CHAR(30),
image CHAR(50),
history TEXT,
comment TEXT,
domains TEXT,
status CHAR(20),
created DATE,
bump DATE
)
@@ -57,6 +63,16 @@ def init_db():
conn.close()
def execute_db(query: str, params: tuple = (), fetch: bool = False):
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute(query, params)
conn.commit()
data = cursor.fetchall() if fetch else None
conn.close()
return data
# ---------------------- Models ----------------------
class ContainerModel(BaseModel):
UUID: str
@@ -65,95 +81,150 @@ class ContainerModel(BaseModel):
tags: Optional[str] = None
env: Optional[str] = None
affiliate: Optional[str] = None
image: Optional[str} = None
image: Optional[str] = None
history: Optional[str] = None
comment: Optional[str] = None
domains: Optional[str] = None
status: str
created: str
bump: Optional[str] = None
class StartContainerRequest(BaseModel):
uuid: str
email: str
class ContainerIDRequest(BaseModel):
container_id: str
# ---------------------- CONTAINER Routes ----------------------
class UpdateContainerRequest(ContainerModel):
pass
class InfoContainerRequest(BaseModel):
container_id: Optional[str] = None
# ---------------------- Routes ----------------------
@app.get("/", include_in_schema=False)
def redirect_to_odoo():
return RedirectResponse(url="https://ODOO4PROJECTS.com")
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
def update_container(request: UpdateContainerRequest):
--> Insert the new container into the database. Create, if container does not exist
existing = execute_db("SELECT * FROM containers WHERE UUID = ?", (request.UUID,), fetch=True)
if existing:
execute_db("""
UPDATE containers SET email=?, expires=?, tags=?, env=?, affiliate=?, image=?,
history=?, comment=?, domains=?, status=?, created=?, bump=?
WHERE UUID=?
""", (
request.email, request.expires, request.tags, request.env, request.affiliate,
request.image, request.history, request.comment, request.domains, request.status,
request.created, request.bump, request.UUID
))
else:
execute_db("""
INSERT INTO containers (UUID, email, expires, tags, env, affiliate, image, history,
comment, domains, status, created, bump)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
request.UUID, request.email, request.expires, request.tags, request.env,
request.affiliate, request.image, request.history, request.comment,
request.domains, request.status, request.created, request.bump
))
return {"message": "Container updated or created"}
@app.post("/container/start", dependencies=[Depends(verify_api_key)])
def start_container(request: StartContainerRequest):
--> refactor, so that only the container is is given in the request. the shell script BIN_PATH/startContainer is called withtge containerid as parameter
def start_container(request: ContainerIDRequest):
return {"message": run_command([f"{BIN_PATH}/startContainer", request.container_id])}
@app.post("/container/stop", dependencies=[Depends(verify_api_key)])
def stop_container(request: StopContainerRequest):
--> refactor, so that only the container is is given in the request. the shell script BIN_PATH/stopContainer is called withtge containerid as parameter
def stop_container(request: ContainerIDRequest):
return {"message": run_command([f"{BIN_PATH}/stopContainer", request.container_id])}
@app.post("/container/nuke", dependencies=[Depends(verify_api_key)])
def nuke_container(request: StopContainerRequest):
--> refactor, so that only the container is is given in the request.
when the status of the database is "nuke" then
the shell script BIN_PATH/nukeContainer is called withtge containerid as parameter
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":
raise HTTPException(400, "Container status is not 'nuke'")
return {"message": run_command([f"{BIN_PATH}/nukeContainer", request.container_id])}
@app.post("/container/info", dependencies=[Depends(verify_api_key)])
def info_container(request: InfoContainerRequest):
--> refactor: When no container id is given, query all containers from the database. when a containeris is given, just select that one. Return the result
--> create an endpoint that changes the container image to the latest version of that image /container/bump besides updating the container image, also update the SQL for this container and put the current date into "bump"
--> add /container/quota return the disk and ram usage of this container. I think you can obtain this from docker
if request.container_id:
rows = execute_db("SELECT * FROM containers WHERE UUID=?", (request.container_id,), fetch=True)
else:
rows = execute_db("SELECT * FROM containers", fetch=True)
return {"containers": rows}
# ------------------------ SYSTEM Routes
@app.post("/container/bump", dependencies=[Depends(verify_api_key)])
def bump_container(request: ContainerIDRequest):
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])
return {"message": msg, "bump_date": today}
@app.post("/container/quota", dependencies=[Depends(verify_api_key)])
def container_quota(request: ContainerIDRequest):
output = run_command([
"docker", "stats", request.container_id, "--no-stream",
"--format", "{{.MemUsage}},{{.BlockIO}}"
])
mem_usage, disk_usage = output.split(",")
return {"memory_usage": mem_usage, "disk_io": disk_usage}
# ---------------------- SYSTEM ----------------------
@app.get("/system/containers", dependencies=[Depends(verify_api_key)])
def get_containers():
result = subprocess.run([BIN_PATH+'/getContainers'], capture_output=True, text=True)
if result.returncode != 0:
return Response(content='{"error": "Script failed"}', media_type="application/json", status_code=500)
return Response(content=result.stdout, 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)])
def list_images():
images = run_command(["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"])
return {"images": images.split("\n")}
--> create an endpoint that lkists all docker images available on the system /system/images
@app.get("/system/info", dependencies=[Depends(verify_api_key)])
def get_system_info():
return all INFOas JSON
in this function add last_update and return the content of /4server/data/update
if this file does not exist return NONE
also add the latest bump date of all images in the database
return the VERSION as well.
try:
alpine_version = None
last_update = None
bump_dates = execute_db("SELECT MAX(bump) FROM containers", fetch=True)[0][0]
if os.path.exists("/4server/data/update"):
with open("/4server/data/update") as f:
last_update = f.read().strip()
if os.path.exists("/etc/alpine-release"):
with open("/etc/alpine-release") as f:
version = f.read().strip()
return {"alpine_version": version}
except FileNotFoundError:
raise HTTPException(status_code=404, detail="File not found. Press play on tape")
alpine_version = f.read().strip()
mem = psutil.virtual_memory()
disk = psutil.disk_usage("/")
cpu_count = psutil.cpu_count(logical=True)
return {
"alpine_version": alpine_version,
"last_update": last_update,
"latest_bump": bump_dates,
"version": VERSION,
"resources": {
"memory": {"total": mem.total, "available": mem.available, "used": mem.used},
"disk": {"total": disk.total, "used": disk.used, "free": disk.free},
"cpu_count": cpu_count
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/system/resources", dependencies=[Depends(verify_api_key)])
def get_resources():
@app.post("/system/pull", dependencies=[Depends(verify_api_key)])
def pull_all_images():
return {"message": run_command([f"{BIN_PATH}/pullAllContainers"])}
--> consolidate this API into /system/info
mem = psutil.virtual_memory()
disk = psutil.disk_usage("/")
return {
"memory": {"total": mem.total, "available": mem.available, "used": mem.used},
"disk": {"total": disk.total, "used": disk.used, "free": disk.free},
"cpu_count": psutil.cpu_count(logical=True),
}
--> create an endpoint that docker pulls all containers /system/pull
# ---------------------- Entry Point ----------------------
if __name__ == "__main__":

View File

@@ -1,14 +1,55 @@
this script gets a container UUID
#!/bin/bash
# Usage: ./start_by_uuid.sh <uuid>
# Example: ./start_by_uuid.sh abc-001-xxxx-xxxx-xxxx
Wtrite a bash script, that gets all info out off the Sqlite3 Database usind the UUID and stores the values in environment variables
DB_PATH="/4server/data/contracts.db"
BIN_PATH="/4server/sbin"
setr the BIN_BATH to /4srver/sbin/
UUID="$1"
the uuid looks like xxx-xxx-xxxx-xxxx-xxxx-....
if [[ -z "$UUID" ]]; then
echo "Usage: $0 <uuid>"
exit 1
fi
get the second number
# Fetch all info from SQLite and export as environment variables
eval $(sqlite3 -separator "=" "$DB_PATH" \
"SELECT 'UUID=' || UUID,
'EMAIL=' || email,
'EXPIRES=' || expires,
'TAGS=' || tags,
'ENV=' || env,
'AFFILIATE=' || affiliate,
'IMAGE=' || image,
'HISTORY=' || history,
'COMMENT=' || comment,
'DOMAINS=' || domains,
'STATUS=' || status,
'CREATED=' || created,
'BUMP=' || bump
FROM containers WHERE UUID='$UUID';" | sed 's/ /\\ /g')
# Debug: print loaded environment variables
# env | grep -E 'UUID|EMAIL|EXPIRES|TAGS|ENV|AFFILIATE|IMAGE|HISTORY|COMMENT|DOMAINS|STATUS|CREATED|BUMP'
# Extract the second part of UUID (split by "-")
SECOND_PART=$(echo "$UUID" | cut -d'-' -f2)
# Decide which script to run
case "$SECOND_PART" in
001)
"$BIN_PATH/start/n8n"
;;
002)
"$BIN_PATH/start/ODOO18"
;;
003)
"$BIN_PATH/start/ODOO19"
;;
*)
echo "Unknown UUID type: $SECOND_PART"
exit 2
;;
esac
When the number is 001 call the script BIN_PATH/start/n8n
When the number is 002 call the sctipr BIN_ÜATH/start/ODOO18
WHen the number is 003 call the script BIN_PATH/start/ODOO19

233
app/test/api.json Normal file
View File

@@ -0,0 +1,233 @@
{
"openapi": "3.0.0",
"info": {
"title": "Container Management API",
"version": "0.0.5",
"description": "API for managing containers and system resources."
},
"servers": [
{ "url": "http://localhost:8888" }
],
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "X-API-Key"
}
},
"schemas": {
"ContainerModel": {
"type": "object",
"properties": {
"UUID": { "type": "string" },
"email": { "type": "string" },
"expires": { "type": "string", "format": "date" },
"tags": { "type": "string" },
"env": { "type": "string" },
"affiliate": { "type": "string" },
"image": { "type": "string" },
"history": { "type": "string" },
"comment": { "type": "string" },
"domains": { "type": "string" },
"status": { "type": "string" },
"created": { "type": "string", "format": "date" },
"bump": { "type": "string", "format": "date" }
},
"required": ["UUID", "email", "expires", "status", "created"]
},
"ContainerIDRequest": {
"type": "object",
"properties": {
"container_id": { "type": "string" }
},
"required": ["container_id"]
},
"InfoContainerRequest": {
"type": "object",
"properties": {
"container_id": { "type": "string" }
}
}
}
},
"security": [{ "ApiKeyAuth": [] }],
"paths": {
"/": {
"get": {
"summary": "Root redirect",
"responses": {
"302": { "description": "Redirect to ODOO4PROJECTS.com" }
}
}
},
"/container/update": {
"post": {
"summary": "Create or update container",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ContainerModel" }
}
}
},
"responses": {
"200": {
"description": "Container updated or created",
"content": { "application/json": { "example": { "message": "Container updated or created" } } }
}
}
}
},
"/container/start": {
"post": {
"summary": "Start a container",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContainerIDRequest" } } }
},
"responses": { "200": { "description": "Container started" } }
}
},
"/container/stop": {
"post": {
"summary": "Stop a container",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContainerIDRequest" } } }
},
"responses": { "200": { "description": "Container stopped" } }
}
},
"/container/nuke": {
"post": {
"summary": "Nuke a container",
"description": "Permanently deletes container if its status is 'nuke'.",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContainerIDRequest" } } }
},
"responses": {
"200": { "description": "Container nuked" },
"400": { "description": "Container status is not 'nuke'" }
}
}
},
"/container/info": {
"post": {
"summary": "Get container info",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/InfoContainerRequest" } } }
},
"responses": { "200": { "description": "Container info list" } }
}
},
"/container/bump": {
"post": {
"summary": "Bump a container",
"description": "Updates bump date and runs bump script.",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContainerIDRequest" } } }
},
"responses": {
"200": { "description": "Bump successful", "content": { "application/json": {} } }
}
}
},
"/container/quota": {
"post": {
"summary": "Get container quota",
"security": [{ "ApiKeyAuth": [] }],
"requestBody": {
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContainerIDRequest" } } }
},
"responses": {
"200": {
"description": "Quota usage",
"content": {
"application/json": {
"example": {
"memory_usage": "50MiB / 2GiB",
"disk_io": "10MB / 200MB"
}
}
}
}
}
}
},
"/system/containers": {
"get": {
"summary": "List running containers",
"security": [{ "ApiKeyAuth": [] }],
"responses": {
"200": {
"description": "Containers in system",
"content": { "application/json": {} }
}
}
}
},
"/system/images": {
"get": {
"summary": "List system images",
"security": [{ "ApiKeyAuth": [] }],
"responses": {
"200": {
"description": "List of docker images",
"content": {
"application/json": {
"example": {
"images": ["repo1:tag", "repo2:tag"]
}
}
}
}
}
}
},
"/system/info": {
"get": {
"summary": "Get system info",
"security": [{ "ApiKeyAuth": [] }],
"responses": {
"200": {
"description": "System resource info",
"content": {
"application/json": {
"example": {
"alpine_version": "3.18.2",
"last_update": "2025-08-01",
"latest_bump": "2025-08-10",
"version": "API: 0.0.5",
"resources": {
"memory": { "total": 16777216, "available": 8388608, "used": 8388608 },
"disk": { "total": 100000000, "used": 50000000, "free": 50000000 },
"cpu_count": 8
}
}
}
}
}
}
}
},
"/system/pull": {
"post": {
"summary": "Pull all images",
"security": [{ "ApiKeyAuth": [] }],
"responses": {
"200": {
"description": "All images pulled",
"content": { "application/json": { "example": { "message": "All images pulled" } } }
}
}
}
}
}
}

View File

@@ -1,8 +0,0 @@
write a curl request that creatrs a container with
a uuid starting with 000-001-....
email o.arnold@projektbox.de
domain n8n.local
and the rest with sane info

53
app/test/runner.sh Normal file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
#
# run_all_tests.sh — simple runner for test_api.sh
#
API_SCRIPT="./test_api.sh"
# Make sure test_api.sh is executable
if [ ! -x "$API_SCRIPT" ]; then
echo "Error: $API_SCRIPT not found or not executable"
exit 1
fi
# List of tests to run (must match functions in test_api.sh)
TESTS=(
root_redirect
update_container
start_container
stop_container
nuke_container
info_all
info_one
bump_container
container_quota
system_containers
system_images
system_info
system_pull
)
ok_count=0
fail_count=0
echo "Running API tests..."
echo "===================="
for test in "${TESTS[@]}"; do
# Run test, capture HTTP status code only
status=$($API_SCRIPT $test -s -o /dev/null -w "%{http_code}")
if [[ "$status" == "200" || "$status" == "302" ]]; then
echo "[OK ] $test"
((ok_count++))
else
echo "[NOK] $test (HTTP $status)"
((fail_count++))
fi
done
echo "===================="
echo "Summary: $ok_count OK, $fail_count NOK"
exit $fail_count

View File

@@ -1,5 +0,0 @@
start the container
000-001-
add a random uuid

141
app/test/test.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/bin/bash
#
# test_api.sh — cURL test suite for Container Management API
#
# ========= CONFIG =========
API_KEY="your-secret-api-key"
BASE_URL="http://localhost:8888"
CONTAINER_ID="123e4567-e89b-12d3-a456-426614174000" # sample UUID
# ==========================
# --- Functions for each endpoint ---
root_redirect() {
curl -i "$BASE_URL/"
}
update_container() {
curl -X POST "$BASE_URL/container/update" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
"UUID": "'"$CONTAINER_ID"'",
"email": "user@example.com",
"expires": "2025-12-31",
"status": "active",
"created": "2025-08-16"
}'
}
start_container() {
curl -X POST "$BASE_URL/container/start" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
stop_container() {
curl -X POST "$BASE_URL/container/stop" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
nuke_container() {
curl -X POST "$BASE_URL/container/nuke" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
info_all() {
curl -X POST "$BASE_URL/container/info" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{}'
}
info_one() {
curl -X POST "$BASE_URL/container/info" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
bump_container() {
curl -X POST "$BASE_URL/container/bump" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
container_quota() {
curl -X POST "$BASE_URL/container/quota" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{ "container_id": "'"$CONTAINER_ID"'" }'
}
system_containers() {
curl -X GET "$BASE_URL/system/containers" \
-H "X-API-Key: $API_KEY"
}
system_images() {
curl -X GET "$BASE_URL/system/images" \
-H "X-API-Key: $API_KEY"
}
system_info() {
curl -X GET "$BASE_URL/system/info" \
-H "X-API-Key: $API_KEY"
}
system_pull() {
curl -X POST "$BASE_URL/system/pull" \
-H "X-API-Key: $API_KEY"
}
# --- Help message ---
show_help() {
cat <<EOF
Usage: $0 <command>
Available commands:
root_redirect - Test root redirect
update_container - Create or update container
start_container - Start container
stop_container - Stop container
nuke_container - Nuke container (status must be "nuke")
info_all - Get info for all containers
info_one - Get info for one container
bump_container - Bump container
container_quota - Show container quota
system_containers - List running containers
system_images - List docker images
system_info - Show system information
system_pull - Pull all container images
Examples:
$0 update_container
$0 system_info
EOF
}
# --- Main ---
if [ $# -eq 0 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
show_help
exit 0
fi
cmd="$1"
shift
if declare -f "$cmd" >/dev/null 2>&1; then
"$cmd" "$@"
else
echo "Unknown command: $cmd"
show_help
exit 1
fi

View File

@@ -6,4 +6,6 @@ services:
- ./app:/app
tty: true
privileged: true
extra_hosts:
- "dev:192.168.9.221"