fix(deploy): inventory-aware orchestration and correct override paths

- orchestrate-deploy.sh: read nodes from inventory/topology.yaml instead of hardcoded list
- orchestrate-deploy.sh: LTE nodes (chelsty-infra, chelsty-ha) use ConnectTimeout=30, non-fatal on failure
- deploy-node.sh: service discovery falls back to services.yaml if no services.txt
- deploy-node.sh: override path corrected to hosts/<node>/runtime/<service>/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
oskar 2026-05-20 14:50:01 +02:00
parent dc483ae31a
commit b02c8bb50e
2 changed files with 49 additions and 24 deletions

View file

@ -8,6 +8,7 @@ set -e
REPO_PATH="${HOME}/homelab-codex-ws"
RUNTIME_PATH="/opt/homelab"
HOSTNAME=$(hostname | tr '[:lower:]' '[:upper:]')
HOST_DIR="${REPO_PATH}/hosts/$(hostname | tr '[:upper:]' '[:lower:]')"
echo "--- Starting Deployment on ${HOSTNAME} ---"
@ -22,20 +23,33 @@ echo "Pulling latest changes..."
git pull
# 2. Identify Services
# Based on our convention, we look for services assigned to this host
# For now, we'll check if a 'services.txt' exists in the host folder
SERVICE_LIST="${REPO_PATH}/hosts/$(hostname | tr '[:upper:]' '[:lower:]')/services.txt"
SERVICES=()
if [ -f "${HOST_DIR}/services.txt" ]; then
mapfile -t SERVICES < <(grep -v '^\s*#' "${HOST_DIR}/services.txt" | grep -v '^\s*$')
elif [ -f "${HOST_DIR}/services.yaml" ]; then
SERVICES=($(python3 -c "
import yaml, sys
try:
with open('${HOST_DIR}/services.yaml', 'r') as f:
data = yaml.safe_load(f)
if data and 'services' in data:
if isinstance(data['services'], dict):
print(' '.join(data['services'].keys()))
elif isinstance(data['services'], list):
print(' '.join(data['services']))
except Exception as e:
print(f'Error parsing YAML: {e}', file=sys.stderr)
sys.exit(1)
"))
fi
if [ ! -f "$SERVICE_LIST" ]; then
echo "No services.txt found for ${HOSTNAME}. Skipping service deployment."
if [ ${#SERVICES[@]} -eq 0 ]; then
echo "No services found for ${HOSTNAME}. Skipping service deployment."
exit 0
fi
# 3. Deploy Services
while IFS= read -r service || [ -n "$service" ]; do
[[ "$service" =~ ^#.*$ ]] && continue # Skip comments
[[ -z "$service" ]] && continue # Skip empty lines
for service in "${SERVICES[@]}"; do
echo "Deploying service: ${service}..."
COMPOSE_FILE="${REPO_PATH}/services/${service}/docker-compose.yml"
@ -45,13 +59,10 @@ while IFS= read -r service || [ -n "$service" ]; do
continue
fi
# Target directory in runtime
TARGET_DIR="${RUNTIME_PATH}/services/${service}"
mkdir -p "$TARGET_DIR"
# We use the compose file from the repo directly
# but we can also handle overrides here
OVERRIDE_FILE="${RUNTIME_PATH}/config/${service}/docker-compose.override.yml"
OVERRIDE_FILE="${HOST_DIR}/runtime/${service}/docker-compose.override.yml"
COMPOSE_CMD="docker compose -f ${COMPOSE_FILE}"
if [ -f "$OVERRIDE_FILE" ]; then
@ -60,7 +71,6 @@ while IFS= read -r service || [ -n "$service" ]; do
fi
$COMPOSE_CMD up -d --remove-orphans
done < "$SERVICE_LIST"
done
echo "--- Deployment Complete ---"

View file

@ -1,15 +1,30 @@
#!/usr/bin/env bash
# orchestrate-deploy.sh - To be run on SATURN
# Triggers deployment on remote execution nodes.
# Triggers deployment on remote execution nodes via inventory.
set -e
HOSTS=("solaria" "piha" "vps")
USER="oskar" # Default user
REPO_PATH="${HOME}/homelab-codex-ws"
USER="oskar"
for HOST in "${HOSTS[@]}"; do
while IFS=' ' read -r HOST TAG; do
echo ">>> Triggering deployment on ${HOST}..."
ssh "${USER}@${HOST}" "bash ~/homelab-codex-ws/scripts/deploy/deploy-node.sh"
done
if [[ "$TAG" == "lte" ]]; then
ssh -o ConnectTimeout=30 "${USER}@${HOST}" "bash ~/homelab-codex-ws/scripts/deploy/deploy-node.sh" || \
echo "WARNING: Deployment on ${HOST} failed or timed out (LTE/intermittent node, skipping)"
else
ssh "${USER}@${HOST}" "bash ~/homelab-codex-ws/scripts/deploy/deploy-node.sh"
fi
done < <(python3 -c "
import yaml, sys
with open('${REPO_PATH}/inventory/topology.yaml') as f:
data = yaml.safe_load(f)
skip = {'saturn', 'solaria'}
for name, info in (data.get('nodes') or {}).items():
if name in skip:
continue
uplink = ((info or {}).get('connectivity') or {}).get('uplink', '')
print(name, 'lte' if uplink == 'lte' else 'standard')
")
echo ">>> All deployments triggered."