#!/bin/bash

K="$(which kubectl)"

if [[ -z "$K" ]]; then
  echo '* УТИЛИТА KUBECTL НЕ НАЙДЕНА' >&2
  exit 1
fi

if ! $K cluster-info >/dev/null 2>&1; then
  echo '* ОШИБКА ПОДКЛЮЧЕНИЯ К КЛАСТЕРУ. ПРОВЕРЬТЕ НАЛИЧИЕ И СОДЕРЖАНИЕ ФАЙЛА ~/.kube/config'
  exit 1
fi

H="$(which helm)"

if [[ -z "$H" ]]; then
  echo '* УТИЛИТА HELM НЕ НАЙДЕНА' >&2
  exit 1
fi

CURL="$(which curl)"

if [[ -z "$CURL" ]]; then
  echo '* УТИЛИТА CURL НЕ НАЙДЕНА' >&2
  exit 1
fi

SED="$(which gsed 2>/dev/null || which sed)"

if [[ -z "$SED" ]]; then
  echo '* УТИЛИТА SED НЕ НАЙДЕНА' >&2
  exit 1
fi

B64="$(which gbase64 || which base64)"

if [[ -z "$B64" ]]; then
  echo '* УТИЛИТА BASE64 НЕ НАЙДЕНА' >&2
  exit 1
fi

TMP_FILE="$(mktemp 2>/dev/null)"

if [[ -z "$TMP_FILE" ]] || [[ ! -f "$TMP_FILE" ]]; then
  echo '* НЕВОЗМОЖНО СОЗДАТЬ ВРЕМЕННЫЙ ФАЙЛ' >&2
  exit 1
fi

ARCH="$(uname -m)"

if [[ "$ARCH" != 'arm64' ]]; then
  ARCH='amd64'
fi

SNAME="$(uname -s|tr 'A-Z' 'a-z')"

set -e

. setup_comita_aml.conf

if ! $K get sc local-path >/dev/null 2>&1; then
  echo '* LOCAL-PATH КЛАСС ХРАНИЛИЩА НЕ НАЙДЕН' >&2
  exit 1
fi

if ! $K get ingressclass nginx >/dev/null 2>&1; then
  echo '* INGRESS NGINX НЕ НАЙДЕН. УСТАНОВКА...'
  helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
  helm repo update
  helm upgrade -i -n kube-system ingress-nginx ingress-nginx/ingress-nginx
  echo '* INGRESS NGINX УСПЕШНО УСТАНОВЛЕН'
fi

if ! $H -n vault get metadata vault >/dev/null 2>&1; then
  echo '* VAULT НЕ НАЙДЕН. УСТАНОВКА...'
  VAULT_LAST_REPLICA=$((VAULT_REPLICAS-1))
  $H repo add hashicorp https://helm.releases.hashicorp.com
  $H repo update
  $H upgrade -i -n vault --create-namespace vault --set server.ha.enabled=true,server.ha.raft.enabled=true,server.ha.replicas=3 hashicorp/vault

  for I in $(seq 0 $TIMEOUT); do
    OK=0

    if [[ $((I%10)) -eq 0 ]]; then
      echo '* ОЖИДАНИЕ ЗАПУСКА VAULT ПОДОВ'
    fi

    for II in $(seq 0 $VAULT_LAST_REPLICA); do
      if [[ "$($K -n vault get po vault-$II -o jsonpath='{.status.containerStatuses[0].started}')" == 'true' ]]; then
        OK=$((OK+1))
      fi
    done

    if [[ $OK -eq $VAULT_REPLICAS ]]; then
      break
    else
      sleep 1
    fi
  done

  $K -n vault exec -i vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > "$TMP_FILE"
  VAULT_UNSEAL_KEY="$(grep -A1 '\x22unseal_keys_b64\x22:' """$TMP_FILE"""|$SED -rn 's/^\s+?\x22(.+?)\x22$/\1/p'|tr -d '\r\n')"
  VAULT_ROOT_TOKEN="$($SED -rn 's/^\s+?\x22root_token\x22:\s+?\x22(.+?)\x22$/\1/p' """$TMP_FILE"""|tr -d '\r\n')"
  $K -n vault create secret generic vault --from-literal="unseal_key=$VAULT_UNSEAL_KEY" --from-literal="root_token=$VAULT_ROOT_TOKEN"
  $K -n vault exec -it vault-0 -- vault operator unseal "$VAULT_UNSEAL_KEY"

  if [[ $VAULT_LAST_REPLICA -gt 0 ]]; then
    for I in $(seq 1 $VAULT_LAST_REPLICA); do
      $K -n vault exec -it vault-$I -- vault operator raft join http://vault-0.vault-internal:8200
      $K -n vault exec -it vault-$I -- vault operator unseal "$VAULT_UNSEAL_KEY"
    done
  fi

  echo "$VAULT_ROOT_TOKEN"|$K -n vault exec -i vault-0 -- vault login token=-
  $K -n vault exec -it vault-0 -- vault auth enable kubernetes
  $K -n vault exec -i vault-0 -- ash -c 'vault write auth/kubernetes/config kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"'
  echo -e 'path "secret/*" {\n  capabilities = ["create", "read", "update", "delete", "list"]\n}'|$K -n vault exec -i vault-0 -- vault policy write aml -
  $K -n vault exec -it vault-0 -- vault secrets enable -path=secret kv-v2
  $K -n vault exec -it vault-0 -- vault write auth/kubernetes/role/aml bound_service_account_names=vault bound_service_account_namespaces='*' policies=aml ttl=3650d
  $H upgrade -n vault -i --set name=vault-unsealer --set image.repository=infra-harbor.comita.sel:80/library/operation/docker/vault-unsealer vault-unsealer vault-unsealer
  echo '* VAULT УСПЕШНО УСТАНОВЛЕН'
fi

if ! $H -n minio get metadata minio >/dev/null 2>&1; then
  echo '* MINIO НЕ НАЙДЕН. УСТАНОВКА...'
  $H repo add minio-operator https://operator.min.io
  $H repo update
  $H upgrade -i -n minio --create-namespace minio minio-operator/operator
  $K apply -f - <<EOF
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: console-sa-secret
  namespace: minio
  annotations:
    kubernetes.io/service-account.name: console-sa
EOF
  MINIO_OPERATOR_JWT="$($K -n minio get secret console-sa-secret -o jsonpath='{.data.token}'|$B64 -d|tr -d '\r\n')"
  mkdir -p bin
  export PATH="$PWD/bin:$PATH"

  if [[ ! -f 'bin/kubectl-minio' ]]; then
    TRY=0

    while sleep 1; do
      if ! $CURL -skL "https://github.com/minio/operator/releases/download/v5.0.14/kubectl-minio_5.0.14_${SNAME}_$ARCH" > bin/kubectl-minio; then
        if [[ $TRY -eq $CURL_TRYS ]]; then
          echo '* НЕ УДАЛОСЬ ЗАГРУЗИТЬ KUBECTL MINIO ПЛАГИН'
          exit 1
        else
          TRY=$((TRY+1))
        fi
      else
        break
      fi
    done
  fi

  if [[ ! -f 'bin/mc' ]]; then
    TRY=0

    while sleep 1; do
      if ! $CURL -skL "https://dl.min.io/client/mc/release/$SNAME-$ARCH/mc" > bin/mc; then
        if [[ $TRY -eq $CURL_TRYS ]]; then
          echo '* НЕ УДАЛОСЬ ЗАГРУЗИТЬ MINIO КЛИЕНТ'
          exit 1
        else
          TRY=$((TRY+1))
        fi
      else
        break
      fi
    done
  fi

  chmod +x bin/*
  while ! $K get deploy -n minio minio-operator >/dev/null 2>&1; do sleep 1; done
  MINIO_OPERATOR_SPEC_REPLICAS="$($K get deploy -n minio minio-operator -o jsonpath='{.spec.replicas}')"

  for I in $(seq 0 $TIMEOUT); do
    if [[ $((I%10)) -eq 0 ]]; then
      echo '* ОЖИДАНИЕ ЗАПУСКА MINIO ОПЕРАТОРОВ'
    fi

    MINIO_OPERATOR_READY_REPLICAS="$($K get deploy -n minio minio-operator -o jsonpath='{.status.readyReplicas}')"

    if [[ -n "$MINIO_OPERATOR_READY_REPLICAS" ]] && [[ $MINIO_OPERATOR_SPEC_REPLICAS -eq $MINIO_OPERATOR_READY_REPLICAS ]]; then
      break
    else
      sleep 1
    fi
  done

  $K minio tenant create aml-minio-tenant -o -n minio -s local-path --disable-tls --servers $MINIO_REPLICAS --volumes-per-server 2 --capacity 16Ti|$SED -r '/^\s+?creationTimestamp: null$/d' > "$TMP_FILE"
  $K apply -f "$TMP_FILE"
  MINIO_CREDS_B64="$($SED -rn 's/^\s+?CONSOLE_(ACCESS|SECRET)_KEY:\s+(.+?)$/\2/p' """$TMP_FILE"""|tr '\n' '|')"
  rm -f "$TMP_FILE"
  MINIO_ACCESS_KEY="$(echo -n """$MINIO_CREDS_B64"""|cut -d '|' -f1|$B64 -d)"
  MINIO_SECRET_KEY="$(echo -n """$MINIO_CREDS_B64"""|cut -d '|' -f2|$B64 -d)"
  while ! $K get statefulset -n minio aml-minio-tenant-ss-0 >/dev/null 2>&1; do sleep 1; done
  MINIO_TENANT_SPEC_REPLICAS="$($K get statefulset -n minio aml-minio-tenant-ss-0 -o jsonpath='{.spec.replicas}')"

  for I in $(seq 0 $TIMEOUT); do
    if [[ $((I%10)) -eq 0 ]]; then
      echo '* ОЖИДАНИЕ ЗАПУСКА MINIO ТЕНАНТОВ'
    fi

    MINIO_TENANT_READY_REPLICAS="$($K get statefulset -n minio aml-minio-tenant-ss-0 -o jsonpath='{.status.readyReplicas}')"

    if [[ -n "$MINIO_TENANT_READY_REPLICAS" ]] && [[ $MINIO_TENANT_SPEC_REPLICAS -eq $MINIO_TENANT_READY_REPLICAS ]]; then
      break
    else
      sleep 1
    fi
  done

  $K port-forward -n minio svc/aml-minio-tenant-hl 9000:9000 & AMT_FWD_PID=$!
  while ! mc alias set kube-minio http://127.0.0.1:9000 "$MINIO_ACCESS_KEY" "$MINIO_SECRET_KEY" >/dev/null 2>&1; do sleep 1; done
  while ! mc ls kube-minio/ >/dev/null 2>&1; do sleep 1; done

  for SECRETJSON in vault_download/*.json; do
    BUCKET_NAME="$($SED -rn 's/\s+?\x22storage\.minio\.bucket\.name\x22:\s+?\x22(.+?)\x22,?$/\1/p' """$SECRETJSON"""|tail -1|tr -d '\r\n')"

    if [[ -n "$BUCKET_NAME" ]]; then
      mc mb "kube-minio/$BUCKET_NAME"
    fi
  done

  mc cp "$PERMISSIONS_FILE_PATH" kube-minio/authad/init/permissions/
  kill -TERM $AMT_FWD_PID
  echo '* MINIO УСПЕШНО УСТАНОВЛЕН'
fi

$K create secret tls aml-tls --cert="$HTTPS_CERT" --key="$HTTPS_KEY"

echo -e 'JWT KEY\nIT\nORG\nNULL\nNULL\nRU\nyes\nsecret'| \
  $K run -i --rm --image=bellsoft/liberica-openjdk-alpine:17 keytool -- ash -c 'keytool -genkey -alias alias -keyalg RSA -keystore jwt.keystore -keysize 2048 -storepass secret -storetype JKS; cat jwt.keystore'| \
  $B64 -w0| \
  $K exec -in vault vault-0 -- vault kv put -mount=secret jwt keystore=-
