From 21adbd562835d7602071877a8d0e52a37884c751 Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Wed, 1 Jul 2026 18:57:40 -0600 Subject: [PATCH] Rebuild cluster worker vars for static Pimox workers --- jeannie | 75 ++++++++++++++++++++++++++++++++++++++++++++++ tests/jeannie-unit | 32 ++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/jeannie b/jeannie index 889da88..df20e1f 100755 --- a/jeannie +++ b/jeannie @@ -477,6 +477,10 @@ run_tofu_stack() { local auto_approve="${LAB_AUTO_APPROVE:-true}" local -a apply_args=() + if [[ "${stack}" == "bootstrap/cluster" ]]; then + ensure_cluster_worker_var_file + fi + if truthy "${auto_approve}"; then apply_args+=("-auto-approve") elif ! disabled_value "${auto_approve}"; then @@ -502,6 +506,10 @@ run_tofu_plan_stack() { local stack="$1" local -a plan_args=() + if [[ "${stack}" == "bootstrap/cluster" ]]; then + ensure_cluster_worker_var_file + fi + if [[ "${stack}" == "bootstrap/cluster" && -n "${LAB_CLUSTER_VAR_FILE:-}" ]]; then plan_args+=("-var-file=${LAB_CLUSTER_VAR_FILE}") fi @@ -1741,10 +1749,69 @@ prepare_cluster_worker_var_file() { export LAB_INCLUDE_RASPBERRY_WORKER="${LAB_INCLUDE_RASPBERRY_WORKER:-${include_raspberry_default}}" mkdir -p "${REPO_ROOT}/.lab" + ensure_static_pimox_worker_spec_file "${pimox_spec_file}" write_cluster_worker_var_file "${var_file}" "${manual_spec_file}" "${pimox_spec_file}" export LAB_CLUSTER_VAR_FILE="${var_file}" } +ensure_static_pimox_worker_spec_file() { + local spec_file="$1" + local worker_network_mode="${LAB_PIMOX_WORKER_NETWORK_MODE:-static}" + local worker_count="${LAB_PIMOX_WORKER_COUNT:-1}" + local worker_skip_indexes="${LAB_PIMOX_SKIP_WORKER_INDEXES:-}" + local worker_key_prefix="${LAB_PIMOX_WORKER_KEY_PREFIX:-pimox}" + local worker_node_prefix="${LAB_PIMOX_WORKER_NODE_PREFIX:-pimox-worker}" + local worker_user="${LAB_PIMOX_WORKER_USER:-jv}" + local worker_key_path="${LAB_PIMOX_WORKER_SSH_KEY_PATH:-/home/jv/.ssh/id_ed25519}" + local worker_static_ips="${LAB_PIMOX_WORKER_STATIC_IPS:-192.168.100.66 192.168.100.67 192.168.100.76}" + local index + local padded + local worker_key + local node_name + local static_ip + + if [[ -s "${spec_file}" || "${worker_network_mode}" != "static" ]]; then + return 0 + fi + if ! [[ "${worker_count}" =~ ^[0-9]+$ ]]; then + echo "LAB_PIMOX_WORKER_COUNT must be a non-negative integer." >&2 + return 1 + fi + if ((worker_count == 0)); then + return 0 + fi + + mkdir -p "$(dirname "${spec_file}")" + : >"${spec_file}" + for ((index = 1; index <= worker_count; index++)); do + if worker_index_is_skipped "${index}" "${worker_skip_indexes}"; then + continue + fi + if ! static_ip="$(pimox_worker_static_ip "${index}" "${worker_static_ips}")"; then + echo "LAB_PIMOX_WORKER_NETWORK_MODE=static requires LAB_PIMOX_WORKER_STATIC_IPS to include an IP for worker index ${index}." >&2 + return 1 + fi + printf -v padded '%02d' "${index}" + worker_key="${worker_key_prefix}${padded}" + node_name="${worker_node_prefix}-${padded}" + printf '%s\t%s\t%s\t%s\t%s\n' "${worker_key}" "${static_ip}" "${worker_user}" "${node_name}" "${worker_key_path}" >>"${spec_file}" + done +} + +cluster_worker_var_file_has_workers() { + local var_file="$1" + + [[ -s "${var_file}" ]] || return 1 + python3 - "${var_file}" <<'PY' +import json +import sys + +with open(sys.argv[1], encoding="utf-8") as handle: + document = json.load(handle) +sys.exit(0 if document.get("worker_nodes") else 1) +PY +} + preflight_check() { local description="$1" local output @@ -4638,6 +4705,14 @@ ensure_cluster_worker_var_file() { if [[ -z "${LAB_CLUSTER_VAR_FILE:-}" ]]; then prepare_cluster_worker_var_file true fi + if truthy "${TF_VAR_allow_empty_worker_nodes:-false}"; then + return 0 + fi + if ! cluster_worker_var_file_has_workers "${LAB_CLUSTER_VAR_FILE}"; then + echo "Cluster worker var file has no worker_nodes: ${LAB_CLUSTER_VAR_FILE}" >&2 + echo "Run the Pimox worker stage first or set LAB_PIMOX_WORKER_COUNT and LAB_PIMOX_WORKER_STATIC_IPS." >&2 + return 1 + fi } run_up_parallel_stage() { diff --git a/tests/jeannie-unit b/tests/jeannie-unit index 5a54c72..12e412e 100755 --- a/tests/jeannie-unit +++ b/tests/jeannie-unit @@ -214,6 +214,37 @@ PY unset LAB_INCLUDE_RASPBERRY_WORKER LAB_RASPBERRY_HOST LAB_RASPBERRY_NODE_NAME LAB_CLUSTER_VAR_FILE } +test_prepare_cluster_worker_var_file_rebuilds_static_pimox_spec() { + rm -f "${LAB_DIR}/pimox-workers.tsv" "${LAB_DIR}/manual-workers.tsv" "${LAB_DIR}/cluster-workers.auto.tfvars.json" + LAB_PIMOX_WORKER_NETWORK_MODE=static + LAB_PIMOX_WORKER_COUNT=2 + LAB_PIMOX_WORKER_STATIC_IPS="192.168.100.66 192.168.100.67" + LAB_PIMOX_WORKER_USER=jv + LAB_PIMOX_WORKER_SSH_KEY_PATH=/home/jv/.ssh/id_ed25519 + unset LAB_INCLUDE_RASPBERRY_WORKER + prepare_cluster_worker_var_file false + python3 - "${LAB_DIR}/pimox-workers.tsv" "${LAB_DIR}/cluster-workers.auto.tfvars.json" <<'PY' +import json +import sys + +spec_file, var_file = sys.argv[1:3] +with open(spec_file, encoding="utf-8") as handle: + specs = [line.rstrip("\n").split("\t") for line in handle if line.strip()] +if specs != [ + ["pimox01", "192.168.100.66", "jv", "pimox-worker-01", "/home/jv/.ssh/id_ed25519"], + ["pimox02", "192.168.100.67", "jv", "pimox-worker-02", "/home/jv/.ssh/id_ed25519"], +]: + raise SystemExit(f"unexpected static worker specs: {specs}") +with open(var_file, encoding="utf-8") as handle: + document = json.load(handle) +nodes = document.get("worker_nodes") or {} +if set(nodes) != {"pimox01", "pimox02"}: + raise SystemExit(f"worker_nodes was not rebuilt from static spec: {nodes}") +PY + pass "worker var file rebuilds missing static Pimox spec" + unset LAB_PIMOX_WORKER_NETWORK_MODE LAB_PIMOX_WORKER_COUNT LAB_PIMOX_WORKER_STATIC_IPS LAB_PIMOX_WORKER_USER LAB_PIMOX_WORKER_SSH_KEY_PATH LAB_CLUSTER_VAR_FILE LAB_INCLUDE_RASPBERRY_WORKER +} + test_report_renderer_hides_ok_links() { local output output="$( @@ -350,6 +381,7 @@ test_configured_worker_count_can_expand_target_set test_cluster_worker_targets_include_pimox_and_manual_workers test_prepare_cluster_worker_var_file_merges_manual_and_pimox_workers test_prepare_cluster_worker_var_file_can_include_raspberry_worker +test_prepare_cluster_worker_var_file_rebuilds_static_pimox_spec test_report_renderer_hides_ok_links test_report_renderer_problems_only_hides_ok_rows test_report_renderer_empty_problems_message