sanitized rig
This commit is contained in:
574
rig/standalone/rigdeps.sh
Executable file
574
rig/standalone/rigdeps.sh
Executable file
@@ -0,0 +1,574 @@
|
||||
#!/usr/bin/env bash
|
||||
# Put kind, tilt and kubectl on a machine that has none of them.
|
||||
#
|
||||
# The single file companion to rigmini.sh, for the same reason: rig installs its
|
||||
# toolchain from ctrl/deps.sh reading ctrl/versions.env, and neither of those is
|
||||
# going to a fresh AWS WorkSpace. The pins live inline here instead.
|
||||
#
|
||||
# What it will not do, deliberately:
|
||||
#
|
||||
# * no sudo, no apt, no yum. It writes ONLY into $OUT_BIN (default
|
||||
# ~/.local/bin). Everything needing root — installing Docker, joining the
|
||||
# docker group, raising inotify limits — is REPORTED for you to decide on.
|
||||
# That is what makes it safe to run on a machine that already works.
|
||||
# * no unverified download. Every artifact is checked against a SHA256 taken
|
||||
# from the publisher's own release list. A mismatch aborts.
|
||||
# * no guessing at another architecture. See ARCHITECTURE below.
|
||||
#
|
||||
# Two tiers, because "install the toolchain" is not one decision:
|
||||
#
|
||||
# core kubectl, jq — talk to a cluster someone else runs. Nothing that
|
||||
# creates one. The right answer on a managed or corporate machine.
|
||||
# dev core plus kind, tilt and ctlptl — build clusters and hot-reload
|
||||
# into them. The default, and what you want on a workspace of your own.
|
||||
#
|
||||
# Usage:
|
||||
# rigdeps.sh detect report the host, change nothing
|
||||
# rigdeps.sh list the pinned versions and where they come from
|
||||
# rigdeps.sh install [core|dev] detect, download, verify, install, report
|
||||
# rigdeps.sh fetch [core|dev] [--to DIR] download + verify only
|
||||
# rigdeps.sh verify run what is installed and see if it works
|
||||
set -euo pipefail
|
||||
|
||||
OUT_BIN="${OUT_BIN:-$HOME/.local/bin}"
|
||||
|
||||
# ── the pinned toolchain ───────────────────────────────────────────────────
|
||||
#
|
||||
# ARCHITECTURE. These checksums are the upstream-published SHA256 of the
|
||||
# **linux/amd64** artifact and of nothing else. An arm64 WorkSpace bundle needs
|
||||
# a different binary with a different checksum, and this script refuses rather
|
||||
# than reusing these — a checksum that is merely plausible is worse than none,
|
||||
# because it turns a verified download into a ceremony.
|
||||
#
|
||||
# To bump a version, or to add arm64: take the checksum from the release's own
|
||||
# published list, never from a download you did.
|
||||
#
|
||||
# curl -sSL https://github.com/<org>/<repo>/releases/download/<tag>/checksums.txt
|
||||
#
|
||||
# kubectl publishes its own instead, at <KUBECTL_URL>.sha256.
|
||||
|
||||
KIND_VERSION=v0.32.0
|
||||
KIND_SHA256=50030de23cf40a18505f20426f6a8506bedf13c6e509244bd1fa9463721b0f54
|
||||
KIND_URL="https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64"
|
||||
|
||||
KUBECTL_VERSION=v1.36.3
|
||||
KUBECTL_SHA256=ebbd080e7c2e275093b55915722043257eb24004363e20acb3c4d71919f88336
|
||||
KUBECTL_URL="https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
|
||||
|
||||
TILT_VERSION=0.37.6
|
||||
TILT_SHA256=e9672b8a18d43501f35dcfe98465969a7db0e436b36cf0c50c7e6f8d40de5fe6
|
||||
TILT_URL="https://github.com/tilt-dev/tilt/releases/download/v${TILT_VERSION}/tilt.${TILT_VERSION}.linux.x86_64.tar.gz"
|
||||
|
||||
# ctlptl creates a kind cluster WITH a local registry wired in, which is what
|
||||
# keeps images off docker.io — an unqualified image name resolves to
|
||||
# docker.io/library/<name>, and there is nothing structural stopping a push there.
|
||||
CTLPTL_VERSION=0.9.4
|
||||
CTLPTL_SHA256=c63a1ec28e60bc3faf6becb76f53355c5cf5e0143dafdd27ad85db5584fa6b1e
|
||||
CTLPTL_URL="https://github.com/tilt-dev/ctlptl/releases/download/v${CTLPTL_VERSION}/ctlptl.${CTLPTL_VERSION}.linux.x86_64.tar.gz"
|
||||
|
||||
# Upstream's static build. Debian's jq is linked against libjq/libonig, which is
|
||||
# fine on Debian and not portable anywhere else.
|
||||
JQ_VERSION=1.8.2
|
||||
JQ_SHA256=b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f
|
||||
JQ_URL="https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/jq-linux-amd64"
|
||||
|
||||
CORE_TOOLS="kubectl jq"
|
||||
DEV_TOOLS="kind tilt ctlptl"
|
||||
|
||||
# No helm: every rig addon installs with `kubectl apply -f`, so nothing has ever
|
||||
# invoked it. Add it the day something actually needs a chart.
|
||||
|
||||
# Collected as we go, printed by report_manual() at the very end. Anything that
|
||||
# needs root or a decision lands here instead of being done.
|
||||
MANUAL=()
|
||||
|
||||
# ── platform ───────────────────────────────────────────────────────────────
|
||||
|
||||
# Windows outside WSL — Git Bash, MSYS, Cygwin — looks close enough to work and
|
||||
# then fails in a pile of confusing ways: no /proc, no docker socket, none of
|
||||
# the tooling. Detectable, so name it instead.
|
||||
require_linux() {
|
||||
case "$(uname -s)" in
|
||||
MINGW*|MSYS*|CYGWIN*)
|
||||
cat >&2 <<'EOF'
|
||||
This has to run inside WSL, not Git Bash / MSYS / Cygwin.
|
||||
|
||||
If WSL is not installed yet, from an elevated PowerShell or Command Prompt:
|
||||
|
||||
wsl --install
|
||||
|
||||
That enables Windows features and needs a reboot, so it is not something this
|
||||
script will do for you. Afterwards, open the Linux shell it installs and run
|
||||
this from there.
|
||||
EOF
|
||||
exit 1 ;;
|
||||
Linux) ;;
|
||||
*) echo "$(uname -s) is not Linux. These are linux binaries; nothing here" >&2
|
||||
echo "would run even if it downloaded." >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) echo amd64 ;;
|
||||
aarch64|arm64) echo arm64 ;;
|
||||
*) uname -m ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# The pins above are amd64. Rather than download something that cannot execute
|
||||
# and let it fail as "cannot execute binary file: Exec format error", say so
|
||||
# here and hand over the commands that produce the right checksums.
|
||||
require_amd64() {
|
||||
local a; a=$(arch)
|
||||
[ "$a" = "amd64" ] && return 0
|
||||
cat >&2 <<EOF
|
||||
This machine is ${a} ($(uname -m)); every pin in this script is linux/amd64.
|
||||
|
||||
Nothing here would run, so it does not download. To make an ${a} version, the
|
||||
URLs need the ${a} artifact and the checksums need to come from each project's
|
||||
own published list — not from these values, and not from a download you did:
|
||||
|
||||
curl -sSL https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/checksums.txt
|
||||
curl -sSL https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${a}/kubectl.sha256
|
||||
curl -sSL https://github.com/tilt-dev/tilt/releases/download/v${TILT_VERSION}/checksums.txt
|
||||
curl -sSL https://github.com/tilt-dev/ctlptl/releases/download/v${CTLPTL_VERSION}/checksums.txt
|
||||
curl -sSL https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/sha256sum.txt
|
||||
|
||||
Edit the pinned block at the top of this file with what those print.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
is_wsl() { grep -qi microsoft /proc/version 2>/dev/null; }
|
||||
|
||||
# ── the tools this script itself needs ─────────────────────────────────────
|
||||
|
||||
# A fresh minimal image may genuinely have neither curl nor wget. Find out once,
|
||||
# up front, rather than half way through the first download.
|
||||
DL=""
|
||||
pick_downloader() {
|
||||
if command -v curl >/dev/null 2>&1; then DL=curl
|
||||
elif command -v wget >/dev/null 2>&1; then DL=wget
|
||||
else
|
||||
echo "neither curl nor wget is installed, so nothing can be downloaded." >&2
|
||||
echo "Install one first: $(pkg_install_cmd curl)" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download() {
|
||||
local url="$1" out="$2"
|
||||
case "$DL" in
|
||||
curl) curl -fsSL --retry 3 -o "$out" "$url" ;;
|
||||
wget) wget -q --tries=3 -O "$out" "$url" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# sha256sum is coreutils; shasum is the perl one that turns up on stripped
|
||||
# images. Verification is not optional, so if neither exists that is fatal.
|
||||
SHA=""
|
||||
pick_sha() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then SHA=sha256sum
|
||||
elif command -v shasum >/dev/null 2>&1; then SHA="shasum -a 256"
|
||||
else
|
||||
echo "no sha256sum and no shasum — downloads could not be verified." >&2
|
||||
echo "Refusing to install unverified binaries." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ── package manager, for the instructions only ─────────────────────────────
|
||||
# This never runs a package manager. It names one so the reported action is
|
||||
# something you can paste, on the distro you are actually on — an apt line on
|
||||
# Amazon Linux 2 is a wrong answer dressed up as help.
|
||||
|
||||
pkg_install_cmd() {
|
||||
local pkg="$1"
|
||||
if command -v apt-get >/dev/null 2>&1; then echo "sudo apt-get update && sudo apt-get install -y $pkg"
|
||||
elif command -v dnf >/dev/null 2>&1; then echo "sudo dnf install -y $pkg"
|
||||
elif command -v yum >/dev/null 2>&1; then echo "sudo yum install -y $pkg"
|
||||
elif command -v zypper >/dev/null 2>&1; then echo "sudo zypper install -y $pkg"
|
||||
elif command -v apk >/dev/null 2>&1; then echo "sudo apk add $pkg"
|
||||
else echo "install '$pkg' with this system's package manager"
|
||||
fi
|
||||
}
|
||||
|
||||
docker_pkg() {
|
||||
# Debian and Ubuntu call it docker.io; the RPM distros call it docker.
|
||||
if command -v apt-get >/dev/null 2>&1; then echo docker.io; else echo docker; fi
|
||||
}
|
||||
|
||||
# ── detect ─────────────────────────────────────────────────────────────────
|
||||
|
||||
detect() {
|
||||
echo "host"
|
||||
echo " kernel $(uname -r)"
|
||||
echo " arch $(arch) ($(uname -m))"
|
||||
[ -r /etc/os-release ] && \
|
||||
echo " distro $(sed -n 's/^PRETTY_NAME="\(.*\)"/\1/p' /etc/os-release)"
|
||||
if is_wsl; then echo " platform WSL"; else echo " platform native linux"; fi
|
||||
|
||||
local total_kb avail_kb
|
||||
total_kb=$(awk '/^MemTotal:/{print $2}' /proc/meminfo)
|
||||
avail_kb=$(awk '/^MemAvailable:/{print $2}' /proc/meminfo)
|
||||
printf " memory %d GB total, %d GB available\n" \
|
||||
$((total_kb / 1024 / 1024)) $((avail_kb / 1024 / 1024))
|
||||
if [ $((avail_kb / 1024 / 1024)) -lt 4 ]; then
|
||||
echo " ! under 4 GB available — a cluster will struggle here."
|
||||
echo " rigmini.sh says how much this box will actually give you."
|
||||
fi
|
||||
|
||||
echo " install to $OUT_BIN"
|
||||
detect_libc
|
||||
detect_prereqs
|
||||
detect_docker
|
||||
detect_inotify
|
||||
return 0
|
||||
}
|
||||
|
||||
# tilt is the one binary here that needs a recent glibc. MEASURED, not guessed:
|
||||
# tilt 0.37.6 on Amazon Linux 2 (glibc 2.26) fails with
|
||||
#
|
||||
# /lib64/libc.so.6: version `GLIBC_2.34' not found (required by .../tilt)
|
||||
#
|
||||
# which names a symbol rather than the problem. Amazon Linux 2 is a stock
|
||||
# WorkSpaces bundle, so this is the likely case, not an exotic one. Report the
|
||||
# version now; `verify` catches the actual failure after installing.
|
||||
detect_libc() {
|
||||
local v=""
|
||||
if command -v ldd >/dev/null 2>&1; then
|
||||
v=$(ldd --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+$' || true)
|
||||
fi
|
||||
if [ -z "$v" ]; then
|
||||
echo " libc unknown (no ldd) — 'verify' is the real test"
|
||||
return 0
|
||||
fi
|
||||
echo " libc glibc $v"
|
||||
if [ "$(printf '%s\n2.34\n' "$v" | sort -V | head -1)" != "2.34" ]; then
|
||||
echo " ! older than glibc 2.34, which tilt needs. kubectl, kind, jq and"
|
||||
echo " ctlptl are static or libc-only and work here; tilt will not start."
|
||||
echo " Install the core tier, or run tilt from a container."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# What this script needs to do its own job. Reported here so `detect` answers
|
||||
# "will install work?" instead of leaving you to find out one download in.
|
||||
# Amazon Linux 2 ships without tar, which is exactly the surprise this catches.
|
||||
detect_prereqs() {
|
||||
local missing=""
|
||||
if command -v curl >/dev/null 2>&1; then echo " download curl"
|
||||
elif command -v wget >/dev/null 2>&1; then echo " download wget"
|
||||
else echo " ! no curl and no wget — nothing can be downloaded"; missing+=" curl"
|
||||
fi
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1 || command -v shasum >/dev/null 2>&1; then
|
||||
echo " checksums ok"
|
||||
else
|
||||
echo " ! no sha256sum or shasum — downloads could not be verified"
|
||||
missing+=" coreutils"
|
||||
fi
|
||||
|
||||
if command -v tar >/dev/null 2>&1 && command -v gzip >/dev/null 2>&1; then
|
||||
echo " archives tar + gzip"
|
||||
else
|
||||
echo " ! no tar/gzip — tilt and ctlptl ship as tarballs, so the dev tier"
|
||||
echo " cannot be unpacked. The core tier is two bare binaries and is fine."
|
||||
missing+=" tar gzip"
|
||||
fi
|
||||
|
||||
if [ -n "$missing" ]; then
|
||||
MANUAL+=("Install what this script needs to run at all:
|
||||
$(pkg_install_cmd "${missing# }")")
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
detect_docker() {
|
||||
# kind builds a cluster out of containers. Without a reachable daemon,
|
||||
# everything here installs perfectly and then does nothing.
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
if [ -S /var/run/docker.sock ]; then
|
||||
echo " docker socket present, no cli"
|
||||
return 0
|
||||
fi
|
||||
echo " ! docker not installed — kind has nothing to build a cluster in"
|
||||
MANUAL+=("Install Docker. It is the one real prerequisite, and the only
|
||||
thing here that needs root:
|
||||
$(pkg_install_cmd "$(docker_pkg)")
|
||||
sudo systemctl enable --now docker
|
||||
sudo usermod -aG docker \"\$USER\"
|
||||
then log out and back in, so the new group applies to your shell.")
|
||||
return 0
|
||||
fi
|
||||
if docker info >/dev/null 2>&1; then
|
||||
echo " docker $(docker version --format '{{.Server.Version}}' 2>/dev/null)"
|
||||
local n
|
||||
n=$(docker ps --filter "label=io.x-k8s.kind.cluster" --format '{{.Names}}' 2>/dev/null | wc -l)
|
||||
# Must be an `if`, not `[ ] && echo`: as the last statement here the
|
||||
# latter returns 1 when the count is zero, and `set -e` kills the
|
||||
# caller. That is the fresh-machine case, where it does most harm.
|
||||
if [ "$n" -gt 0 ]; then
|
||||
echo " - $n kind node container(s) already running"
|
||||
fi
|
||||
else
|
||||
echo " ! docker cli present but the daemon is unreachable"
|
||||
MANUAL+=("Start Docker, or add yourself to the docker group:
|
||||
sudo systemctl enable --now docker
|
||||
sudo usermod -aG docker \"\$USER\" # then log out and back in")
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# kind and tilt both watch large trees. Distro defaults are far too low and the
|
||||
# failure mode is silent: tilt simply stops noticing that files changed.
|
||||
detect_inotify() {
|
||||
local w i
|
||||
w=$(cat /proc/sys/fs/inotify/max_user_watches 2>/dev/null || echo 0)
|
||||
i=$(cat /proc/sys/fs/inotify/max_user_instances 2>/dev/null || echo 0)
|
||||
echo " inotify watches=$w instances=$i"
|
||||
if [ "$w" -lt 524288 ] || [ "$i" -lt 512 ]; then
|
||||
echo " ! low — tilt will silently stop seeing file changes"
|
||||
MANUAL+=("Raise the inotify limits (needs root):
|
||||
echo -e 'fs.inotify.max_user_watches=524288\\nfs.inotify.max_user_instances=512' \\
|
||||
| sudo tee /etc/sysctl.d/99-rig.conf
|
||||
sudo sysctl --system")
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── fetch ──────────────────────────────────────────────────────────────────
|
||||
|
||||
verify_sha() {
|
||||
local file="$1" want="$2" name="$3" got
|
||||
got=$($SHA "$file" | awk '{print $1}')
|
||||
if [ "$got" != "$want" ]; then
|
||||
echo >&2
|
||||
echo "CHECKSUM MISMATCH for $name — not installing it." >&2
|
||||
echo " expected $want" >&2
|
||||
echo " got $got" >&2
|
||||
echo >&2
|
||||
echo "Either the pin in this script is stale, or what arrived is not what" >&2
|
||||
echo "the publisher released. Neither is worth guessing about." >&2
|
||||
rm -f "$file"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# fetch_bin <name> <url> <sha256> <dest-dir> — a bare binary
|
||||
fetch_bin() {
|
||||
local name="$1" url="$2" sha="$3" dest="$4"
|
||||
local tmp="$dest/.$name.tmp"
|
||||
printf ' %-8s ' "$name"
|
||||
download "$url" "$tmp"
|
||||
verify_sha "$tmp" "$sha" "$name"
|
||||
mv "$tmp" "$dest/$name"
|
||||
chmod +x "$dest/$name"
|
||||
echo "ok"
|
||||
}
|
||||
|
||||
# fetch_tgz <name> <url> <sha256> <dest-dir> <path-inside> <strip>
|
||||
# Archive layouts differ, so the caller says which. tilt and ctlptl both ship
|
||||
# the binary at the archive root, hence strip=0.
|
||||
fetch_tgz() {
|
||||
local name="$1" url="$2" sha="$3" dest="$4" inner="$5" strip="$6"
|
||||
local tmp="$dest/.$name.tgz"
|
||||
printf ' %-8s ' "$name"
|
||||
download "$url" "$tmp"
|
||||
verify_sha "$tmp" "$sha" "$name"
|
||||
# --no-same-owner: some archives ship as uid 1001, and extracting as root
|
||||
# would otherwise restore an owner that is not you.
|
||||
tar -xzf "$tmp" -C "$dest" --strip-components="$strip" --no-same-owner "$inner"
|
||||
rm -f "$tmp"
|
||||
chmod +x "$dest/$name"
|
||||
echo "ok"
|
||||
}
|
||||
|
||||
fetch() {
|
||||
local dest="$OUT_BIN" tier="dev"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--to) dest="${2:?--to needs a directory}"; shift 2 ;;
|
||||
core|dev) tier="$1"; shift ;;
|
||||
*) echo "unknown argument: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
mkdir -p "$dest"
|
||||
|
||||
if ! command -v tar >/dev/null 2>&1 && [ "$tier" = "dev" ]; then
|
||||
echo "tar is missing, and tilt and ctlptl ship as tarballs." >&2
|
||||
echo " $(pkg_install_cmd tar)" >&2
|
||||
echo "Or install the core tier, which is two bare binaries: $0 install core" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "fetching '$tier' into $dest (verifying every checksum)"
|
||||
fetch_bin kubectl "$KUBECTL_URL" "$KUBECTL_SHA256" "$dest"
|
||||
fetch_bin jq "$JQ_URL" "$JQ_SHA256" "$dest"
|
||||
if [ "$tier" = "dev" ]; then
|
||||
fetch_bin kind "$KIND_URL" "$KIND_SHA256" "$dest"
|
||||
fetch_tgz tilt "$TILT_URL" "$TILT_SHA256" "$dest" tilt 0
|
||||
fetch_tgz ctlptl "$CTLPTL_URL" "$CTLPTL_SHA256" "$dest" ctlptl 0
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── verify ─────────────────────────────────────────────────────────────────
|
||||
|
||||
tier_tools() { [ "$1" = "core" ] && echo "$CORE_TOOLS" || echo "$CORE_TOOLS $DEV_TOOLS"; }
|
||||
|
||||
# Downloading a verified binary proves it is the right file, not that this
|
||||
# machine can run it. On an old distro tilt fails here, with a linker error
|
||||
# about a missing symbol, and finding that out now beats finding out during a
|
||||
# first cluster build.
|
||||
verify_tools() {
|
||||
local tier="${1:-dev}" b bin out rc broke=0
|
||||
echo "checking that each one actually runs"
|
||||
for b in $(tier_tools "$tier"); do
|
||||
bin="$OUT_BIN/$b"
|
||||
if [ ! -x "$bin" ]; then
|
||||
printf ' %-8s not installed\n' "$b"
|
||||
continue
|
||||
fi
|
||||
rc=0
|
||||
case "$b" in
|
||||
kubectl) out=$("$bin" version --client 2>&1 | head -1) || rc=$? ;;
|
||||
jq) out=$("$bin" --version 2>&1 | head -1) || rc=$? ;;
|
||||
*) out=$("$bin" version 2>&1 | head -1) || rc=$? ;;
|
||||
esac
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
printf ' %-8s %s\n' "$b" "$out"
|
||||
else
|
||||
printf ' ! %-6s does not run here: %s\n' "$b" "$out"
|
||||
broke=1
|
||||
fi
|
||||
done
|
||||
if [ "$broke" -eq 1 ]; then
|
||||
echo
|
||||
echo " A binary that downloads and verifies but will not start is almost"
|
||||
echo " always this distro's libc being older than the release needs."
|
||||
echo " 'detect' prints the glibc version. The core tier (kubectl + jq)"
|
||||
echo " has no such dependency and will work regardless."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── install ────────────────────────────────────────────────────────────────
|
||||
|
||||
# Installing into a directory early in PATH silently replaces whatever the
|
||||
# machine was already using, which on a shared or corporate machine can break
|
||||
# unrelated work — kubectl more than one minor away from its cluster is the
|
||||
# common one. Say so; never decide it.
|
||||
warn_shadowing() {
|
||||
local b existing shadowed="" tier="${1:-dev}"
|
||||
case ":${PATH}:" in
|
||||
*":$OUT_BIN:"*) ;;
|
||||
*) return 0 ;; # not on PATH, so nothing is being shadowed yet
|
||||
esac
|
||||
for b in $(tier_tools "$tier"); do
|
||||
[ -x "$OUT_BIN/$b" ] || continue
|
||||
existing=$(PATH=$(echo "$PATH" | tr ':' '\n' | grep -vx "$OUT_BIN" | paste -sd:) \
|
||||
command -v "$b" 2>/dev/null || true)
|
||||
[ -n "$existing" ] || continue
|
||||
[ "$existing" = "$OUT_BIN/$b" ] && continue
|
||||
shadowed+=" $b $existing"$'\n'
|
||||
done
|
||||
[ -n "$shadowed" ] || return 0
|
||||
|
||||
echo
|
||||
echo " ! these were already installed elsewhere and are now shadowed:"
|
||||
printf '%s' "$shadowed"
|
||||
MANUAL+=("Decide which toolchain wins. To keep the previous one:
|
||||
rm -f $(for b in $(tier_tools "$tier"); do printf '%s ' "$OUT_BIN/$b"; done)
|
||||
Or install somewhere private instead:
|
||||
OUT_BIN=\$PWD/bin $0 install")
|
||||
return 0
|
||||
}
|
||||
|
||||
report_manual() {
|
||||
echo
|
||||
if [ ${#MANUAL[@]} -eq 0 ]; then
|
||||
echo "nothing left to do by hand."
|
||||
return 0
|
||||
fi
|
||||
echo "host actions this cannot perform (${#MANUAL[@]}):"
|
||||
echo
|
||||
local n=1 m
|
||||
for m in "${MANUAL[@]}"; do
|
||||
echo " $n. $m"
|
||||
echo
|
||||
n=$((n + 1))
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
install() {
|
||||
local tier="${1:-dev}"
|
||||
detect
|
||||
echo
|
||||
fetch "$tier"
|
||||
echo
|
||||
verify_tools "$tier"
|
||||
warn_shadowing "$tier"
|
||||
|
||||
if [ "$tier" = "core" ]; then
|
||||
echo
|
||||
echo " core tier: no kind, tilt or ctlptl. '$0 install dev' adds them."
|
||||
fi
|
||||
|
||||
case ":${PATH}:" in
|
||||
*":$OUT_BIN:"*) ;;
|
||||
*) MANUAL+=("Put the toolchain on your PATH — add to ~/.bashrc:
|
||||
export PATH=\"${OUT_BIN}:\$PATH\"
|
||||
then: source ~/.bashrc") ;;
|
||||
esac
|
||||
|
||||
report_manual
|
||||
|
||||
if [ "$tier" = "dev" ]; then
|
||||
echo "Once Docker is reachable and this is on PATH:"
|
||||
echo
|
||||
echo " kind create cluster --name scratch"
|
||||
echo " kubectl cluster-info --context kind-scratch"
|
||||
echo " kind delete cluster --name scratch"
|
||||
echo
|
||||
echo "That round trip is the real test that this machine can host a rig."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
list() {
|
||||
echo "pinned, linux/amd64 only:"
|
||||
printf ' %-8s %s\n' kubectl "$KUBECTL_VERSION"
|
||||
printf ' %-8s %s\n' jq "$JQ_VERSION"
|
||||
printf ' %-8s %s\n' kind "$KIND_VERSION"
|
||||
printf ' %-8s %s\n' tilt "$TILT_VERSION"
|
||||
printf ' %-8s %s\n' ctlptl "$CTLPTL_VERSION"
|
||||
echo
|
||||
echo " core = $CORE_TOOLS"
|
||||
echo " dev = $CORE_TOOLS $DEV_TOOLS"
|
||||
echo
|
||||
echo "Checksums are pinned in the block at the top of this file. To bump one,"
|
||||
echo "take the new checksum from the publisher's own release list — the header"
|
||||
echo "comment has the exact commands."
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── main ───────────────────────────────────────────────────────────────────
|
||||
|
||||
require_linux
|
||||
|
||||
case "${1:-install}" in
|
||||
detect) detect; report_manual ;;
|
||||
list) list ;;
|
||||
verify) verify_tools "${2:-dev}" ;;
|
||||
fetch) shift; require_amd64; pick_downloader; pick_sha; fetch "$@" ;;
|
||||
install) shift; require_amd64; pick_downloader; pick_sha; install "${1:-dev}" ;;
|
||||
*) echo "usage: $0 [detect|list|install|fetch|verify]" >&2
|
||||
echo " install [core|dev] (default dev)" >&2
|
||||
echo " fetch [core|dev] [--to DIR]" >&2
|
||||
echo " OUT_BIN=<dir> overrides the install directory" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user