Streamlit Instances: - Add Publish button with HAProxy integration (uses instance port) - Add Edit dialog for modifying instance settings - Replace enable/disable buttons with checkbox - Get LAN IP dynamically from status data - Bump luci-app-streamlit to r8 HAProxy: - Add haproxy-acme-cron script for background cert processing - Cron runs every 5 minutes to issue pending ACME certificates - Prevents UI blocking during certificate issuance - Bump secubox-app-haproxy to r19 RPCD: - Fix json_error to return consistent format with json_success Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
764 lines
18 KiB
Bash
764 lines
18 KiB
Bash
#!/bin/sh
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
# LuCI RPC backend for Streamlit Platform
|
|
# Copyright (C) 2025 CyberMind.fr
|
|
|
|
. /lib/functions.sh
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
CONFIG="streamlit"
|
|
LXC_NAME="streamlit"
|
|
LXC_PATH="/srv/lxc"
|
|
APPS_PATH="/srv/streamlit/apps"
|
|
|
|
# JSON helpers
|
|
json_init_obj() { json_init; json_add_object "result"; }
|
|
json_close_obj() { json_close_object; json_dump; }
|
|
|
|
json_error() {
|
|
json_init_obj
|
|
json_add_boolean "success" 0
|
|
json_add_string "message" "$1"
|
|
json_close_obj
|
|
}
|
|
|
|
json_success() {
|
|
json_init_obj
|
|
json_add_boolean "success" 1
|
|
[ -n "$1" ] && json_add_string "message" "$1"
|
|
json_close_obj
|
|
}
|
|
|
|
# Check if container is running
|
|
lxc_running() {
|
|
lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"
|
|
}
|
|
|
|
# Check if container exists
|
|
lxc_exists() {
|
|
[ -f "$LXC_PATH/$LXC_NAME/config" ] && [ -d "$LXC_PATH/$LXC_NAME/rootfs" ]
|
|
}
|
|
|
|
# Get service status
|
|
get_status() {
|
|
local enabled running installed uptime
|
|
local http_port data_path memory_limit active_app
|
|
|
|
config_load "$CONFIG"
|
|
config_get enabled main enabled "0"
|
|
config_get http_port main http_port "8501"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
config_get memory_limit main memory_limit "512M"
|
|
config_get active_app main active_app "hello"
|
|
|
|
running="false"
|
|
installed="false"
|
|
uptime=""
|
|
|
|
if lxc_exists; then
|
|
installed="true"
|
|
fi
|
|
|
|
if lxc_running; then
|
|
running="true"
|
|
uptime=$(lxc-info -n "$LXC_NAME" 2>/dev/null | grep -i "cpu use" | head -1 | awk '{print $3}')
|
|
fi
|
|
|
|
# Count apps
|
|
local app_count=0
|
|
APPS_PATH="$data_path/apps"
|
|
if [ -d "$APPS_PATH" ]; then
|
|
app_count=$(ls -1 "$APPS_PATH"/*.py 2>/dev/null | wc -l)
|
|
fi
|
|
|
|
# Get LAN IP for URL
|
|
local lan_ip
|
|
lan_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")
|
|
|
|
json_init_obj
|
|
json_add_boolean "enabled" "$( [ "$enabled" = "1" ] && echo 1 || echo 0 )"
|
|
json_add_boolean "running" "$( [ "$running" = "true" ] && echo 1 || echo 0 )"
|
|
json_add_boolean "installed" "$( [ "$installed" = "true" ] && echo 1 || echo 0 )"
|
|
json_add_string "uptime" "$uptime"
|
|
json_add_int "http_port" "$http_port"
|
|
json_add_string "data_path" "$data_path"
|
|
json_add_string "memory_limit" "$memory_limit"
|
|
json_add_string "active_app" "$active_app"
|
|
json_add_int "app_count" "$app_count"
|
|
json_add_string "web_url" "http://${lan_ip}:${http_port}"
|
|
json_add_string "container_name" "$LXC_NAME"
|
|
json_close_obj
|
|
}
|
|
|
|
# Get configuration
|
|
get_config() {
|
|
local http_port http_host data_path memory_limit enabled active_app
|
|
local headless gather_stats theme_base theme_primary
|
|
|
|
config_load "$CONFIG"
|
|
|
|
# Main settings
|
|
config_get http_port main http_port "8501"
|
|
config_get http_host main http_host "0.0.0.0"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
config_get memory_limit main memory_limit "512M"
|
|
config_get enabled main enabled "0"
|
|
config_get active_app main active_app "hello"
|
|
|
|
# Server settings
|
|
config_get headless server headless "true"
|
|
config_get gather_stats server browser_gather_usage_stats "false"
|
|
config_get theme_base server theme_base "dark"
|
|
config_get theme_primary server theme_primary_color "#0ff"
|
|
|
|
json_init_obj
|
|
json_add_object "main"
|
|
json_add_boolean "enabled" "$( [ "$enabled" = "1" ] && echo 1 || echo 0 )"
|
|
json_add_int "http_port" "$http_port"
|
|
json_add_string "http_host" "$http_host"
|
|
json_add_string "data_path" "$data_path"
|
|
json_add_string "memory_limit" "$memory_limit"
|
|
json_add_string "active_app" "$active_app"
|
|
json_close_object
|
|
|
|
json_add_object "server"
|
|
json_add_boolean "headless" "$( [ "$headless" = "true" ] && echo 1 || echo 0 )"
|
|
json_add_boolean "browser_gather_usage_stats" "$( [ "$gather_stats" = "true" ] && echo 1 || echo 0 )"
|
|
json_add_string "theme_base" "$theme_base"
|
|
json_add_string "theme_primary_color" "$theme_primary"
|
|
json_close_object
|
|
|
|
json_close_obj
|
|
}
|
|
|
|
# Save configuration
|
|
save_config() {
|
|
read -r input
|
|
|
|
local http_port http_host data_path memory_limit enabled active_app
|
|
local headless gather_stats theme_base theme_primary
|
|
|
|
http_port=$(echo "$input" | jsonfilter -e '@.http_port' 2>/dev/null)
|
|
http_host=$(echo "$input" | jsonfilter -e '@.http_host' 2>/dev/null)
|
|
data_path=$(echo "$input" | jsonfilter -e '@.data_path' 2>/dev/null)
|
|
memory_limit=$(echo "$input" | jsonfilter -e '@.memory_limit' 2>/dev/null)
|
|
enabled=$(echo "$input" | jsonfilter -e '@.enabled' 2>/dev/null)
|
|
active_app=$(echo "$input" | jsonfilter -e '@.active_app' 2>/dev/null)
|
|
headless=$(echo "$input" | jsonfilter -e '@.headless' 2>/dev/null)
|
|
gather_stats=$(echo "$input" | jsonfilter -e '@.browser_gather_usage_stats' 2>/dev/null)
|
|
theme_base=$(echo "$input" | jsonfilter -e '@.theme_base' 2>/dev/null)
|
|
theme_primary=$(echo "$input" | jsonfilter -e '@.theme_primary_color' 2>/dev/null)
|
|
|
|
[ -n "$http_port" ] && uci set "${CONFIG}.main.http_port=$http_port"
|
|
[ -n "$http_host" ] && uci set "${CONFIG}.main.http_host=$http_host"
|
|
[ -n "$data_path" ] && uci set "${CONFIG}.main.data_path=$data_path"
|
|
[ -n "$memory_limit" ] && uci set "${CONFIG}.main.memory_limit=$memory_limit"
|
|
[ -n "$enabled" ] && uci set "${CONFIG}.main.enabled=$enabled"
|
|
[ -n "$active_app" ] && uci set "${CONFIG}.main.active_app=$active_app"
|
|
[ -n "$headless" ] && uci set "${CONFIG}.server.headless=$headless"
|
|
[ -n "$gather_stats" ] && uci set "${CONFIG}.server.browser_gather_usage_stats=$gather_stats"
|
|
[ -n "$theme_base" ] && uci set "${CONFIG}.server.theme_base=$theme_base"
|
|
[ -n "$theme_primary" ] && uci set "${CONFIG}.server.theme_primary_color=$theme_primary"
|
|
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "Configuration saved"
|
|
}
|
|
|
|
# Start service
|
|
start_service() {
|
|
if lxc_running; then
|
|
json_error "Service is already running"
|
|
return
|
|
fi
|
|
|
|
if ! lxc_exists; then
|
|
json_error "Container not installed. Run install first."
|
|
return
|
|
fi
|
|
|
|
/etc/init.d/streamlit start >/dev/null 2>&1 &
|
|
|
|
sleep 2
|
|
if lxc_running; then
|
|
json_success "Service started"
|
|
else
|
|
json_error "Failed to start service"
|
|
fi
|
|
}
|
|
|
|
# Stop service
|
|
stop_service() {
|
|
if ! lxc_running; then
|
|
json_error "Service is not running"
|
|
return
|
|
fi
|
|
|
|
/etc/init.d/streamlit stop >/dev/null 2>&1
|
|
|
|
sleep 2
|
|
if ! lxc_running; then
|
|
json_success "Service stopped"
|
|
else
|
|
json_error "Failed to stop service"
|
|
fi
|
|
}
|
|
|
|
# Restart service
|
|
restart_service() {
|
|
/etc/init.d/streamlit restart >/dev/null 2>&1 &
|
|
|
|
sleep 3
|
|
if lxc_running; then
|
|
json_success "Service restarted"
|
|
else
|
|
json_error "Service restart failed"
|
|
fi
|
|
}
|
|
|
|
# Install Streamlit
|
|
install() {
|
|
if lxc_exists; then
|
|
json_error "Already installed. Use update to refresh."
|
|
return
|
|
fi
|
|
|
|
# Run install in background
|
|
/usr/sbin/streamlitctl install >/var/log/streamlit-install.log 2>&1 &
|
|
|
|
json_init_obj
|
|
json_add_boolean "started" 1
|
|
json_add_string "message" "Installation started in background"
|
|
json_add_string "log_file" "/var/log/streamlit-install.log"
|
|
json_close_obj
|
|
}
|
|
|
|
# Uninstall Streamlit
|
|
uninstall() {
|
|
/usr/sbin/streamlitctl uninstall >/dev/null 2>&1
|
|
|
|
if ! lxc_exists; then
|
|
json_success "Uninstalled successfully"
|
|
else
|
|
json_error "Uninstall failed"
|
|
fi
|
|
}
|
|
|
|
# Update Streamlit
|
|
update() {
|
|
if ! lxc_exists; then
|
|
json_error "Not installed. Run install first."
|
|
return
|
|
fi
|
|
|
|
# Run update in background
|
|
/usr/sbin/streamlitctl update >/var/log/streamlit-update.log 2>&1 &
|
|
|
|
json_init_obj
|
|
json_add_boolean "started" 1
|
|
json_add_string "message" "Update started in background"
|
|
json_add_string "log_file" "/var/log/streamlit-update.log"
|
|
json_close_obj
|
|
}
|
|
|
|
# Get logs
|
|
get_logs() {
|
|
read -r input
|
|
local lines
|
|
lines=$(echo "$input" | jsonfilter -e '@.lines' 2>/dev/null)
|
|
[ -z "$lines" ] && lines=100
|
|
|
|
local data_path
|
|
config_load "$CONFIG"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
|
|
json_init_obj
|
|
json_add_array "logs"
|
|
|
|
# Get container logs from data path
|
|
if [ -d "$data_path/logs" ]; then
|
|
local logfile
|
|
for logfile in "$data_path/logs"/*.log; do
|
|
[ -f "$logfile" ] || continue
|
|
tail -n "$lines" "$logfile" 2>/dev/null | while IFS= read -r line; do
|
|
json_add_string "" "$line"
|
|
done
|
|
done
|
|
fi
|
|
|
|
# Also check install/update logs
|
|
for logfile in /var/log/streamlit-install.log /var/log/streamlit-update.log; do
|
|
[ -f "$logfile" ] || continue
|
|
tail -n 50 "$logfile" 2>/dev/null | while IFS= read -r line; do
|
|
json_add_string "" "$line"
|
|
done
|
|
done
|
|
|
|
json_close_array
|
|
json_close_obj
|
|
}
|
|
|
|
# List apps
|
|
list_apps() {
|
|
local data_path active_app
|
|
config_load "$CONFIG"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
config_get active_app main active_app "hello"
|
|
|
|
APPS_PATH="$data_path/apps"
|
|
|
|
json_init_obj
|
|
json_add_array "apps"
|
|
|
|
if [ -d "$APPS_PATH" ]; then
|
|
for app in "$APPS_PATH"/*.py; do
|
|
[ -f "$app" ] || continue
|
|
local name=$(basename "$app" .py)
|
|
local size=$(ls -la "$app" 2>/dev/null | awk '{print $5}')
|
|
local mtime=$(stat -c %Y "$app" 2>/dev/null || echo "0")
|
|
|
|
local is_active=0
|
|
[ "$name" = "$active_app" ] && is_active=1
|
|
|
|
json_add_object ""
|
|
json_add_string "name" "$name"
|
|
json_add_string "path" "$app"
|
|
json_add_string "size" "$size"
|
|
json_add_int "mtime" "$mtime"
|
|
json_add_boolean "active" "$is_active"
|
|
json_close_object
|
|
done
|
|
fi
|
|
|
|
json_close_array
|
|
json_add_string "active_app" "$active_app"
|
|
json_add_string "apps_path" "$APPS_PATH"
|
|
json_close_obj
|
|
}
|
|
|
|
# Add app
|
|
add_app() {
|
|
read -r input
|
|
local name path
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
path=$(echo "$input" | jsonfilter -e '@.path' 2>/dev/null)
|
|
|
|
if [ -z "$name" ] || [ -z "$path" ]; then
|
|
json_error "Missing name or path"
|
|
return
|
|
fi
|
|
|
|
/usr/sbin/streamlitctl app add "$name" "$path" >/dev/null 2>&1
|
|
if [ $? -eq 0 ]; then
|
|
json_success "App added: $name"
|
|
else
|
|
json_error "Failed to add app"
|
|
fi
|
|
}
|
|
|
|
# Remove app
|
|
remove_app() {
|
|
read -r input
|
|
local name
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
|
|
if [ -z "$name" ]; then
|
|
json_error "Missing app name"
|
|
return
|
|
fi
|
|
|
|
/usr/sbin/streamlitctl app remove "$name" >/dev/null 2>&1
|
|
if [ $? -eq 0 ]; then
|
|
json_success "App removed: $name"
|
|
else
|
|
json_error "Failed to remove app"
|
|
fi
|
|
}
|
|
|
|
# Set active app
|
|
set_active_app() {
|
|
read -r input
|
|
local name
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
|
|
if [ -z "$name" ]; then
|
|
json_error "Missing app name"
|
|
return
|
|
fi
|
|
|
|
/usr/sbin/streamlitctl app run "$name" >/dev/null 2>&1
|
|
if [ $? -eq 0 ]; then
|
|
json_success "Active app set to: $name"
|
|
else
|
|
json_error "Failed to set active app"
|
|
fi
|
|
}
|
|
|
|
# Get app details
|
|
get_app() {
|
|
read -r input
|
|
local name
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
|
|
if [ -z "$name" ]; then
|
|
json_error "Missing app name"
|
|
return
|
|
fi
|
|
|
|
local data_path active_app
|
|
config_load "$CONFIG"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
config_get active_app main active_app "hello"
|
|
|
|
local app_file="$data_path/apps/${name}.py"
|
|
|
|
if [ ! -f "$app_file" ]; then
|
|
json_error "App not found"
|
|
return
|
|
fi
|
|
|
|
local size=$(ls -la "$app_file" 2>/dev/null | awk '{print $5}')
|
|
local mtime=$(stat -c %Y "$app_file" 2>/dev/null || echo "0")
|
|
local lines=$(wc -l < "$app_file" 2>/dev/null || echo "0")
|
|
|
|
local is_active=0
|
|
[ "$name" = "$active_app" ] && is_active=1
|
|
|
|
json_init_obj
|
|
json_add_string "name" "$name"
|
|
json_add_string "path" "$app_file"
|
|
json_add_string "size" "$size"
|
|
json_add_int "mtime" "$mtime"
|
|
json_add_int "lines" "$lines"
|
|
json_add_boolean "active" "$is_active"
|
|
json_close_obj
|
|
}
|
|
|
|
# Upload app (receive base64 content)
|
|
upload_app() {
|
|
read -r input
|
|
local name content
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
content=$(echo "$input" | jsonfilter -e '@.content' 2>/dev/null)
|
|
|
|
if [ -z "$name" ] || [ -z "$content" ]; then
|
|
json_error "Missing name or content"
|
|
return
|
|
fi
|
|
|
|
local data_path
|
|
config_load "$CONFIG"
|
|
config_get data_path main data_path "/srv/streamlit"
|
|
|
|
local app_file="$data_path/apps/${name}.py"
|
|
mkdir -p "$data_path/apps"
|
|
|
|
# Decode base64 and write
|
|
echo "$content" | base64 -d > "$app_file" 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
# Register in UCI
|
|
uci set "${CONFIG}.${name}=app"
|
|
uci set "${CONFIG}.${name}.name=$name"
|
|
uci set "${CONFIG}.${name}.path=${name}.py"
|
|
uci set "${CONFIG}.${name}.enabled=1"
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "App uploaded: $name"
|
|
else
|
|
json_error "Failed to decode app content"
|
|
fi
|
|
}
|
|
|
|
# List instances
|
|
list_instances() {
|
|
json_init_obj
|
|
json_add_array "instances"
|
|
|
|
config_load "$CONFIG"
|
|
|
|
_add_instance_json() {
|
|
local section="$1"
|
|
local name app port enabled autostart inst_name
|
|
|
|
config_get inst_name "$section" name ""
|
|
config_get app "$section" app ""
|
|
config_get port "$section" port ""
|
|
config_get enabled "$section" enabled "0"
|
|
config_get autostart "$section" autostart "0"
|
|
|
|
[ -z "$app" ] && return
|
|
|
|
json_add_object ""
|
|
json_add_string "id" "$section"
|
|
json_add_string "name" "$inst_name"
|
|
json_add_string "app" "$app"
|
|
json_add_int "port" "$port"
|
|
json_add_boolean "enabled" "$( [ "$enabled" = "1" ] && echo 1 || echo 0 )"
|
|
json_add_boolean "autostart" "$( [ "$autostart" = "1" ] && echo 1 || echo 0 )"
|
|
json_close_object
|
|
}
|
|
|
|
config_foreach _add_instance_json instance
|
|
|
|
json_close_array
|
|
json_close_obj
|
|
}
|
|
|
|
# Add instance
|
|
add_instance() {
|
|
read -r input
|
|
local id name app port
|
|
id=$(echo "$input" | jsonfilter -e '@.id' 2>/dev/null)
|
|
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
|
|
app=$(echo "$input" | jsonfilter -e '@.app' 2>/dev/null)
|
|
port=$(echo "$input" | jsonfilter -e '@.port' 2>/dev/null)
|
|
|
|
if [ -z "$id" ] || [ -z "$app" ] || [ -z "$port" ]; then
|
|
json_error "Missing id, app, or port"
|
|
return
|
|
fi
|
|
|
|
[ -z "$name" ] && name="$id"
|
|
|
|
# Validate port number
|
|
if ! echo "$port" | grep -qE '^[0-9]+$'; then
|
|
json_error "Invalid port number"
|
|
return
|
|
fi
|
|
|
|
# Check if instance already exists
|
|
local existing
|
|
existing=$(uci -q get "${CONFIG}.${id}")
|
|
if [ -n "$existing" ]; then
|
|
json_error "Instance $id already exists"
|
|
return
|
|
fi
|
|
|
|
uci set "${CONFIG}.${id}=instance"
|
|
uci set "${CONFIG}.${id}.name=$name"
|
|
uci set "${CONFIG}.${id}.app=$app"
|
|
uci set "${CONFIG}.${id}.port=$port"
|
|
uci set "${CONFIG}.${id}.enabled=1"
|
|
uci set "${CONFIG}.${id}.autostart=1"
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "Instance added: $id"
|
|
}
|
|
|
|
# Remove instance
|
|
remove_instance() {
|
|
read -r input
|
|
local id
|
|
id=$(echo "$input" | jsonfilter -e '@.id' 2>/dev/null)
|
|
|
|
if [ -z "$id" ]; then
|
|
json_error "Missing instance id"
|
|
return
|
|
fi
|
|
|
|
# Check if instance exists
|
|
local existing
|
|
existing=$(uci -q get "${CONFIG}.${id}")
|
|
if [ -z "$existing" ]; then
|
|
json_error "Instance $id not found"
|
|
return
|
|
fi
|
|
|
|
uci delete "${CONFIG}.${id}"
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "Instance removed: $id"
|
|
}
|
|
|
|
# Enable instance
|
|
enable_instance() {
|
|
read -r input
|
|
local id
|
|
id=$(echo "$input" | jsonfilter -e '@.id' 2>/dev/null)
|
|
|
|
if [ -z "$id" ]; then
|
|
json_error "Missing instance id"
|
|
return
|
|
fi
|
|
|
|
uci set "${CONFIG}.${id}.enabled=1"
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "Instance enabled: $id"
|
|
}
|
|
|
|
# Disable instance
|
|
disable_instance() {
|
|
read -r input
|
|
local id
|
|
id=$(echo "$input" | jsonfilter -e '@.id' 2>/dev/null)
|
|
|
|
if [ -z "$id" ]; then
|
|
json_error "Missing instance id"
|
|
return
|
|
fi
|
|
|
|
uci set "${CONFIG}.${id}.enabled=0"
|
|
uci commit "$CONFIG"
|
|
|
|
json_success "Instance disabled: $id"
|
|
}
|
|
|
|
# Check install progress
|
|
get_install_progress() {
|
|
local log_file="/var/log/streamlit-install.log"
|
|
local status="unknown"
|
|
local progress=0
|
|
local message=""
|
|
|
|
if [ -f "$log_file" ]; then
|
|
# Check for completion markers
|
|
if grep -q "Installation complete" "$log_file" 2>/dev/null; then
|
|
status="completed"
|
|
progress=100
|
|
message="Installation completed successfully"
|
|
elif grep -q "ERROR" "$log_file" 2>/dev/null; then
|
|
status="error"
|
|
message=$(grep "ERROR" "$log_file" | tail -1)
|
|
else
|
|
status="running"
|
|
# Estimate progress based on log content
|
|
if grep -q "Rootfs created" "$log_file" 2>/dev/null; then
|
|
progress=80
|
|
message="Setting up container..."
|
|
elif grep -q "Extracting rootfs" "$log_file" 2>/dev/null; then
|
|
progress=60
|
|
message="Extracting container rootfs..."
|
|
elif grep -q "Downloading Alpine" "$log_file" 2>/dev/null; then
|
|
progress=40
|
|
message="Downloading Alpine rootfs..."
|
|
elif grep -q "Installing Streamlit" "$log_file" 2>/dev/null; then
|
|
progress=20
|
|
message="Starting installation..."
|
|
else
|
|
progress=10
|
|
message="Initializing..."
|
|
fi
|
|
fi
|
|
else
|
|
status="not_started"
|
|
message="Installation has not been started"
|
|
fi
|
|
|
|
# Check if process is still running
|
|
if pgrep -f "streamlitctl install" >/dev/null 2>&1; then
|
|
status="running"
|
|
fi
|
|
|
|
json_init_obj
|
|
json_add_string "status" "$status"
|
|
json_add_int "progress" "$progress"
|
|
json_add_string "message" "$message"
|
|
json_close_obj
|
|
}
|
|
|
|
# Main RPC handler
|
|
case "$1" in
|
|
list)
|
|
cat <<-EOF
|
|
{
|
|
"get_status": {},
|
|
"get_config": {},
|
|
"save_config": {"http_port": 8501, "http_host": "str", "data_path": "str", "memory_limit": "str", "enabled": "str", "active_app": "str", "headless": "str", "browser_gather_usage_stats": "str", "theme_base": "str", "theme_primary_color": "str"},
|
|
"start": {},
|
|
"stop": {},
|
|
"restart": {},
|
|
"install": {},
|
|
"uninstall": {},
|
|
"update": {},
|
|
"get_logs": {"lines": 100},
|
|
"list_apps": {},
|
|
"get_app": {"name": "str"},
|
|
"add_app": {"name": "str", "path": "str"},
|
|
"remove_app": {"name": "str"},
|
|
"set_active_app": {"name": "str"},
|
|
"upload_app": {"name": "str", "content": "str"},
|
|
"get_install_progress": {},
|
|
"list_instances": {},
|
|
"add_instance": {"id": "str", "name": "str", "app": "str", "port": 8501},
|
|
"remove_instance": {"id": "str"},
|
|
"enable_instance": {"id": "str"},
|
|
"disable_instance": {"id": "str"}
|
|
}
|
|
EOF
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
get_status)
|
|
get_status
|
|
;;
|
|
get_config)
|
|
get_config
|
|
;;
|
|
save_config)
|
|
save_config
|
|
;;
|
|
start)
|
|
start_service
|
|
;;
|
|
stop)
|
|
stop_service
|
|
;;
|
|
restart)
|
|
restart_service
|
|
;;
|
|
install)
|
|
install
|
|
;;
|
|
uninstall)
|
|
uninstall
|
|
;;
|
|
update)
|
|
update
|
|
;;
|
|
get_logs)
|
|
get_logs
|
|
;;
|
|
list_apps)
|
|
list_apps
|
|
;;
|
|
get_app)
|
|
get_app
|
|
;;
|
|
add_app)
|
|
add_app
|
|
;;
|
|
remove_app)
|
|
remove_app
|
|
;;
|
|
set_active_app)
|
|
set_active_app
|
|
;;
|
|
upload_app)
|
|
upload_app
|
|
;;
|
|
get_install_progress)
|
|
get_install_progress
|
|
;;
|
|
list_instances)
|
|
list_instances
|
|
;;
|
|
add_instance)
|
|
add_instance
|
|
;;
|
|
remove_instance)
|
|
remove_instance
|
|
;;
|
|
enable_instance)
|
|
enable_instance
|
|
;;
|
|
disable_instance)
|
|
disable_instance
|
|
;;
|
|
*)
|
|
json_error "Unknown method: $2"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|