#!/usr/bin/env bash
# kai-scheduler/kai-scheduler v0.16.9 - base variant: default
# Path: fetch this entry's retained objects, check their SHA-256, then apply
# them with kubectl. It uses curl, shasum, awk and kubectl. It needs no cub
# CLI and no ConfigHub account.
# Generated by scripts/generate-public-site.mjs from this entry's listing:
# https://confighub.github.io/helm-expt/site/listings/kai-scheduler-kai-scheduler-v0-16-9-default.json
# Entry page: https://confighub.github.io/helm-expt/site/charts/kai-scheduler-kai-scheduler-v0-16-9.html
set -euo pipefail

say() { printf '\n>> %s\n' "$*"; }

for tool in curl awk kubectl; do
  if ! command -v "$tool" >/dev/null 2>&1; then
    printf '%s is required and was not found.\n' "$tool" >&2
    exit 1
  fi
done
if command -v shasum >/dev/null 2>&1; then
  sha256_of() { shasum -a 256 "$1" | awk '{print $1}'; }
elif command -v sha256sum >/dev/null 2>&1; then
  sha256_of() { sha256sum "$1" | awk '{print $1}'; }
else
  printf 'shasum is required and was not found.\n' >&2
  exit 1
fi

work=./kai-scheduler-kai-scheduler-v0-16-9-default-objects
objects_url=https://raw.githubusercontent.com/confighub/helm-expt/main/recipes/kai-scheduler/kai-scheduler/v0.16.9/revisions/default/r001/rendered/release-objects.yaml
objects_sha256=7254c6c835430dbc6c8513ccb0d7d5a94b2d4fd0cdc7d4029fed5e13c541dd76

say "Fetch the retained objects into $work/objects.yaml"
mkdir -p "$work"
curl -fsSL -o "$work/objects.yaml" "$objects_url"

say "Check the file against the SHA-256 in the listing"
fetched_sha256="$(sha256_of "$work/objects.yaml")"
if [ "$fetched_sha256" != "$objects_sha256" ]; then
  printf 'The file differs from the listing, so the script stops. Nothing was applied.\n  listing: %s\n  fetched: %s\n' "$objects_sha256" "$fetched_sha256" >&2
  exit 1
fi
printf 'The file matches: sha256 %s\n' "$fetched_sha256"

say "Split the file into its 37 objects. The cluster is untouched so far"
rm -rf "$work/docs" "$work/crds" "$work/namespaces" "$work/rest"
mkdir -p "$work/docs" "$work/crds" "$work/namespaces" "$work/rest"
awk -v dir="$work/docs" 'BEGIN { n = 0; f = sprintf("%s/doc-%04d.yaml", dir, n) } /^---[ \t]*$/ { close(f); n++; f = sprintf("%s/doc-%04d.yaml", dir, n); next } { print > f }' "$work/objects.yaml"
for n in 0002 0004 0006 0008 0010 0012; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0017; do mv "$work/docs/doc-$n.yaml" "$work/namespaces/"; done
for n in 0013 0014 0015 0016 0018 0019 0020 0021 0022 0023 0024 0025; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
for n in 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
for n in 0038 0039 0040 0065 0066 0067; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
ls "$work/crds" "$work/namespaces" "$work/rest"

if [ "${REQUIREMENTS_READY:-0}" != "1" ]; then
  say "Stop before applying anything. This entry's plan has 1 step that an install needs first"
  cat >&2 <<'EOF_REQUIREMENTS'
This script cannot carry out this step of the plan. It is yours to do, with your own values:
  - Before an install or an upgrade, move the CRDs forward and migrate topologies. Helm runs these in hook-weight order before it applies the chart's objects. The listing gives the rest.
Nothing was applied. Complete it before you apply the objects.
When it is done, re-run with:
  REQUIREMENTS_READY=1 bash try-objects.sh
EOF_REQUIREMENTS
  exit 1
fi
say "REQUIREMENTS_READY=1 is set. The script takes your word for 1 step and does not check it"

say "Check that kubectl reaches a cluster"
if ! kubectl get --raw /version >/dev/null 2>&1; then
  printf 'kubectl cannot reach a cluster. Point it at a throwaway cluster and re-run this script.\n' >&2
  exit 1
fi
kubectl config current-context 2>/dev/null || true

say "Create the kai-scheduler namespace if it does not exist"
if ! kubectl get namespace kai-scheduler >/dev/null 2>&1; then
  kubectl create namespace kai-scheduler
fi

wait_for_crd() {
  crd_name="$1"
  deadline=$(( $(date +%s) + 180 ))
  until kubectl get "crd/${crd_name}" >/dev/null 2>&1; do
    if [ "$(date +%s)" -ge "$deadline" ]; then
      printf "CRD %s did not appear within 180 seconds.\n" "$crd_name" >&2
      return 1
    fi
    sleep 2
  done
  kubectl wait --for=condition=Established --timeout=120s "crd/${crd_name}"
}

say "Check the 6 CRDs this file holds"
missing_crds=0
if ! kubectl get crd/configs.kai.scheduler >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/schedulingshards.kai.scheduler >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/topologies.kai.scheduler >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/bindrequests.scheduling.run.ai >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/podgroups.scheduling.run.ai >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/queues.scheduling.run.ai >/dev/null 2>&1; then
  missing_crds=1
fi
if [ "$missing_crds" -eq 1 ]; then
  say "A CRD is missing, so apply the file's CRDs first"
  kubectl apply --server-side -f "$work/crds"
  crd_outcome="were applied first"
elif kubectl diff --server-side -f "$work/crds" >/dev/null 2>&1; then
  say "The CRDs already exist and match this file. The script leaves them under their current owner"
  crd_outcome="already existed and matched, so the script left them alone"
elif [ "${APPLY_CRDS:-0}" = "1" ]; then
  say "The existing CRDs differ from this file. APPLY_CRDS=1 is set, so the script applies the file's CRDs"
  kubectl apply --server-side -f "$work/crds"
  crd_outcome="differed and were applied, because APPLY_CRDS=1 was set"
else
  say "The CRDs already exist and differ from this file, or another tool owns them"
  cat <<'EOF_CRDS'
This script does not change CRDs it did not just create.
If this is an upgrade, the objects that follow may need the newer CRDs.
To let this script apply the file's CRDs, re-run with:
  APPLY_CRDS=1 bash try-objects.sh
EOF_CRDS
  exit 1
fi
wait_for_crd configs.kai.scheduler
wait_for_crd schedulingshards.kai.scheduler
wait_for_crd topologies.kai.scheduler
wait_for_crd bindrequests.scheduling.run.ai
wait_for_crd podgroups.scheduling.run.ai
wait_for_crd queues.scheduling.run.ai

say "Apply the 1 Namespace object this file holds"
kubectl apply -f "$work/namespaces"

say "Apply the other 30 objects"
kubectl apply -f "$work/rest"

say "Done. The 6 CRDs $crd_outcome. kubectl applied the other 31 objects of this entry's retained file."
say "The script stops here. It did not wait for any workload to start"
say "This install is not finished. The plan has an install step that this script does not run:"
cat <<'EOF_INSTALL_STEPS'
   - After an install or an upgrade, apply the Config that tells the operator what to run. In this chart version the kai-config Config object is not a chart object. The listing gives the rest.
EOF_INSTALL_STEPS
say "Not run by this script: 3 other steps of this entry's plan. The entry page says who runs each one."
cat <<'EOF_NOT_RUN'
   - Before an install or an upgrade, move the CRDs forward and migrate topologies. Helm runs these in hook-weight order before it applies the chart's objects. The listing gives the rest.
   - After a delete, remove what the operator created. The post-delete-cleanup Job deletes the Deployments the operator created in the release namespace and the kai-config Config object, with its own ServiceAccount, ClusterRole and ClusterRoleBinding. The listing gives the rest.
   - Helm was asked to keep these objects when the release goes away. A reconciler that prunes anything absent from its desired state will delete them instead, and for a custom resource definition that takes every resource of that kind with it. The listing gives the rest.
EOF_NOT_RUN
