#!/usr/bin/env bash
# flux-aio 2.9.4-0 - 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/timoni-flux-aio-2-9-4-0-default.json
# Entry page: https://confighub.github.io/helm-expt/site/d/examples/timoni/flux-aio-2-9-4-0/README.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=./timoni-flux-aio-2-9-4-0-default-objects
objects_url=https://raw.githubusercontent.com/confighub/helm-expt/main/examples/timoni/flux-aio-2-9-4-0/rendered/release-objects.yaml
objects_sha256=ef43b86cb0b2de345b59d1925d0f29927e600c65c7b84c42a1bfb8710d772e8e

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 21 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 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0018 0019 0020; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0000; do mv "$work/docs/doc-$n.yaml" "$work/namespaces/"; done
for n in 0001 0002 0003 0004 0005; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
ls "$work/crds" "$work/namespaces" "$work/rest"

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

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 15 CRDs this file holds"
missing_crds=0
if ! kubectl get crd/alerts.notification.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/artifactgenerators.source.extensions.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/buckets.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/externalartifacts.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/gitrepositories.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/helmcharts.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/helmreleases.helm.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/helmrepositories.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/imagepolicies.image.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/imagerepositories.image.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/imageupdateautomations.image.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/kustomizations.kustomize.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/ocirepositories.source.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/providers.notification.toolkit.fluxcd.io >/dev/null 2>&1; then
  missing_crds=1
fi
if ! kubectl get crd/receivers.notification.toolkit.fluxcd.io >/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 alerts.notification.toolkit.fluxcd.io
wait_for_crd artifactgenerators.source.extensions.fluxcd.io
wait_for_crd buckets.source.toolkit.fluxcd.io
wait_for_crd externalartifacts.source.toolkit.fluxcd.io
wait_for_crd gitrepositories.source.toolkit.fluxcd.io
wait_for_crd helmcharts.source.toolkit.fluxcd.io
wait_for_crd helmreleases.helm.toolkit.fluxcd.io
wait_for_crd helmrepositories.source.toolkit.fluxcd.io
wait_for_crd imagepolicies.image.toolkit.fluxcd.io
wait_for_crd imagerepositories.image.toolkit.fluxcd.io
wait_for_crd imageupdateautomations.image.toolkit.fluxcd.io
wait_for_crd kustomizations.kustomize.toolkit.fluxcd.io
wait_for_crd ocirepositories.source.toolkit.fluxcd.io
wait_for_crd providers.notification.toolkit.fluxcd.io
wait_for_crd receivers.notification.toolkit.fluxcd.io

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

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

say "Done. The 15 CRDs $crd_outcome. kubectl applied the other 6 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: 1 step of this entry's plan. The entry page says who runs it."
cat <<'EOF_NOT_RUN'
   - Observe source, kustomize, helm, notification, and watcher controller readiness after apply.
EOF_NOT_RUN
