download_tool() { local destination="$1" local checksum="$2" local url="$3" if [[ -x "$destination" ]] && [[ "$(sha256sum "$destination" | cut -d' ' -f1)" = "$checksum" ]]; then return fi curl --fail --location --silent --show-error "$url" --output "$destination.tmp" test "$(sha256sum "$destination.tmp" | cut -d' ' -f1)" = "$checksum" chmod 0755 "$destination.tmp" mv "$destination.tmp" "$destination" } prepare_tools() { mkdir -p "$BIN" download_tool \ "$BIN/kind" \ "$KIND_SHA256" \ "https://github.com/kubernetes-sigs/kind/releases/download/$KIND_VERSION/kind-linux-amd64" download_tool \ "$BIN/kubectl" \ "$KUBECTL_SHA256" \ "https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl" test "$("$BIN/kind" version | awk '{print $2}')" = "$KIND_VERSION" test "$("$BIN/kubectl" --kubeconfig "$KUBECONFIG_PATH" --context "$CONTEXT" version --client=true -o json | jq -r .clientVersion.gitVersion)" = "$KUBECTL_VERSION" test "$(nerdctl --version | awk '{print $3}')" = "$NERDCTL_VERSION" test "$(runtime_ctr version | awk '/Client:/{client=1} client && $1=="Version:"{print $2; exit}')" = "v$CONTAINERD_VERSION" test "$(runtime_ctr version | awk '/Server:/{server=1} server && $1=="Version:"{print $2; exit}')" = "v$CONTAINERD_VERSION" } configure_provider() { if [[ -z "${NUTHATCH_REAL_NERDCTL:-}" ]]; then NUTHATCH_REAL_NERDCTL="$(command -v nerdctl)" || return fi export NUTHATCH_REAL_NERDCTL export CONTAINERD_NAMESPACE="$NERDCTL_NAMESPACE" export KIND_EXPERIMENTAL_PROVIDER=nerdctl export PATH="$TESTBED/provider:$PATH" } runtime_ctr() { ctr --address "${CONTAINERD_ADDRESS:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/containerd/containerd.sock}" "$@" } runtime_namespace_exists() { "$NUTHATCH_REAL_NERDCTL" namespace list --quiet | grep -Fx "$NERDCTL_NAMESPACE" >/dev/null } cluster_exists() { runtime_namespace_exists && "$BIN/kind" get clusters | grep -Fx "$CLUSTER" >/dev/null } delete_cluster() { local container local containers if cluster_exists; then "$BIN/kind" delete cluster --name "$CLUSTER" || true fi containers="$("$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" ps \ --all \ --quiet \ --filter "label=io.x-k8s.kind.cluster=$CLUSTER")" || return while IFS= read -r container; do [[ -z "$container" ]] || "$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" rm --force "$container" || return done <<< "$containers" if cluster_exists; then "$BIN/kind" delete cluster --name "$CLUSTER" || true fi if cluster_exists; then printf 'kind cluster %s still exists after teardown\n' "$CLUSTER" >&2 return 1 fi } remove_runtime_namespace() { local status=0 local digest local digests local lease local leases local network for network in kind nuthatch-kind; do if "$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" network inspect "$network" >/dev/null 2>&1; then "$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" network remove "$network" >/dev/null || status=1 fi done if ! runtime_namespace_exists; then return "$status" fi "$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" image prune --all --force >/dev/null || status=1 leases="$(runtime_ctr --namespace "$NERDCTL_NAMESPACE" leases list --quiet)" || status=1 while IFS= read -r lease; do [[ -z "$lease" ]] || runtime_ctr --namespace "$NERDCTL_NAMESPACE" leases delete "$lease" >/dev/null || status=1 done <<< "$leases" digests="$(runtime_ctr --namespace "$NERDCTL_NAMESPACE" content list --quiet)" || status=1 while IFS= read -r digest; do [[ -z "$digest" ]] || runtime_ctr --namespace "$NERDCTL_NAMESPACE" content remove "$digest" >/dev/null || status=1 done <<< "$digests" "$NUTHATCH_REAL_NERDCTL" namespace remove "$NERDCTL_NAMESPACE" >/dev/null || status=1 runtime_namespace_exists && status=1 return "$status" } prepare_provider() { configure_provider delete_cluster remove_runtime_namespace "$NUTHATCH_REAL_NERDCTL" namespace create "$NERDCTL_NAMESPACE" >/dev/null } load_external_image() { local name="$1" local source="$2" local digest="${source##*@}" local image="nuthatch-testbed/$name:sha256-${digest#sha256:}" local archive="$RUNTIME/image-archives/$digest.tar" "$NUTHATCH_REAL_NERDCTL" image pull --platform linux/amd64 --unpack=false --quiet "$source" >&2 "$NUTHATCH_REAL_NERDCTL" image tag "$source" "$image" "$NUTHATCH_REAL_NERDCTL" image save --platform linux/amd64 --output "$archive" "$image" printf 'Loading %s from %s\n' "$image" "$source" >&2 "$BIN/kind" load image-archive "$archive" --name "$CLUSTER" >&2 printf '%s\n' "$image" } load_local_image() { local image="$1" local namespace="${2:-default}" local archive="$RUNTIME/image-archives/nuthatch-app.tar" rm -f "$archive" "$NUTHATCH_REAL_NERDCTL" --namespace "$namespace" image save \ --platform linux/amd64 \ --output "$archive" \ "$image" "$BIN/kind" load image-archive "$archive" --name "$CLUSTER" }