#!/usr/bin/env bash set -euo pipefail echo "== Refresh Python tools ==" python3 -m pip install --break-system-packages --upgrade \ pip \ yamllint \ ansible \ ansible-lint echo "== Sanity check installed tools ==" for cmd in docker terraform tflint ansible-lint yamllint yq jq shellcheck; do if command -v "$cmd" >/dev/null 2>&1; then echo "OK: $cmd -> $(command -v "$cmd")" else echo "MISSING: $cmd" fi done echo "== Reconcile dummy secret material ==" REPO_ROOT="${CODEX_REPO_DIR:-$PWD}" SECRETS_DIR="$REPO_ROOT/secrets" INVENTORY_JSON="$SECRETS_DIR/inventory.json" EXAMPLE_ENV="$SECRETS_DIR/.env.secrets.example" STACK_ENV="$SECRETS_DIR/stack-secrets.env" if [[ ! -f "$INVENTORY_JSON" ]]; then echo "Missing inventory file: $INVENTORY_JSON" exit 1 fi if [[ ! -f "$EXAMPLE_ENV" ]]; then echo "Missing example env file: $EXAMPLE_ENV" exit 1 fi mkdir -p "$SECRETS_DIR" dummy_value_for_key() { local key="$1" case "$key" in *EMAIL* ) echo "dummy@example.com" ;; *DB_USER* ) echo "dummyuser" ;; *USERNAME*|*USER* ) echo "dummy-user" ;; *DOMAIN* ) echo "example.lan.ddnsgeek.com" ;; *TZ ) echo "Australia/Brisbane" ;; *URL* ) echo "https://example.lan.ddnsgeek.com" ;; *PORT* ) echo "1234" ;; *PASSWORD*|*PASS*|*TOKEN*|*SECRET*|*KEY*|*JWT* ) echo "dummy-${key,,}" ;; *FINGERPRINT* ) echo "0000000000000000000000000000000000000000" ;; *DB_NAME* ) echo "dummydb" ;; *NAME* ) echo "dummy-name" ;; *ADDRESS* ) echo "dummy" ;; * ) echo "dummy-value" ;; esac } rebuild_dummy_stack_env() { local tmp tmp="$(mktemp)" cp "$EXAMPLE_ENV" "$tmp" while IFS= read -r var; do [[ -z "$var" ]] && continue dummy="$(dummy_value_for_key "$var")" if grep -Eq "^[[:space:]]*${var}=" "$tmp"; then sed -i "s|^[[:space:]]*${var}=.*|${var}=${dummy}|" "$tmp" else printf '%s=%s\n' "$var" "$dummy" >> "$tmp" fi done < <(jq -r '.env_template_variables[].variable' "$INVENTORY_JSON") mv "$tmp" "$STACK_ENV" chmod 600 "$STACK_ENV" || true echo "Updated $STACK_ENV" } reconcile_file_based_secrets() { local wanted existing relpath abspath wanted="$(mktemp)" existing="$(mktemp)" jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" | sort -u > "$wanted" find "$SECRETS_DIR" -maxdepth 1 -type f -name '*.txt' -printf '%P\n' \ | sed "s#^#secrets/#" \ | sort -u > "$existing" # Create missing listed files while IFS= read -r relpath; do [[ -z "$relpath" ]] && continue abspath="$REPO_ROOT/$relpath" if [[ ! -f "$abspath" ]]; then mkdir -p "$(dirname "$abspath")" printf 'dummy-secret\n' > "$abspath" chmod 600 "$abspath" || true echo "Created $relpath" fi done < <(comm -23 "$wanted" "$existing") # Remove stale files no longer listed in inventory.json while IFS= read -r relpath; do [[ -z "$relpath" ]] && continue abspath="$REPO_ROOT/$relpath" if [[ -f "$abspath" ]]; then rm -f "$abspath" echo "Removed stale $relpath" fi done < <(comm -13 "$wanted" "$existing") rm -f "$wanted" "$existing" } rebuild_dummy_stack_env reconcile_file_based_secrets echo "== Dummy secret reconciliation complete ==" echo "stack env: $STACK_ENV" jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" | sed 's/^/file secret: /' REPO_ROOT="${CODEX_REPO_DIR:-$PWD}" ANSIBLE_DIR="$REPO_ROOT/infrastructure/ansible" ANSIBLE_CONFIG="$ANSIBLE_DIR/ansible.cfg" ANSIBLE_COLLECTIONS_REQ="$ANSIBLE_DIR/collections/requirements.yml" ANSIBLE_INVENTORY="$ANSIBLE_DIR/inventory/hosts.yml" ANSIBLE_PING_PLAYBOOK="$ANSIBLE_DIR/playbooks/ping.yml" if [[ -f "$ANSIBLE_COLLECTIONS_REQ" ]]; then echo "== Refresh Ansible collections (bootstrap) ==" ansible-galaxy collection install -r "$ANSIBLE_COLLECTIONS_REQ" -p "$ANSIBLE_DIR/collections" || true fi if command -v ansible >/dev/null 2>&1; then echo "== Ansible bootstrap validation ==" ANSIBLE_CONFIG="$ANSIBLE_CONFIG" ansible --version | head -n 1 || true if command -v ansible-lint >/dev/null 2>&1; then ansible-lint --version || true fi if [[ -f "$ANSIBLE_INVENTORY" ]]; then ANSIBLE_CONFIG="$ANSIBLE_CONFIG" \ ansible-inventory -i "$ANSIBLE_INVENTORY" --list > /dev/null || true fi if [[ -f "$ANSIBLE_PING_PLAYBOOK" && -f "$ANSIBLE_INVENTORY" ]]; then ANSIBLE_CONFIG="$ANSIBLE_CONFIG" \ ansible-playbook -i "$ANSIBLE_INVENTORY" "$ANSIBLE_PING_PLAYBOOK" --syntax-check || true fi fi