#!/usr/bin/env bash
#
# Copyright 2026 Datastrato Inc.
#
# Collect diagnostics from a Datastrato Enterprise install into one archive
# for a support ticket.
#
# Usage:
#   ./collect-diagnostics.sh                      # finds the release itself
#   RELEASE=my-release NAMESPACE=my-ns ./collect-diagnostics.sh
#
# Needs kubectl and helm pointed at the cluster, and read access to the
# release's namespace. Each step that fails is noted and the rest still run.

set -u

log() { printf '%s %s\n' "$(date +%H:%M:%S)" "$*"; }

for tool in kubectl helm tar; do
  if ! command -v "$tool" >/dev/null 2>&1; then
    echo "ERROR: $tool is not on PATH." >&2
    exit 1
  fi
done

# Find the release when RELEASE and NAMESPACE are not given: the release whose
# chart name starts with enterprise-helm.
if [ -z "${RELEASE:-}" ] || [ -z "${NAMESPACE:-}" ]; then
  FOUND=$(helm list -A --no-headers 2>/dev/null | awk '$0 ~ /enterprise-helm-/ {print $1" "$2}')
  COUNT=$(printf '%s\n' "$FOUND" | grep -c . || true)
  if [ "$COUNT" -ne 1 ]; then
    echo "ERROR: found $COUNT Datastrato Enterprise releases. Set RELEASE and NAMESPACE." >&2
    helm list -A 2>/dev/null >&2
    exit 1
  fi
  RELEASE=${RELEASE:-${FOUND%% *}}
  NAMESPACE=${NAMESPACE:-${FOUND##* }}
fi
log "Release $RELEASE in namespace $NAMESPACE"

OUT="diagnostics-$RELEASE-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUT"
FAILED=()

run() {
  # run FILE COMMAND...  writes stdout and stderr to $OUT/FILE
  local file=$1; shift
  if "$@" >"$OUT/$file" 2>&1; then
    log "  ok      $file"
  else
    log "  FAILED  $file (see the file for the error)"
    FAILED+=("$file")
  fi
}

log "Release, versions and values"
run helm-list.txt     helm list -n "$NAMESPACE"
run helm-history.txt  helm history "$RELEASE" -n "$NAMESPACE"
# Replace credential values: any key whose name contains password, secret,
# token, credential or key (except names, classes, paths, endpoints and Secret
# names), and the value of any environment variable whose name contains one.
REDACT_AWK='
{
  line = $0; lower = tolower(line)
  if (pending && lower ~ /^[ \t]*value:/) {
    sub(/value:.*/, "value: REDACTED", line); pending = 0; print line; next
  }
  pending = 0
  if (match(lower, /^[ \t]*-?[ \t]*name:[ \t]*/)) {
    v = substr(lower, RSTART + RLENGTH)
    if (v ~ /(password|secret|token|credential|key)/) pending = 1
  }
  if (line ~ /^[ \t]*(- )?[A-Za-z0-9_.-]+:[ \t]*[^ \t#]/) {
    k = line; sub(/^[ \t]*(- )?/, "", k); sub(/:.*/, "", k); lk = tolower(k)
    if (lk ~ /(password|secret|token|credential|key)/ && lk !~ /(name|class|file|path|ref|enabled|endpoint|uri|url|keys)$/ && lk != "existingsecret") {
      sub(/:[ \t].*/, ": REDACTED", line)
    }
  }
  print line
}
'
if helm get values "$RELEASE" -n "$NAMESPACE" -o yaml 2>"$OUT/values-error.txt" \
  | awk "$REDACT_AWK" > "$OUT/values-redacted.yaml"; then
  rm -f "$OUT/values-error.txt"
  log "  ok      values-redacted.yaml"
else
  log "  FAILED  values-redacted.yaml (see values-error.txt)"
  FAILED+=("values-redacted.yaml")
fi
run images.txt kubectl -n "$NAMESPACE" get pods -o \
  jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}'
run versions.txt sh -c "kubectl version 2>&1; echo; helm version"

log "Workloads, events and volumes"
run resources.txt      kubectl -n "$NAMESPACE" get all,pvc,ingress -o wide
run events.txt         kubectl -n "$NAMESPACE" get events --sort-by=.lastTimestamp
run pods-describe.txt  kubectl -n "$NAMESPACE" describe pods
run nodes.txt          kubectl get nodes -o wide

log "Container logs"
for POD in $(kubectl -n "$NAMESPACE" get pods -o name 2>/dev/null); do
  NAME=${POD#pod/}
  run "logs-$NAME.txt" kubectl -n "$NAMESPACE" logs "$POD" --all-containers --tail 2000
  if kubectl -n "$NAMESPACE" logs "$POD" --all-containers --previous --tail 2000 \
    >"$OUT/logs-$NAME-previous.txt" 2>/dev/null; then
    log "  ok      logs-$NAME-previous.txt"
  else
    rm -f "$OUT/logs-$NAME-previous.txt"
  fi
done

log "Server log, health and metrics"
SERVER="deploy/$RELEASE-gravitino"
if ! kubectl -n "$NAMESPACE" get "$SERVER" >/dev/null 2>&1; then
  SERVER="deploy/$RELEASE"
fi
run gravitino-server.log kubectl -n "$NAMESPACE" exec "$SERVER" -c gravitino -- \
  sh -c 'tail -n 5000 "${GRAVITINO_LOG_DIR:-/opt/gravitino/logs/$HOSTNAME}/gravitino-server.log"'
run health-ready.json kubectl -n "$NAMESPACE" exec "$SERVER" -c gravitino -- \
  curl -s http://localhost:8090/api/health/ready
run metrics.json kubectl -n "$NAMESPACE" exec "$SERVER" -c gravitino -- \
  curl -s http://localhost:8090/metrics

tar czf "$OUT.tar.gz" "$OUT"
log "Wrote $OUT.tar.gz ($(du -h "$OUT.tar.gz" | cut -f1))"
if [ ${#FAILED[@]} -gt 0 ]; then
  log "Steps that failed: ${FAILED[*]}"
fi
echo
echo "Before sending: check $OUT/values-redacted.yaml. Credentials stored under a name"
echo "without password, secret, token, credential or key in it are not redacted."
