# services/monitoring/oneoffs/grafana-user-dedupe-job.yaml
# One-off job for monitoring/grafana-user-dedupe-api-v8.
# Purpose: grafana user dedupe api v8 (see container args/env in this file).
# Run by setting spec.suspend to false, reconcile, then set it back to true.
# Safe to delete the finished Job/pod; it should not run continuously.
apiVersion: batch/v1
kind: Job
metadata:
  name: grafana-user-dedupe-api-v8
  namespace: monitoring
spec:
  suspend: true
  backoffLimit: 1
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/agent-pre-populate-only: "true"
        vault.hashicorp.com/role: "monitoring"
        vault.hashicorp.com/agent-inject-secret-grafana-env.sh: "kv/data/atlas/monitoring/grafana-admin"
        vault.hashicorp.com/agent-inject-template-grafana-env.sh: |
          {{ with secret "kv/data/atlas/monitoring/grafana-admin" }}
          export GRAFANA_USER="{{ index .Data.data "admin-user" }}"
          export GRAFANA_PASSWORD="{{ index .Data.data "admin-password" }}"
          {{ end }}
    spec:
      serviceAccountName: monitoring-vault-sync
      automountServiceAccountToken: true
      restartPolicy: Never
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: node-role.kubernetes.io/worker
                    operator: Exists
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              preference:
                matchExpressions:
                  - key: kubernetes.io/arch
                    operator: In
                    values: ["arm64"]
      containers:
        - name: dedupe
          image: registry.bstein.dev/bstein/python:3.12-slim
          command:
            - /bin/sh
            - -c
          args:
            - |
              set -eu
              for _ in $(seq 1 30); do
                if [ -f /vault/secrets/grafana-env.sh ]; then
                  break
                fi
                sleep 1
              done
              if [ ! -f /vault/secrets/grafana-env.sh ]; then
                echo "Vault secret not available"
                exit 1
              fi
              . /vault/secrets/grafana-env.sh
              grafana_url="${GRAFANA_URL}"
              if [ -z "${grafana_url}" ]; then
                echo "GRAFANA_URL is required"
                exit 1
              fi
              if [ -z "${GRAFANA_USER}" ] || [ -z "${GRAFANA_PASSWORD}" ]; then
                echo "Grafana admin credentials missing"
                exit 1
              fi
              if [ -z "${GRAFANA_DEDUPE_EMAILS}" ]; then
                echo "GRAFANA_DEDUPE_EMAILS is required"
                exit 1
              fi
              python - <<'PY'
              import base64
              import json
              import os
              import urllib.parse
              import urllib.error
              import urllib.request

              grafana_url = os.environ["GRAFANA_URL"].rstrip("/")
              user = os.environ["GRAFANA_USER"]
              password = os.environ["GRAFANA_PASSWORD"]
              lookups = [e.strip() for e in os.environ["GRAFANA_DEDUPE_EMAILS"].split(",") if e.strip()]

              token = base64.b64encode(f"{user}:{password}".encode("utf-8")).decode("utf-8")
              headers = {"Authorization": f"Basic {token}"}

              def request(method: str, url: str):
                  req = urllib.request.Request(url, headers=headers, method=method)
                  try:
                      with urllib.request.urlopen(req, timeout=10) as resp:
                          return resp.status, resp.read()
                  except urllib.error.HTTPError as err:
                      body = err.read()
                      return err.code, body

              for _ in range(60):
                  status, _ = request("GET", f"{grafana_url}/api/health")
                  if status == 200:
                      break
              else:
                  raise SystemExit("Grafana API did not become ready in time")

              for lookup in lookups:
                  search_url = f"{grafana_url}/api/users/search?query={urllib.parse.quote(lookup)}"
                  status, body = request("GET", search_url)
                  if status != 200:
                      print(f"search failed for {lookup}: status={status} body={body.decode('utf-8', errors='ignore')}")
                      continue
                  payload = json.loads(body)
                  users = payload.get("users", [])
                  matches = [
                      user
                      for user in users
                      if user.get("email", "").lower() == lookup.lower()
                      or user.get("login", "").lower() == lookup.lower()
                  ]
                  if not matches:
                      print(f"no grafana user found for {lookup}")
                      continue
                  for user in matches:
                      user_id = user.get("id")
                      if not user_id:
                          continue
                      print(f"deleting grafana user {user_id} ({user.get('email')})")
                      delete_url = f"{grafana_url}/api/admin/users/{user_id}"
                      del_status, del_body = request("DELETE", delete_url)
                      if del_status not in (200, 202, 204):
                          print(
                              "delete failed for",
                              user_id,
                              "status",
                              del_status,
                              "body",
                              del_body.decode("utf-8", errors="ignore"),
                          )
              PY
              echo "done"
          env:
            - name: GRAFANA_URL
              value: http://grafana.monitoring.svc.cluster.local
            - name: GRAFANA_DEDUPE_EMAILS
              value: brad.stein@gmail.com,brad@bstein.dev
