diff --git a/examples/demo/README.md b/examples/demo/README.md index d1882cb..bc00f35 100644 --- a/examples/demo/README.md +++ b/examples/demo/README.md @@ -18,6 +18,13 @@ few alerts. `./run-demo.sh --help` for the knobs, `./run-demo.sh --teardown` to tear it back down. The rest of this file is the manual walkthrough it automates. +It pulls the demo's images on the host and loads them into the kind node +first, since the node may not trust the TLS chain to `git.ryuvia.com`. To +redo just that step (after bumping a pin, or for a pod stuck in +`ImagePullBackOff`), run `./run-demo.sh --load-images`; add +`PULL_ALWAYS=true` to re-pull tags the host already has. +`PRELOAD_IMAGES=false` skips it in a full run. + ## Prerequisites - The operator and its CRDs installed and running (`make install diff --git a/examples/demo/run-demo.sh b/examples/demo/run-demo.sh index d212ea9..5290118 100755 --- a/examples/demo/run-demo.sh +++ b/examples/demo/run-demo.sh @@ -8,10 +8,20 @@ # Usage: # ./run-demo.sh deploy the whole demo (idempotent: safe to # re-run against a cluster that already has it) +# ./run-demo.sh --load-images +# only (re)load the demo's images into the +# existing kind cluster -- after bumping a pin, +# or when a pod is stuck in ImagePullBackOff # ./run-demo.sh --teardown delete the demo namespace (and, if # TEARDOWN_CLUSTER=true, the kind cluster too) # ./run-demo.sh --help # +# Images are pulled on the host and loaded into the kind node, because the +# node itself cannot always pull from git.ryuvia.com (x509 errors from a +# corporate TLS proxy whose CA the host trusts but the node does not). The +# tags come from the same files the demo deploys: the operator chart's +# appVersion, 01-server.yaml and 00-postgres.yaml. +# # All of the defaults below are overridable as environment variables. set -euo pipefail @@ -32,6 +42,12 @@ WAIT_TIMEOUT="${WAIT_TIMEOUT:-180s}" TEARDOWN_CLUSTER="${TEARDOWN_CLUSTER:-false}" +# Pull on the host and `kind load` every demo image before installing. +PRELOAD_IMAGES="${PRELOAD_IMAGES:-true}" +# Re-pull images the host already has (otherwise only missing ones are pulled). +PULL_ALWAYS="${PULL_ALWAYS:-false}" +CONTAINER_TOOL="${CONTAINER_TOOL:-docker}" + PF_PIDFILE="${PF_PIDFILE:-/tmp/terdut-demo-port-forward.pid}" PF_LOGFILE="${PF_LOGFILE:-/tmp/terdut-demo-port-forward.log}" @@ -47,9 +63,17 @@ die() { printf '[run-demo] FAILED: %s\n' "$*" >&2; exit 1; } usage() { cat </dev/null } +# manager.image.repository from the chart's values.yaml. +chart_value_image_repo() { + awk '/^manager:/{f=1;next} f&&/^[^ #]/{exit} f&&$1=="repository:"{print $2;exit}' "$1" +} + +# Prints every image the demo runs, one per line. +demo_images() { + local op_repo op_tag srv_repo srv_tag + op_repo="$(chart_value_image_repo "$CHART_DIR/values.yaml")" + op_tag="$(awk -F'"' '/^appVersion:/{print $2}' "$CHART_DIR/Chart.yaml")" + srv_repo="$(awk '$1=="repository:"{print $2;exit}' "$SCRIPT_DIR/01-server.yaml")" + srv_tag="$(awk '$1=="tag:"{print $2;exit}' "$SCRIPT_DIR/01-server.yaml")" + [ -n "$op_repo" ] && [ -n "$op_tag" ] || die "could not read the operator image from $CHART_DIR" + [ -n "$srv_repo" ] && [ -n "$srv_tag" ] || die "could not read the server image from 01-server.yaml" + printf '%s\n' "${op_repo}:${op_tag}" "${srv_repo}:${srv_tag}" + # postgres:17-alpine: the demo database, and the operator's wait-for-postgres init container. + awk '$1=="image:"{print $2}' "$SCRIPT_DIR/00-postgres.yaml" | sort -u +} + +load_images() { + command -v "$CONTAINER_TOOL" >/dev/null 2>&1 \ + || die "$CONTAINER_TOOL not on PATH (needed to pull images for kind; set CONTAINER_TOOL)" + # Not `kind load docker-image`: it imports with --all-platforms, which fails + # ("content digest ... not found") for a multi-arch image when the host's + # containerd image store only holds its own platform. Saving just that + # platform to an archive and loading the archive avoids it. + local platform="" save_args=() img archive + if [ "$CONTAINER_TOOL" = "docker" ]; then + platform="$(docker version --format '{{.Server.Os}}/{{.Server.Arch}}' 2>/dev/null || true)" + fi + if [ -n "$platform" ]; then + save_args=(--platform "$platform") + fi + archive="$(mktemp --suffix=.tar)" + while IFS= read -r img; do + if [ "$PULL_ALWAYS" = "true" ] || ! "$CONTAINER_TOOL" image inspect "$img" >/dev/null 2>&1; then + log "pulling $img on the host" + "$CONTAINER_TOOL" pull -q ${platform:+--platform "$platform"} "$img" >/dev/null \ + || { rm -f "$archive"; die "could not pull $img"; } + fi + log "loading $img into kind cluster '$CLUSTER_NAME'" + "$CONTAINER_TOOL" save "${save_args[@]}" -o "$archive" "$img" \ + && kind load image-archive --name "$CLUSTER_NAME" "$archive" >/dev/null \ + || { rm -f "$archive"; die "loading $img into kind failed"; } + done < <(demo_images) + rm -f "$archive" +} + install_operator() { log "installing terdut-operator into namespace $OPERATOR_NAMESPACE" helm upgrade --install "$RELEASE_NAME" "$CHART_DIR" \ @@ -287,6 +359,15 @@ main() { trap - EXIT exit 0 ;; + --load-images) + preflight + ensure_kind_cluster + load_images + log "images loaded; pods stuck in ImagePullBackOff retry on their own," \ + "or delete them to restart now" + trap - EXIT + exit 0 + ;; --help|-h) usage trap - EXIT @@ -301,6 +382,9 @@ main() { preflight ensure_kind_cluster + if [ "$PRELOAD_IMAGES" = "true" ]; then + load_images + fi install_operator apply_demo wait_for_server_ready