#!/usr/bin/env sh # ansible/install.sh — install Ansible into a userland virtualenv and expose # its CLIs on PATH. Ansible is Python, not a single binary, so it can't live # in bin/ alongside the downloaded release binaries. # # The venv lives at ~/.local/opt/ansible and its CLIs are symlinked into # ~/.local/bin. Both are under $HOME, so they persist across Kasm redeploys; # the venv is only rebuilt when missing. Building it needs python3 + venv, # which may require a system package on a fresh box (the one place this # module uses sudo, via pkg_install). set -eu SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" REPO_ROOT="$(dirname -- "$SCRIPT_DIR")" # shellcheck source=../lib/os-detect.sh . "$REPO_ROOT/lib/os-detect.sh" # shellcheck source=../lib/fetch.sh . "$REPO_ROOT/lib/fetch.sh" say() { printf '%s\n' "$*" >&2; } VENV="$HOME/.local/opt/ansible" BIN_DIR="$HOME/.local/bin" ANSIBLE_CLIS="ansible ansible-playbook ansible-galaxy ansible-vault ansible-config ansible-doc ansible-inventory ansible-console ansible-pull" # Another ansible (mise, pipx, a distro package) already wins on PATH, so this # venv would never run -- see `shadowed` in lib/fetch.sh. if _winner="$(shadowed ansible)"; then say "ansible: $_winner comes first on PATH; skipping (a copy in $BIN_DIR would never run)." exit 0 fi # Verify it actually runs, not just that the file exists: a Kasm redeploy can # wipe the system python3 the venv links to, leaving a present-but-broken # venv that must be rebuilt. if "$VENV/bin/ansible" --version >/dev/null 2>&1; then say "ansible venv already present at $VENV." else rm -rf "$VENV" command -v python3 >/dev/null 2>&1 || pkg_install python3 say "Creating ansible venv at $VENV..." if ! python3 -m venv "$VENV" 2>/dev/null; then # Debian splits venv/ensurepip into python3-venv; install it and retry. say "python venv module missing; installing it..." case "$(detect_pkg_family)" in debian) pkg_install python3-venv python3-pip ;; rhel) pkg_install python3 python3-pip ;; *) say "install python3 venv support manually"; exit 1 ;; esac rm -rf "$VENV" python3 -m venv "$VENV" fi "$VENV/bin/pip" install --quiet --upgrade pip say "Installing ansible (this pulls in a lot of collections)..." "$VENV/bin/pip" install --quiet ansible say "Installed ansible into $VENV." fi # Symlink the CLIs into ~/.local/bin (which is on PATH via zsh/zshrc). mkdir -p "$BIN_DIR" for cli in $ANSIBLE_CLIS; do if [ -x "$VENV/bin/$cli" ]; then ln -sf "$VENV/bin/$cli" "$BIN_DIR/$cli" fi done say "Linked ansible CLIs into $BIN_DIR."