Auto-load env file for PROXMOX_TOKEN_SECRET on startup

Scripts now search for an 'env' file up the directory tree from the
script location and source it automatically. No manual 'source env'
needed. Falls back gracefully -- if no env file exists and the secret
isn't exported, require_api_auth() catches it with a clear error.

Also fix unbound variable in --labs when pool has no VMs (declare -A
needs explicit =() initialization under set -u).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maarten 2026-02-21 08:56:28 +01:00
parent e0faba8980
commit 00f57746ff
2 changed files with 61 additions and 9 deletions

View File

@ -90,7 +90,10 @@ incu-contrib/
`proxmox:` overlay → CLI flags (`--host`, `--method`). Auto-discovery looks
for `proxmox.yaml` in script directory then cwd; override with `--proxmox FILE`.
- **API token secret**: stored in `env` file at the repo root (gitignored).
Source it before running scripts: `source env` (exports `PROXMOX_TOKEN_SECRET`).
Scripts auto-load it on startup by searching for `env` up the directory
tree from the script location. No manual `source env` needed. If the file
is missing and `PROXMOX_TOKEN_SECRET` is not exported, API commands fail
with a clear error message.
- **Connection methods**: SSH (default, `ssh root@host qm ...`) or API
(`curl -k https://host:8006/api2/json/...` with `PVEAPIToken` header).
- **Minimum API privileges** for token-based access (role: `IncusOSDeployer`):

View File

@ -19,6 +19,55 @@ readonly MIN_DISK_GIB=50
readonly MIN_MEMORY_MIB=4096
readonly MANAGED_MARKER="[incusos-lab:managed]"
# ---------------------------------------------------------------------------
# Auto-load env file (secrets like PROXMOX_TOKEN_SECRET)
# ---------------------------------------------------------------------------
# Searches for an 'env' file: first next to the script, then walking up from
# the current directory. Sources it if found and not already loaded. This is
# a convenience -- users can still export variables manually or source the
# file themselves.
load_env_file() {
# Skip if the secret is already set (user exported it, or env already sourced)
if [[ -n "${PROXMOX_TOKEN_SECRET:-}" ]]; then
return 0
fi
local script_real
script_real=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# Check: script directory's parent (repo root when script is in incusos/)
if [[ -f "${script_real}/../env" ]]; then
# shellcheck source=/dev/null
source "${script_real}/../env"
return 0
fi
# Check: script directory itself
if [[ -f "${script_real}/env" ]]; then
# shellcheck source=/dev/null
source "${script_real}/env"
return 0
fi
# Walk up from cwd
local dir="$PWD"
while [[ "$dir" != "/" ]]; do
if [[ -f "${dir}/env" ]]; then
# shellcheck source=/dev/null
source "${dir}/env"
return 0
fi
dir=$(dirname "$dir")
done
# No env file found -- not an error; require_api_auth() will catch
# missing secrets later if API method is used.
return 0
}
load_env_file
# ---------------------------------------------------------------------------
# Color and formatting
# ---------------------------------------------------------------------------
@ -1438,8 +1487,8 @@ validate_config() {
errors=$((errors + 1))
fi
if [[ -z "${PROXMOX_TOKEN_SECRET:-}" ]]; then
error "PROXMOX_TOKEN_SECRET environment variable is required for API method"
error "Set it with: export PROXMOX_TOKEN_SECRET=\"<your-token-secret>\""
error "PROXMOX_TOKEN_SECRET is not set (no env file found in repo tree)"
error "Create an env file or export directly (see --help)"
errors=$((errors + 1))
fi
fi
@ -1589,9 +1638,9 @@ require_api_auth() {
exit 1
fi
if [[ -z "${PROXMOX_TOKEN_SECRET:-}" ]]; then
error "PROXMOX_TOKEN_SECRET environment variable is not set"
error "Source your env file: source env"
error "Or set it directly: export PROXMOX_TOKEN_SECRET=\"<your-token-secret>\""
error "PROXMOX_TOKEN_SECRET is not set (no env file found in repo tree)"
error "Create an env file: echo 'export PROXMOX_TOKEN_SECRET=\"<secret>\"' > env"
error "Or export directly: export PROXMOX_TOKEN_SECRET=\"<your-token-secret>\""
exit 1
fi
# Verify we can actually reach the API with these credentials
@ -3540,9 +3589,9 @@ for v in data:
fi
# For each VM, get config and check for managed marker
declare -A lab_configs # config_name -> "vmid1:name1:status1 vmid2:name2:status2 ..."
declare -A lab_ram # config_name -> total RAM in MiB
declare -A lab_disk # config_name -> total disk in GiB
declare -A lab_configs=() # config_name -> "vmid1:name1:status1 vmid2:name2:status2 ..."
declare -A lab_ram=() # config_name -> total RAM in MiB
declare -A lab_disk=() # config_name -> total disk in GiB
local unmanaged=0
for vmid in "${vmids[@]}"; do