#!/usr/bin/env bash
# gatekeeper/gatekeeper 3.22.2 - 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/gatekeeper-gatekeeper-3-22-2-default.json
# Entry page: https://confighub.github.io/helm-expt/site/charts/gatekeeper-gatekeeper-3-22-2.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=./gatekeeper-gatekeeper-3-22-2-default-objects
objects_url=https://raw.githubusercontent.com/confighub/helm-expt/main/recipes/gatekeeper/gatekeeper/3.22.2/revisions/default/r001/rendered/release-objects.yaml
objects_sha256=757e7fe97f5331bd964463ed228d147bdc090f3bb6d7c34b319522124efd2e5d

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 30 objects. The cluster is untouched so far"
rm -rf "$work/docs" "$work/crds" "$work/rest"
mkdir -p "$work/docs" "$work/crds" "$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 0014 0016 0018 0020 0022 0024; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0026 0028 0030 0032 0034; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
for n in 0047; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
ls "$work/crds" "$work/rest"

if [ "${REQUIREMENTS_READY:-0}" != "1" ]; then
  say "Stop before applying anything. This entry's plan has 2 steps that an install needs first"
  cat >&2 <<'EOF_REQUIREMENTS'
This script cannot carry out these steps of the plan. They are yours to do, with your own values:
  - CRD and admission-webhook prerequisites must be checked before apply.
  - The chart defines 17 hook object(s) that do not travel in a flattened bundle, so the work they do has to happen some other way. A recorded run installed this base without them and watched that work happen as the ordered actions below. The listing gives the rest.
Nothing was applied. Complete them before you apply the objects.
When they are 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 2 steps and does not check them"

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 default namespace if it does not exist"
if ! kubectl get namespace default >/dev/null 2>&1; then
  kubectl create namespace default
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 17 CRDs this file holds"
missing_crds=0
if ! kubectl get crd/assign.mutations.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/assignimage.mutations.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/assignmetadata.mutations.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/configs.config.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/configpodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/connections.connection.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/connectionpodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/constraintpodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/constrainttemplates.templates.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/constrainttemplatepodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/expansiontemplate.expansion.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/expansiontemplatepodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/modifyset.mutations.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/mutatorpodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/providers.externaldata.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/providerpodstatuses.status.gatekeeper.sh >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/syncsets.syncset.gatekeeper.sh >/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 assign.mutations.gatekeeper.sh
wait_for_crd assignimage.mutations.gatekeeper.sh
wait_for_crd assignmetadata.mutations.gatekeeper.sh
wait_for_crd configs.config.gatekeeper.sh
wait_for_crd configpodstatuses.status.gatekeeper.sh
wait_for_crd connections.connection.gatekeeper.sh
wait_for_crd connectionpodstatuses.status.gatekeeper.sh
wait_for_crd constraintpodstatuses.status.gatekeeper.sh
wait_for_crd constrainttemplates.templates.gatekeeper.sh
wait_for_crd constrainttemplatepodstatuses.status.gatekeeper.sh
wait_for_crd expansiontemplate.expansion.gatekeeper.sh
wait_for_crd expansiontemplatepodstatuses.status.gatekeeper.sh
wait_for_crd modifyset.mutations.gatekeeper.sh
wait_for_crd mutatorpodstatuses.status.gatekeeper.sh
wait_for_crd providers.externaldata.gatekeeper.sh
wait_for_crd providerpodstatuses.status.gatekeeper.sh
wait_for_crd syncsets.syncset.gatekeeper.sh

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

say "Done. The 17 CRDs $crd_outcome. kubectl applied the other 13 objects of this entry's retained file."
say "The script stops here. It did not wait for any workload to start"
say "Not run by this script: 3 steps of this entry's plan. The entry page says who runs each one."
cat <<'EOF_NOT_RUN'
   - CRD and admission-webhook prerequisites must be checked before apply.
   - The chart defines 17 hook object(s) that do not travel in a flattened bundle, so the work they do has to happen some other way. A recorded run installed this base without them and watched that work happen as the ordered actions below. The listing gives the rest.
   - The pinned rendered CRD route must be recorded as a target-aware operation before stronger upgrade claims.
EOF_NOT_RUN
