diff --git a/AGENTS.md b/AGENTS.md index 75fd143..c0e3787 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,6 +75,8 @@ make prole # PyInstaller one-file binary → dist/prole ### Interactive installer (ncurses) ```bash ./install.sh # reads conf/gke.cfg (or PROLE_CONF) +# or via the unified launcher: +./knoe.sh install ``` ### Unattended deploy diff --git a/Makefile b/Makefile index 011f8e5..ba523a1 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ help: @echo "Targets:" @echo " prole - Build the 'prole' CLI binary (ncurses/silent only)" @echo " requirements - Install Python dependencies" - @echo " install - Run silent install via prole.sh" + @echo " install - Run silent install via knoe.sh" @echo " init - Sync OpenTofu pipeline, tofu init, stage deployment git dir" @echo " deploy - Run infrastructure deployment via OpenTofu" @echo " test - Run full install.py test suite with pyconv and coverage summary" @@ -57,7 +57,7 @@ prole: install: @echo "Running silent install..." - PROLE_CONF=$(PROLE_CONF) ./prole.sh install -s -c $(PROLE_CONF)/prole.cfg + PROLE_CONF=$(PROLE_CONF) ./knoe.sh install -s -c $(PROLE_CONF)/prole.cfg init: @command -v tofu >/dev/null 2>&1 || (echo "Error: OpenTofu (tofu) not found in PATH." && exit 1) diff --git a/etc/init_min.sh b/etc/init_min.sh index 992fe0c..c2f5132 100644 --- a/etc/init_min.sh +++ b/etc/init_min.sh @@ -27,37 +27,18 @@ case "$ACTION" in fi fi - # Create start.sh and stop.sh in PROJECT_ROOT - log "Generating start.sh and stop.sh..." + # Create start.sh and stop.sh aliases to knoe.sh + log "Generating start.sh and stop.sh as wrappers to knoe.sh..." cat > "$PROJECT_ROOT/start.sh" < \$*"; } - -log "Starting knoe-db (containerd)..." -# nerdctl run -d --name knoe-db knoe-db:latest - -log "Starting knoe-auth (containerd)..." -# nerdctl run -d --name knoe-auth prole-authority:latest - -log "Minimal environment started." +exec "\$(dirname "\$0")/knoe.sh" --min start "\$@" EOF chmod +x "$PROJECT_ROOT/start.sh" cat > "$PROJECT_ROOT/stop.sh" < \$*"; } - -log "Stopping knoe-auth (containerd)..." -# nerdctl stop knoe-auth || true -# nerdctl rm knoe-auth || true - -log "Stopping knoe-db (containerd)..." -# nerdctl stop knoe-db || true -# nerdctl rm knoe-db || true - -log "Minimal environment stopped." +exec "\$(dirname "\$0")/knoe.sh" --min stop "\$@" EOF chmod +x "$PROJECT_ROOT/stop.sh" diff --git a/prole.sh b/knoe.sh similarity index 93% rename from prole.sh rename to knoe.sh index 03bb04f..a4302c8 100755 --- a/prole.sh +++ b/knoe.sh @@ -1,9 +1,10 @@ #!/usr/bin/env bash set -euo pipefail -# prole.sh - Unified launcher for Prole infrastructure and installer +# knoe.sh - Unified launcher for Knoe infrastructure and installer ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +KNOE_HOME="${KNOE_HOME:-$ROOT_DIR}" cd "${ROOT_DIR}" if [[ -z "${OPENBAO_ROOT_TOKEN:-}" ]]; then @@ -22,9 +23,9 @@ RESET=0 EXTRA_ARGS=() # Canonical wrapper aliases: -# ./prole.sh --reset => full silent reset run -# ./prole.sh --update => silent update run -# ./prole.sh --perfsnap => topology/storage snapshot +# ./knoe.sh --reset => full silent reset run +# ./knoe.sh --update => silent update run +# ./knoe.sh --perfsnap => topology/storage snapshot if [[ $# -gt 0 ]]; then case "$1" in --reset) @@ -43,13 +44,14 @@ usage() { echo "Usage: $0 [options] [command] [command-options]" echo echo "Options:" - echo " -l, --log Create a datestamped logfile in prole/logs including all stdout/stderr" + echo " -l, --log Create a datestamped logfile in logs including all stdout/stderr" echo " -v, --verbose Pass a verbose switch to all functions called by ansible and install.sh" - echo " -d, --debug Enable a debug logfile in prole/logs with high verbosity from install.sh" - echo " -c, --config Path to config file (default: conf/{k3d|k3s|gke}.cfg)" + echo " -d, --debug Enable a debug logfile in logs with high verbosity from install.sh" + echo " -c, --config Path to config file (default: conf/{k3d|k3s|gke|min}.cfg)" echo " --coverage Create a coverage report for the run of install.sh" echo " -s, --silent Run unattended install (passes -S to install.sh)" - echo " -r, --reset Perform a reset before action (site/deploy/install); for canonical full reset run use './prole.sh --reset'" + echo " -r, --reset Perform a reset before action (site/deploy/install); for canonical full reset run use './knoe.sh --reset'" + echo " --min Use minimal containerd mode" echo echo "Commands:" echo " init Run/re-run initialization scripts to verify, repair, and renew the deployment" @@ -61,8 +63,9 @@ usage() { echo " update Canonical silent update run (installer --update)" echo " perfsnap Save topology/storage performance snapshot (includes storage_probe)" echo " deploy Full end-to-end: site run, and silent install (reset optional)" - echo " start Verify/clean environment, ensure cluster availability, run silent install" - echo " stop Validate environment, run full backup+archive, stop services (keep cluster idle)" + echo " start Launch services (containerd in min mode, or cluster in k3d/k3s/k8s)" + echo " stop Stop services" + echo " restart Restart services (min mode only)" echo " backup Run a database backup (-f/full for full, default incremental)" echo " passwd Change the Prole master password and propagate secrets" echo " status Show deployment health status (use -v for verbose)" @@ -71,6 +74,7 @@ usage() { } # Parse global options +MIN_MODE=0 while [[ $# -gt 0 ]]; do case "$1" in -l|--log|--logs) LOG=1; shift ;; @@ -80,8 +84,9 @@ while [[ $# -gt 0 ]]; do --coverage) COVERAGE=1; shift ;; -s|--silent) SILENT=1; shift ;; -r|--reset) RESET=1; shift ;; + --min) MIN_MODE=1; EXTRA_ARGS+=("--min"); shift ;; -h|--help) usage; exit 0 ;; - install|ansible|site|reset|reset-run|update|perfsnap|deploy|init|start|stop|backup|passwd|status) break ;; + install|ansible|site|reset|reset-run|update|perfsnap|deploy|init|start|stop|restart|backup|passwd|status) break ;; *) EXTRA_ARGS+=("$1"); shift ;; esac done @@ -121,12 +126,13 @@ default_cfg_path() { mode="${mode_hint,,}" case "$mode" in + min) [[ -f "$conf_dir/min.cfg" ]] && { printf '%s' "$conf_dir/min.cfg"; return 0; } ;; k3d) [[ -f "$conf_dir/k3d.cfg" ]] && { printf '%s' "$conf_dir/k3d.cfg"; return 0; } ;; k3s|service|services) [[ -f "$conf_dir/k3s.cfg" ]] && { printf '%s' "$conf_dir/k3s.cfg"; return 0; } ;; k8s|gke|prod|production) [[ -f "$conf_dir/gke.cfg" ]] && { printf '%s' "$conf_dir/gke.cfg"; return 0; } ;; esac - for cfg in k3d.cfg k3s.cfg gke.cfg prole.cfg; do + for cfg in min.cfg k3d.cfg k3s.cfg gke.cfg prole.cfg; do if [[ -f "$conf_dir/$cfg" ]]; then printf '%s' "$conf_dir/$cfg" return 0 @@ -598,7 +604,7 @@ case "${CMD}" in if [[ "${COVERAGE}" -eq 1 ]]; then _reset_args=("--coverage" "${_reset_args[@]}") fi - exec "${ROOT_DIR}/prole.sh" "${_reset_args[@]}" + exec "${ROOT_DIR}/knoe.sh" "${_reset_args[@]}" ;; update) CONFIG_PATH="$(resolve_cfg_path)" @@ -606,7 +612,7 @@ case "${CMD}" in if [[ "${COVERAGE}" -eq 1 ]]; then _update_args=("--coverage" "${_update_args[@]}") fi - exec "${ROOT_DIR}/prole.sh" "${_update_args[@]}" + exec "${ROOT_DIR}/knoe.sh" "${_update_args[@]}" ;; perfsnap) CONFIG_PATH="$(resolve_cfg_path)" @@ -903,10 +909,43 @@ PY ;; start) if [[ ! -f "${PROLE_CFG_DEFAULT}" ]]; then - err_msg "Missing ${PROLE_CFG_DEFAULT}" - exit 1 + # If no config, but we are in min mode, we can try to proceed if we just want to start containers + if [[ "${MIN_MODE}" -ne 1 ]]; then + err_msg "Missing ${PROLE_CFG_DEFAULT}" + exit 1 + fi + else + load_prole_cfg "${PROLE_CFG_DEFAULT}" fi - load_prole_cfg "${PROLE_CFG_DEFAULT}" + + local_mode=$(resolve_prole_mode) + if [[ "${MIN_MODE}" -eq 1 ]]; then + local_mode="min" + fi + if [[ -z "${local_mode:-}" ]]; then + local_mode="k3d" + fi + + if [[ "$local_mode" == "min" ]]; then + log_msg "Starting knoe-db and authority (containerd)..." + mkdir -p "${KNOE_HOME}/logs" + + # Start knoe-db + log_msg "Launching knoe-db..." + nohup nerdctl run --rm --name knoe-db -p 5432:5432 knoe-db:latest > "${KNOE_HOME}/logs/knoe-db.log" 2>&1 & + + # Start authority (which connects to knoedb) + log_msg "Launching authority..." + # In min mode, we assume knoe-db is available on localhost:5432 + nohup nerdctl run --rm --name authority -p 8080:8080 \ + -e DB_HOST=host.nerdctl.internal \ + -e DB_PORT=5432 \ + prole-authority:latest > "${KNOE_HOME}/logs/authority.log" 2>&1 & + + log_msg "Minimal environment started. Logs at ${KNOE_HOME}/logs" + exit 0 + fi + stop_port_forwards local_mode=$(resolve_prole_mode) @@ -972,11 +1011,32 @@ PY fi ;; stop) + if [[ -f "${PROLE_CFG_DEFAULT}" ]]; then + load_prole_cfg "${PROLE_CFG_DEFAULT}" + fi + + local_mode=$(resolve_prole_mode) + if [[ "${MIN_MODE}" -eq 1 ]]; then + local_mode="min" + fi + if [[ -z "${local_mode:-}" ]]; then + local_mode="k3d" + fi + + if [[ "$local_mode" == "min" ]]; then + log_msg "Stopping containerd pods..." + nerdctl stop authority || true + nerdctl rm authority || true + nerdctl stop knoe-db || true + nerdctl rm knoe-db || true + log_msg "Minimal environment stopped." + exit 0 + fi + if [[ ! -f "${PROLE_CFG_DEFAULT}" ]]; then err_msg "Missing ${PROLE_CFG_DEFAULT}" exit 1 fi - load_prole_cfg "${PROLE_CFG_DEFAULT}" local_mode=$(resolve_prole_mode) if [[ -z "${local_mode:-}" ]]; then @@ -1060,6 +1120,10 @@ PY fi fi ;; + restart) + "${ROOT_DIR}/knoe.sh" stop "$@" + "${ROOT_DIR}/knoe.sh" start "$@" + ;; backup) if [[ ! -f "${PROLE_CFG_DEFAULT}" ]]; then err_msg "Missing ${PROLE_CFG_DEFAULT}" diff --git a/status.py b/status.py index baed47d..0629507 100755 --- a/status.py +++ b/status.py @@ -138,15 +138,15 @@ def _build_milestones( """Return an ordered list of (display_name, command) milestones. Navigation order: - 1. ``./prole.sh status`` + 1. ``./knoe.sh status`` 2. Kubernetes pod overview (``kubecolor get pods -o wide -A``) 3. ``cnpg status knoe-db`` 4. One entry per active service init script (same list as status.sh) """ milestones: list[tuple[str, list[str]]] = [] - prole_sh = PROJECT_ROOT / "prole.sh" + prole_sh = PROJECT_ROOT / "knoe.sh" - # 1. Overall prole.sh status + # 1. Overall knoe.sh status milestones.append( ( "Prole Status",