From 755f60267fb82acdf6e8d86e9b05f49fbef8035b Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Mon, 29 Jun 2026 12:55:19 -0600 Subject: [PATCH] Add homelab tofu plan mode --- jeannie | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/jeannie b/jeannie index 777eb91..2dd01f3 100755 --- a/jeannie +++ b/jeannie @@ -430,7 +430,15 @@ delete_prometheus_stack_storage() { run_tofu_stack() { local stack="$1" - local -a apply_args=(-auto-approve) + local auto_approve="${LAB_AUTO_APPROVE:-true}" + local -a apply_args=() + + if truthy "${auto_approve}"; then + apply_args+=("-auto-approve") + elif ! disabled_value "${auto_approve}"; then + echo "LAB_AUTO_APPROVE must be true or false." >&2 + exit 1 + fi if [[ "${stack}" == "bootstrap/cluster" && -n "${LAB_CLUSTER_VAR_FILE:-}" ]]; then apply_args+=("-var-file=${LAB_CLUSTER_VAR_FILE}") @@ -446,6 +454,18 @@ run_tofu_stack() { tofu -chdir="${REPO_ROOT}/${stack}" apply "${apply_args[@]}" } +run_tofu_plan_stack() { + local stack="$1" + local -a plan_args=() + + if [[ "${stack}" == "bootstrap/cluster" && -n "${LAB_CLUSTER_VAR_FILE:-}" ]]; then + plan_args+=("-var-file=${LAB_CLUSTER_VAR_FILE}") + fi + + tofu -chdir="${REPO_ROOT}/${stack}" init + tofu -chdir="${REPO_ROOT}/${stack}" plan "${plan_args[@]}" +} + move_prometheus_stack_workers() { local stack="bootstrap/platform" local namespace="${LAB_MONITORING_NAMESPACE:-monitoring}" @@ -3839,6 +3859,63 @@ up() { echo "Deployment successfully completed." } +tofu_stack_from_plan_target() { + case "$1" in + provisioning) + printf 'bootstrap/provisioning\n' + ;; + cluster) + printf 'bootstrap/cluster\n' + ;; + platform) + printf 'bootstrap/platform\n' + ;; + apps) + printf 'bootstrap/apps\n' + ;; + edge) + printf 'bootstrap/edge\n' + ;; + *) + echo "Unknown plan target '$1'. Use all, provisioning, cluster, platform, apps, or edge." >&2 + return 1 + ;; + esac +} + +plan_homelab() { + local target="${1:-all}" + local stack + local -a stacks=() + + require_debian_server "plan" + + if [[ "${target}" == "all" ]]; then + if [[ -z "${LAB_CLUSTER_VAR_FILE:-}" ]]; then + prepare_cluster_worker_var_file true + fi + stacks=( + "bootstrap/provisioning" + "bootstrap/cluster" + "bootstrap/platform" + "bootstrap/apps" + "bootstrap/edge" + ) + else + stack="$(tofu_stack_from_plan_target "${target}")" + if [[ "${stack}" == "bootstrap/cluster" && -z "${LAB_CLUSTER_VAR_FILE:-}" ]]; then + prepare_cluster_worker_var_file true + fi + stacks=("${stack}") + fi + + for stack in "${stacks[@]}"; do + echo + echo "Planning ${stack}..." + run_tofu_plan_stack "${stack}" + done +} + rebuild_cluster() { require_debian_server "rebuild-cluster" @@ -5047,6 +5124,9 @@ case "${1:-}" in up) up ;; + plan) + plan_homelab "${2:-all}" + ;; rebuild-cluster) rebuild_cluster ;; @@ -5135,7 +5215,7 @@ case "${1:-}" in nuke ;; *) - echo "Usage: $0 {up|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|ollama-setup|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|fix-debian-docker-root|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|openwrt|nuke}" + echo "Usage: $0 {up|plan [all|provisioning|cluster|platform|apps|edge]|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|ollama-setup|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|fix-debian-docker-root|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|openwrt|nuke}" exit 1 ;; esac