#!/usr/bin/env bash
# jetstack/trust-manager v0.22.1 - 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/jetstack-trust-manager-v0-22-1-default.json
# Entry page: https://confighub.github.io/helm-expt/site/charts/jetstack-trust-manager-v0-22-1.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=./jetstack-trust-manager-v0-22-1-default-objects
objects_url=https://raw.githubusercontent.com/confighub/helm-expt/main/recipes/jetstack/trust-manager/v0.22.1/revisions/default/r001/rendered/release-objects.yaml
objects_sha256=50eb2239a5db07734497711c4e812eb111d231852c2f614e5b0a1faec7bab683

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 14 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; do mv "$work/docs/doc-$n.yaml" "$work/crds/"; done
for n in 0001 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013; do mv "$work/docs/doc-$n.yaml" "$work/rest/"; done
for n in 0014; 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:
  - The installer package includes these CRDs as prerequisites/target-facts/default-crds.yaml. Apply the missing CRDs server-side and leave existing CRDs under their current owner. The listing gives the rest.
  - Secret default/trust-manager-tls must exist before apply. trust-manager admission webhook TLS material normally produced by the rendered cert-manager Certificate lifecycle.
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

serves_kind() {
  kubectl api-resources --api-group="$1" --no-headers 2>/dev/null | awk -v kind="$2" '$NF == kind { found = 1 } END { exit found ? 0 : 1 }'
}

say "Check that the cluster serves the 2 kinds this file uses and does not define"
missing_kinds=""
if ! serves_kind cert-manager.io Certificate; then
  missing_kinds="$missing_kinds Certificate.cert-manager.io"
fi
if ! serves_kind cert-manager.io Issuer; then
  missing_kinds="$missing_kinds Issuer.cert-manager.io"
fi
if [ -n "$missing_kinds" ]; then
  printf 'The cluster does not serve:%s\n' "$missing_kinds" >&2
  printf 'This file uses these kinds and does not define them. Install what defines them, then re-run this script. Nothing was applied.\n' >&2
  exit 1
fi

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

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 1 CRD this file holds"
missing_crds=0
if ! kubectl get crd/bundles.trust.cert-manager.io >/dev/null 2>&1; then
  missing_crds=1
fi
if [ "$missing_crds" -eq 1 ]; then
  say "The CRD is missing, so apply the file's CRD first"
  kubectl apply --server-side -f "$work/crds"
  crd_outcome="was applied first"
elif kubectl diff --server-side -f "$work/crds" >/dev/null 2>&1; then
  say "The CRD already exists and matches this file. The script leaves it under its current owner"
  crd_outcome="already existed and matched, so the script left it alone"
elif [ "${APPLY_CRDS:-0}" = "1" ]; then
  say "The existing CRD differs from this file. APPLY_CRDS=1 is set, so the script applies the file's CRD"
  kubectl apply --server-side -f "$work/crds"
  crd_outcome="differed and was applied, because APPLY_CRDS=1 was set"
else
  say "The CRD already exists and differs from this file, or another tool owns it"
  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 CRD, re-run with:
  APPLY_CRDS=1 bash try-objects.sh
EOF_CRDS
  exit 1
fi
wait_for_crd bundles.trust.cert-manager.io

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

say "Done. The 1 CRD $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'
   - The installer package includes these CRDs as prerequisites/target-facts/default-crds.yaml. Apply the missing CRDs server-side and leave existing CRDs under their current owner. The listing gives the rest.
   - Secret default/trust-manager-tls must exist before apply. trust-manager admission webhook TLS material normally produced by the rendered cert-manager Certificate lifecycle.
   - 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
