1 contributor
#!/usr/bin/env bash
set -euo pipefail
project_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
inventory_path=${INVENTORY_PATH:-"$project_root/inventory/hosts.yaml"}
upstream_hosts_file=${UPSTREAM_HOSTS_FILE:-}
upstream_ssh_target=${UPSTREAM_SSH_TARGET:-nextgen@192.168.2.103}
upstream_hosts_path=${UPSTREAM_HOSTS_PATH:-/home/nextgen/projects/ssh-infrastructure/inventory/hosts.yaml}
local_is_jumper_identity_file=${LOCAL_IS_JUMPER_IDENTITY_FILE:-}
if [[ -z "$local_is_jumper_identity_file" ]]; then
local_is_jumper_identity_file='~/.ssh/keys/is-jumper_ed25519'
fi
deploy_after_sync=${DEPLOY_AFTER_SYNC:-1}
force_deploy=${FORCE_DEPLOY:-0}
tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/ssh-infra-sync.XXXXXX")
trap 'rm -rf "$tmpdir"' EXIT
tmp_hosts="$tmpdir/hosts.yaml"
tmp_generated="$tmpdir/generated"
if [[ -n "$upstream_hosts_file" ]]; then
cp "$upstream_hosts_file" "$tmp_hosts"
else
/usr/bin/scp -q "${upstream_ssh_target}:${upstream_hosts_path}" "$tmp_hosts"
fi
python3 - "$tmp_hosts" "$local_is_jumper_identity_file" <<'PY'
from pathlib import Path
import sys
import yaml
path = Path(sys.argv[1])
identity_file = sys.argv[2]
text = path.read_text(encoding="utf-8")
with path.open("r", encoding="utf-8") as handle:
data = yaml.safe_load(handle)
is_jumper = data.get("entrypoints", {}).get("is_jumper", {})
if (
is_jumper.get("identity_file") == identity_file
and is_jumper.get("identities_only") is True
):
raise SystemExit(0)
lines = text.splitlines(keepends=True)
entrypoints_idx = None
for idx, line in enumerate(lines):
if line.strip() == "entrypoints:" and not line.startswith((" ", "\t")):
entrypoints_idx = idx
break
if entrypoints_idx is None:
raise SystemExit("missing entrypoints section")
is_jumper_idx = None
for idx in range(entrypoints_idx + 1, len(lines)):
line = lines[idx]
if line and not line.startswith((" ", "\t")) and line.strip():
break
if line.startswith(" is_jumper:"):
is_jumper_idx = idx
break
if is_jumper_idx is None:
raise SystemExit("missing entrypoints.is_jumper section")
block_end = len(lines)
for idx in range(is_jumper_idx + 1, len(lines)):
line = lines[idx]
if line.strip() and not line.startswith(" "):
block_end = idx
break
identity_line = f" identity_file: {identity_file}\n"
identities_only_line = " identities_only: true\n"
identity_idx = None
identities_only_idx = None
for idx in range(is_jumper_idx + 1, block_end):
stripped = lines[idx].strip()
if stripped.startswith("identity_file:"):
identity_idx = idx
elif stripped.startswith("identities_only:"):
identities_only_idx = idx
if identity_idx is None:
insert_at = identities_only_idx if identities_only_idx is not None else block_end
lines.insert(insert_at, identity_line)
if identities_only_idx is not None:
identities_only_idx += 1
block_end += 1
else:
lines[identity_idx] = identity_line
if identities_only_idx is None:
insert_at = (identity_idx + 1) if identity_idx is not None else block_end
lines.insert(insert_at, identities_only_line)
else:
lines[identities_only_idx] = identities_only_line
path.write_text("".join(lines), encoding="utf-8")
PY
python3 "$project_root/tools/generate-configs.py" \
--inventory "$tmp_hosts" \
--output-dir "$tmp_generated"
if cmp -s "$tmp_hosts" "$inventory_path"; then
printf 'inventory unchanged: %s\n' "$inventory_path"
if [[ "$deploy_after_sync" == "1" && "$force_deploy" == "1" ]]; then
"$project_root/tools/deploy-local.sh"
fi
exit 0
fi
install -m 644 "$tmp_hosts" "$inventory_path"
printf 'updated inventory from upstream: %s\n' "$inventory_path"
if [[ "$deploy_after_sync" == "1" ]]; then
"$project_root/tools/deploy-local.sh"
else
printf 'skipped deploy because DEPLOY_AFTER_SYNC=%s\n' "$deploy_after_sync"
fi