warpgate/tests/harness/config-gen.sh
grabbit 6bb7ec4d27 Web UI overhaul: interactive config editor, SSE live updates, log viewer, and SMB reload fixes
- Replace raw TOML textarea with Alpine.js interactive form editor (10 collapsible
  sections with change-tier badges, dynamic array management for connections/shares/
  warmup rules, proper input controls per field type)
- Add SSE-based live dashboard updates replacing htmx polling
- Add log viewer tab with ring buffer backend and incremental polling
- Fix SMB not seeing new shares after config reload: kill entire smbd process group
  (not just parent PID) so forked workers release port 445
- Add SIGHUP-based smbd config reload for share changes instead of full restart,
  preserving existing client connections
- Generate human-readable commented TOML from config editor instead of bare
  toml::to_string_pretty() output
- Fix Alpine.js 2.x __x.$data calls in dashboard/share templates (now Alpine 3.x)
- Fix toggle switch CSS overlap with field labels
- Fix dashboard going blank on tab switch (remove hx-swap-oob from tab content)
- Add htmx:afterSettle → Alpine.initTree() bridge for robust tab switching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:06:52 +08:00

253 lines
7.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Warpgate Integration Test — Config Generator
#
# Generates a config.toml pointing at the mock NAS for testing.
# Supports override parameters as key=value arguments.
#
# Usage:
# source config-gen.sh
# _gen_config # defaults
# _gen_config cache.max_size=10M # override one field
# _gen_config writeback.write_back=0s # instant write-back
set -euo pipefail
_gen_config() {
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
# Defaults pointing at mock NAS
local conn_name="${TEST_CONN_NAME:-nas}"
local nas_host="${MOCK_NAS_IP:-10.99.0.2}"
local nas_user="root"
local nas_key_file="${TEST_SSH_KEY:-$TEST_DIR/test_key}"
local sftp_port="22"
local sftp_connections="4"
local cache_dir="${CACHE_DIR:-$TEST_DIR/cache}"
local cache_max_size="200G"
local cache_max_age="720h"
local cache_min_free="1G"
local read_chunk_size="16M"
local read_chunk_limit="64M"
local read_ahead="32M"
local buffer_size="16M"
local bw_limit_up="0"
local bw_limit_down="0"
local bw_adaptive="true"
local write_back="5s"
local transfers="4"
local dir_cache_time="5s"
local enable_smb="true"
local enable_nfs="false"
local enable_webdav="false"
local nfs_allowed_network="10.99.0.0/24"
local webdav_port="8080"
local warmup_auto="false"
local warmup_rules=""
local smb_auth_enabled="false"
local smb_auth_username=""
local smb_auth_smb_pass=""
# Default share: single share at /
local share_name="${TEST_SHARE_NAME:-data}"
local share_remote_path="${TEST_SHARE_REMOTE_PATH:-/}"
local share_mount_point="${TEST_MOUNT:-$TEST_DIR/mnt}"
local shares_config=""
# Apply overrides
for override in "$@"; do
local key="${override%%=*}"
local value="${override#*=}"
case "$key" in
connection.name|conn_name) conn_name="$value" ;;
connection.nas_host|nas_host) nas_host="$value" ;;
connection.nas_user|nas_user) nas_user="$value" ;;
connection.nas_key_file|nas_key_file) nas_key_file="$value" ;;
connection.sftp_port|sftp_port) sftp_port="$value" ;;
connection.sftp_connections|sftp_connections) sftp_connections="$value" ;;
cache.dir|cache_dir) cache_dir="$value" ;;
cache.max_size|cache_max_size) cache_max_size="$value" ;;
cache.max_age|cache_max_age) cache_max_age="$value" ;;
cache.min_free|cache_min_free) cache_min_free="$value" ;;
read.chunk_size|read_chunk_size) read_chunk_size="$value" ;;
read.chunk_limit|read_chunk_limit) read_chunk_limit="$value" ;;
read.read_ahead|read_ahead) read_ahead="$value" ;;
read.buffer_size|buffer_size) buffer_size="$value" ;;
bandwidth.limit_up|bw_limit_up) bw_limit_up="$value" ;;
bandwidth.limit_down|bw_limit_down) bw_limit_down="$value" ;;
bandwidth.adaptive|bw_adaptive) bw_adaptive="$value" ;;
writeback.write_back|write_back) write_back="$value" ;;
writeback.transfers|transfers) transfers="$value" ;;
directory_cache.cache_time|dir_cache_time) dir_cache_time="$value" ;;
protocols.enable_smb|enable_smb) enable_smb="$value" ;;
protocols.enable_nfs|enable_nfs) enable_nfs="$value" ;;
protocols.enable_webdav|enable_webdav) enable_webdav="$value" ;;
protocols.nfs_allowed_network|nfs_allowed_network) nfs_allowed_network="$value" ;;
protocols.webdav_port|webdav_port) webdav_port="$value" ;;
warmup.auto|warmup_auto) warmup_auto="$value" ;;
warmup.rules) warmup_rules="$value" ;;
smb_auth.enabled|smb_auth_enabled) smb_auth_enabled="$value" ;;
smb_auth.username|smb_auth_username) smb_auth_username="$value" ;;
smb_auth.smb_pass|smb_auth_smb_pass) smb_auth_smb_pass="$value" ;;
share.name|share_name) share_name="$value" ;;
share.remote_path|share_remote_path) share_remote_path="$value" ;;
share.mount_point|share_mount_point) share_mount_point="$value" ;;
shares) shares_config="$value" ;;
*) echo "WARNING: unknown config override: $key" >&2 ;;
esac
done
cat > "$config_file" <<CONFIG_EOF
[[connections]]
name = "$conn_name"
nas_host = "$nas_host"
nas_user = "$nas_user"
nas_key_file = "$nas_key_file"
sftp_port = $sftp_port
sftp_connections = $sftp_connections
[cache]
dir = "$cache_dir"
max_size = "$cache_max_size"
max_age = "$cache_max_age"
min_free = "$cache_min_free"
[read]
chunk_size = "$read_chunk_size"
chunk_limit = "$read_chunk_limit"
read_ahead = "$read_ahead"
buffer_size = "$buffer_size"
[bandwidth]
limit_up = "$bw_limit_up"
limit_down = "$bw_limit_down"
adaptive = $bw_adaptive
[writeback]
write_back = "$write_back"
transfers = $transfers
[directory_cache]
cache_time = "$dir_cache_time"
[protocols]
enable_smb = $enable_smb
enable_nfs = $enable_nfs
enable_webdav = $enable_webdav
nfs_allowed_network = "$nfs_allowed_network"
webdav_port = $webdav_port
[warmup]
auto = $warmup_auto
CONFIG_EOF
# Append smb_auth section if enabled
if [[ "$smb_auth_enabled" == "true" ]]; then
cat >> "$config_file" <<SMB_AUTH_EOF
[smb_auth]
enabled = true
SMB_AUTH_EOF
if [[ -n "$smb_auth_username" ]]; then
echo "username = \"$smb_auth_username\"" >> "$config_file"
fi
if [[ -n "$smb_auth_smb_pass" ]]; then
echo "smb_pass = \"$smb_auth_smb_pass\"" >> "$config_file"
fi
fi
# Append shares config — use override or default single share
if [[ -n "$shares_config" ]]; then
echo "" >> "$config_file"
echo "$shares_config" >> "$config_file"
else
cat >> "$config_file" <<SHARES_EOF
[[shares]]
name = "$share_name"
connection = "$conn_name"
remote_path = "$share_remote_path"
mount_point = "$share_mount_point"
SHARES_EOF
fi
# Append warmup rules if specified
if [[ -n "$warmup_rules" ]]; then
echo "" >> "$config_file"
echo "$warmup_rules" >> "$config_file"
fi
export TEST_CONFIG="$config_file"
}
# Generate a minimal config (only required fields)
_gen_minimal_config() {
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
local conn_name="${TEST_CONN_NAME:-nas}"
cat > "$config_file" <<CONFIG_EOF
[[connections]]
name = "$conn_name"
nas_host = "${MOCK_NAS_IP:-10.99.0.2}"
nas_user = "root"
nas_key_file = "${TEST_SSH_KEY:-$TEST_DIR/test_key}"
[cache]
dir = "${CACHE_DIR:-$TEST_DIR/cache}"
[[shares]]
name = "data"
connection = "$conn_name"
remote_path = "/"
mount_point = "${TEST_MOUNT:-$TEST_DIR/mnt}"
CONFIG_EOF
export TEST_CONFIG="$config_file"
}
# Generate an intentionally broken config
_gen_broken_config() {
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
local type="${1:-missing_field}"
case "$type" in
missing_field)
# Missing nas_host
cat > "$config_file" <<CONFIG_EOF
[[connections]]
name = "nas"
nas_user = "root"
[cache]
dir = "/tmp/cache"
[[shares]]
name = "data"
connection = "nas"
remote_path = "/"
mount_point = "/tmp/mnt"
CONFIG_EOF
;;
bad_toml)
cat > "$config_file" <<CONFIG_EOF
[[connections
name = "broken toml
CONFIG_EOF
;;
*)
echo "Unknown broken config type: $type" >&2
return 1
;;
esac
export TEST_CONFIG="$config_file"
}