Fix jeannie helper sourcing and validation
This commit is contained in:
parent
d004ad05fa
commit
4405c76003
30
jeannie
30
jeannie
|
|
@ -2,11 +2,39 @@
|
|||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BUILDX_CONFIG="/tmp/buildx-config.toml"
|
||||
HOMELAB_STATE_DIR="${HOMELAB_STATE_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/homelab}"
|
||||
COSIGN_KEY_PREFIX="${COSIGN_KEY_PREFIX:-${HOMELAB_STATE_DIR}/cosign/cosign}"
|
||||
COSIGN_KEY_PATH="${COSIGN_KEY_PATH:-${COSIGN_KEY_PREFIX}.key}"
|
||||
COSIGN_PUBLIC_KEY_PATH="${COSIGN_PUBLIC_KEY_PATH:-${COSIGN_KEY_PREFIX}.pub}"
|
||||
COSIGN_PASSWORD_FILE="${COSIGN_PASSWORD_FILE:-${HOMELAB_STATE_DIR}/cosign/cosign.password}"
|
||||
COSIGN_VERSION="${COSIGN_VERSION:-2.6.3}"
|
||||
COSIGN_BIN="${COSIGN_BIN:-}"
|
||||
HOMELAB_COSIGN_PUBLIC_KEY_CONFIGMAP="${HOMELAB_COSIGN_PUBLIC_KEY_CONFIGMAP:-homelab-cosign-public-key}"
|
||||
HOMELAB_SBOM_PREDICATE_TYPE="${HOMELAB_SBOM_PREDICATE_TYPE:-https://spdx.dev/Document}"
|
||||
JEANNIE_LOG_DIR="${JEANNIE_LOG_DIR:-${HOMELAB_STATE_DIR}/logs}"
|
||||
JEANNIE_LOG_FILE="${JEANNIE_LOG_FILE:-}"
|
||||
JEANNIE_ERROR_LOG_FILE="${JEANNIE_ERROR_LOG_FILE:-}"
|
||||
JEANNIE_STEP_INDEX=0
|
||||
JEANNIE_STEP_TOTAL=0
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${REPO_ROOT}/scripts/report-ui"
|
||||
source "${REPO_ROOT}/lib/jeannie/core.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/env.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/toolchain.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/pimox.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/preflight.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/pipeline.sh"
|
||||
source "${REPO_ROOT}/lib/jeannie/security.sh"
|
||||
# shellcheck disable=SC1091
|
||||
source "${REPO_ROOT}/lib/jeannie/commands.sh"
|
||||
|
||||
trap 'rm -f "${BUILDX_CONFIG}"' EXIT
|
||||
|
||||
load_homelab_inventory_defaults
|
||||
export_homelab_inventory_tf_vars
|
||||
KUBECONFIG_PATH="${KUBECONFIG_PATH:-${TF_VAR_kubeconfig_path:-${LAB_KUBECONFIG_PATH:-/home/jv/.kube/config}}}"
|
||||
|
||||
print_usage() {
|
||||
cat <<'EOF'
|
||||
|
|
@ -368,7 +396,7 @@ case "${1:-}" in
|
|||
doctor_cluster "${@:2}"
|
||||
;;
|
||||
preflight)
|
||||
homelab_preflight \"full\"
|
||||
homelab_preflight "full"
|
||||
;;
|
||||
doctor-preapply)
|
||||
doctor_preapply
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2140
|
||||
|
||||
pimox_ssh() {
|
||||
local host="$1"
|
||||
|
|
@ -493,7 +494,7 @@ cluster_control_plane_tracked() {
|
|||
}
|
||||
|
||||
cluster_admin_kubeconfig_present() {
|
||||
[[ -s "${KUBECONFIG_PATH_PATH}" ]] ||
|
||||
[[ -s "${KUBECONFIG_PATH}" ]] ||
|
||||
sudo test -s /etc/kubernetes/admin.conf 2>/dev/null ||
|
||||
[[ -n "${KUBECONFIG_PATH:-}" && -s "${KUBECONFIG_PATH}" ]]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2043,SC2140
|
||||
|
||||
load_homelab_inventory_defaults() {
|
||||
local inventory_file="${HOMELAB_INVENTORY_FILE:-${REPO_ROOT}/homelab.yml}"
|
||||
|
|
@ -26,7 +27,7 @@ mapping = {
|
|||
"hosts.debian.lan_ip": "LAB_DEBIAN_LAN_IP",
|
||||
"hosts.debian.tailscale_ip": "LAB_DEBIAN_TAILSCALE_IP",
|
||||
"hosts.debian.docker_root": "LAB_DEBIAN_DOCKER_ROOT",
|
||||
"hosts.debian.kubeconfig": "LAB_KUBECONFIG_PATH_PATH",
|
||||
"hosts.debian.kubeconfig": "LAB_KUBECONFIG_PATH",
|
||||
"hosts.rpi4.user": "LAB_RPI_USER",
|
||||
"hosts.rpi4.lan_ip": "LAB_RPI_HOST",
|
||||
"hosts.rpi4.tailscale_ip": "LAB_RPI_TAILSCALE_IP",
|
||||
|
|
@ -157,7 +158,7 @@ export_if_unset() {
|
|||
}
|
||||
|
||||
export_homelab_inventory_tf_vars() {
|
||||
export_if_unset TF_VAR_kubeconfig_path "${LAB_KUBECONFIG_PATH_PATH:-}"
|
||||
export_if_unset TF_VAR_kubeconfig_path "${LAB_KUBECONFIG_PATH:-}"
|
||||
export_if_unset TF_VAR_control_plane_endpoint "${LAB_DEBIAN_LAN_IP:-}"
|
||||
export_if_unset TF_VAR_registry_endpoint "${LAB_REGISTRY_ENDPOINT:-}"
|
||||
export_if_unset TF_VAR_provisioning_host "${LAB_DEBIAN_LAN_IP:-}"
|
||||
|
|
@ -216,7 +217,7 @@ helm_release_secret_exists() {
|
|||
local release_name="$2"
|
||||
local secret_name
|
||||
|
||||
secret_name="$(kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" -n "${namespace}" get secrets \
|
||||
secret_name="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get secrets \
|
||||
-l "owner=helm,name=${release_name}" \
|
||||
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)"
|
||||
|
||||
|
|
@ -229,11 +230,11 @@ kubernetes_resource_exists() {
|
|||
local resource_name="$3"
|
||||
|
||||
if [[ -n "${namespace}" ]]; then
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" -n "${namespace}" get "${resource_kind}" "${resource_name}" >/dev/null 2>&1
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get "${resource_kind}" "${resource_name}" >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get "${resource_kind}" "${resource_name}" >/dev/null 2>&1
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" get "${resource_kind}" "${resource_name}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
adopt_tofu_helm_release() {
|
||||
|
|
@ -405,7 +406,7 @@ ensure_homelab_node_labels() {
|
|||
[[ -n "${node}" ]] || continue
|
||||
|
||||
if [[ "${node}" == "${control_plane_node}" ]]; then
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" label node "${node}" \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" label node "${node}" \
|
||||
homelab.dev/node-role=control-plane \
|
||||
homelab.dev/storage=local \
|
||||
homelab.dev/workload-class=control-plane \
|
||||
|
|
@ -413,26 +414,26 @@ ensure_homelab_node_labels() {
|
|||
continue
|
||||
fi
|
||||
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" label node "${node}" \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" label node "${node}" \
|
||||
node-role.kubernetes.io/worker=worker \
|
||||
--overwrite
|
||||
|
||||
if [[ "${node}" == pimox-worker-* ]]; then
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" label node "${node}" \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" label node "${node}" \
|
||||
homelab.dev/node-role=app \
|
||||
homelab.dev/storage=ssd \
|
||||
homelab.dev/workload-class=platform \
|
||||
--overwrite
|
||||
elif [[ "${node}" == "${raspberry_node}" ]]; then
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" label node "${node}" \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" label node "${node}" \
|
||||
homelab.dev/node-role=edge-app \
|
||||
homelab.dev/storage=local \
|
||||
homelab.dev/workload-class=edge \
|
||||
--overwrite
|
||||
fi
|
||||
done < <(kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
|
||||
done < <(kubectl --kubeconfig "${KUBECONFIG_PATH}" get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
|
||||
|
||||
target_nodes="$(kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get nodes -l "${prometheus_selector}" -o name)"
|
||||
target_nodes="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" get nodes -l "${prometheus_selector}" -o name)"
|
||||
if [[ -z "${target_nodes}" ]]; then
|
||||
echo "No nodes match ${prometheus_selector}; refusing to move prometheus-stack." >&2
|
||||
exit 1
|
||||
|
|
@ -445,22 +446,22 @@ delete_prometheus_stack_storage() {
|
|||
local pvc_names
|
||||
local pv_names
|
||||
|
||||
pvc_names="$(kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" -n "${namespace}" get pvc -o name 2>/dev/null |
|
||||
pvc_names="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get pvc -o name 2>/dev/null |
|
||||
awk -F/ -v pattern="${pattern}" '$2 ~ pattern {print $2}')"
|
||||
pv_names="$(kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get pv \
|
||||
pv_names="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" get pv \
|
||||
-o jsonpath='{range .items[?(@.spec.claimRef.namespace=="'"${namespace}"'")]}{.metadata.name}{"\t"}{.spec.claimRef.name}{"\n"}{end}' 2>/dev/null |
|
||||
awk -v pattern="${pattern}" '$2 ~ pattern {print $1}')"
|
||||
|
||||
if [[ -n "${pvc_names}" ]]; then
|
||||
echo "Deleting old prometheus-stack PVCs in ${namespace}; saved Prometheus, Alertmanager, and Grafana data will be discarded..."
|
||||
printf '%s\n' "${pvc_names}" |
|
||||
xargs -r kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" -n "${namespace}" delete pvc --wait=true --timeout=180s
|
||||
xargs -r kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" delete pvc --wait=true --timeout=180s
|
||||
fi
|
||||
|
||||
if [[ -n "${pv_names}" ]]; then
|
||||
echo "Deleting old prometheus-stack retained PV objects..."
|
||||
printf '%s\n' "${pv_names}" |
|
||||
xargs -r kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" delete pv --wait=false
|
||||
xargs -r kubectl --kubeconfig "${KUBECONFIG_PATH}" delete pv --wait=false
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -579,7 +580,7 @@ EOF
|
|||
exit 1
|
||||
fi
|
||||
|
||||
export TF_VAR_kubeconfig_path="${TF_VAR_kubeconfig_path:-${KUBECONFIG_PATH_PATH}}"
|
||||
export TF_VAR_kubeconfig_path="${TF_VAR_kubeconfig_path:-${KUBECONFIG_PATH}}"
|
||||
export KUBECONFIG_PATH="${TF_VAR_kubeconfig_path}"
|
||||
|
||||
echo "Moving prometheus-stack off the control plane. Existing prometheus-stack PVC data will be deleted."
|
||||
|
|
@ -589,7 +590,7 @@ EOF
|
|||
tofu -chdir="${REPO_ROOT}/${stack}" destroy -target=helm_release.prometheus_stack "${approve_args[@]}"
|
||||
delete_prometheus_stack_storage "${namespace}"
|
||||
tofu -chdir="${REPO_ROOT}/${stack}" apply "${approve_args[@]}"
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" -n "${namespace}" get pods -o wide
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get pods -o wide
|
||||
}
|
||||
|
||||
doctor_versions_report() {
|
||||
|
|
@ -604,12 +605,12 @@ doctor_versions_report() {
|
|||
ensure_python3
|
||||
|
||||
api_version="$(
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" version -o json |
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" version -o json |
|
||||
python3 -c 'import json, sys; print(json.load(sys.stdin)["serverVersion"]["gitVersion"])'
|
||||
)"
|
||||
api_minor="$(printf '%s\n' "${api_version}" | awk -F. '{gsub(/^v/, "", $1); print $1 "." $2}')"
|
||||
node_rows="$(
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get nodes \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" get nodes \
|
||||
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kubeletVersion}{"\t"}{.status.nodeInfo.containerRuntimeVersion}{"\n"}{end}'
|
||||
)"
|
||||
|
||||
|
|
@ -690,12 +691,12 @@ doctor_versions_compact() {
|
|||
fi
|
||||
|
||||
api_version="$(
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" version -o json |
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" version -o json |
|
||||
python3 -c 'import json, sys; print(json.load(sys.stdin)["serverVersion"]["gitVersion"])'
|
||||
)"
|
||||
api_minor="$(printf '%s\n' "${api_version}" | awk -F. '{gsub(/^v/, "", $1); print $1 "." $2}')"
|
||||
node_rows="$(
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH_PATH}" get nodes \
|
||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" get nodes \
|
||||
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kubeletVersion}{"\t"}{.status.nodeInfo.containerRuntimeVersion}{"\n"}{end}'
|
||||
)"
|
||||
|
||||
|
|
@ -1568,10 +1569,6 @@ fi
|
|||
sudo taskset -c \"\$cpuset\" bash \"\$start_script\""
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -f \"\$start_script\"
|
||||
}
|
||||
|
||||
pimox_shutdown_vm_gracefully() {
|
||||
local host="$1"
|
||||
local user="$2"
|
||||
|
|
@ -2913,16 +2910,6 @@ fi
|
|||
EOF
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if mountpoint -q "\$mnt_dir" 2>/dev/null; then
|
||||
sudo umount "\$mnt_dir" || sudo umount -l "\$mnt_dir" || true
|
||||
fi
|
||||
if [ -n "\$loopdev" ]; then
|
||||
sudo losetup -d "\$loopdev" >/dev/null 2>&1 || true
|
||||
fi
|
||||
rm -rf "\$tmp_dir"
|
||||
}
|
||||
|
||||
openwrt() {
|
||||
require_debian_server "openwrt"
|
||||
|
||||
|
|
@ -3766,38 +3753,6 @@ sudo docker compose ps
|
|||
install_gitea_backup_timer
|
||||
}
|
||||
|
||||
install_missing_packages() {
|
||||
missing_packages=''
|
||||
for package in \"\$@\"; do
|
||||
if ! dpkg-query -W -f='\${Status}' \"\$package\" 2>/dev/null | grep -q 'install ok installed'; then
|
||||
missing_packages=\"\$missing_packages \$package\"
|
||||
fi
|
||||
done
|
||||
if [ -n \"\$missing_packages\" ]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \$missing_packages
|
||||
fi
|
||||
}
|
||||
|
||||
repair_docker_iptables() {
|
||||
if sudo iptables -t nat -S DOCKER >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo 'Docker NAT chain is missing on the Gitea host; restarting Docker once to restore iptables state...'
|
||||
sudo systemctl restart docker
|
||||
sleep 3
|
||||
|
||||
if sudo iptables -t nat -S DOCKER >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo 'Docker NAT chain is still missing after restarting Docker.' >&2
|
||||
sudo iptables -t nat -S >&2 || true
|
||||
sudo systemctl status docker --no-pager -l >&2 || true
|
||||
exit 1
|
||||
}
|
||||
|
||||
install_missing_debian_packages() {
|
||||
local missing_packages=()
|
||||
local package
|
||||
|
|
@ -5284,7 +5239,7 @@ apps() {
|
|||
website_image_ref="${registry_endpoint}/php-website:${WEBSITE_IMAGE_TAG:-$(website_image_tag "${website_source_hash}")}"
|
||||
export TF_VAR_registry_endpoint="${TF_VAR_registry_endpoint:-${registry_endpoint}}"
|
||||
export TF_VAR_website_image_ref="${TF_VAR_website_image_ref:-${website_image_ref}}"
|
||||
export TF_VAR_kubeconfig_path="${TF_VAR_kubeconfig_path:-${KUBECONFIG_PATH_PATH}}"
|
||||
export TF_VAR_kubeconfig_path="${TF_VAR_kubeconfig_path:-${KUBECONFIG_PATH}}"
|
||||
export KUBECONFIG_PATH="${TF_VAR_kubeconfig_path}"
|
||||
|
||||
require_argocd_application_controller
|
||||
|
|
@ -5704,6 +5659,15 @@ PY
|
|||
return "${status}"
|
||||
}
|
||||
|
||||
graphiphy_map() {
|
||||
if ! command -v graphiphy >/dev/null 2>&1; then
|
||||
echo "graphiphy is not installed; skipping repo map generation."
|
||||
return 0
|
||||
fi
|
||||
|
||||
graphiphy "${REPO_ROOT}"
|
||||
}
|
||||
|
||||
up_task() {
|
||||
require_debian_server "__up-task"
|
||||
|
||||
|
|
@ -5792,4 +5756,4 @@ tofu_stack_from_plan_target() {
|
|||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,8 +122,11 @@ main() {
|
|||
# 2. Render Modular Docs
|
||||
for tmpl in "${TEMPLATES_DIR}"/*.tmpl; do
|
||||
[[ -e "$tmpl" ]] || continue
|
||||
local filename=$(basename "$tmpl" .md.tmpl)
|
||||
local output_file="${DOCS_DIR}/${filename}.md"
|
||||
local filename
|
||||
local output_file
|
||||
|
||||
filename=$(basename "$tmpl" .md.tmpl)
|
||||
output_file="${DOCS_DIR}/${filename}.md"
|
||||
|
||||
if [[ "${mode}" == "check" ]]; then
|
||||
rendered_tmp=$(mktemp)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ run_test() {
|
|||
}
|
||||
|
||||
# Source modules to be tested
|
||||
# shellcheck disable=SC1091
|
||||
source /home/jv/my-homelab-configs/lib/jeannie/core.sh
|
||||
# shellcheck disable=SC1091
|
||||
source /home/jv/my-homelab-configs/lib/jeannie/env.sh
|
||||
|
||||
# Test Core: truthy (returns 0 for true, 1 for false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue