#!/bin/bash

# Script para configurar el nodo master de Kubernetes en Oracle Linux 9.4 (ol9.4)

# Salir inmediatamente si ocurre un error
set -e

# Funciones para mostrar mensajes
echo_info() {
    echo -e "\e[32m[INFO]\e[0m $1"
}

echo_error() {
    echo -e "\e[31m[ERROR]\e[0m $1" >&2
}

# Obtener el usuario que ejecuta el script
if [ "$SUDO_USER" ]; then
    ORIGINAL_USER="$SUDO_USER"
else
    ORIGINAL_USER=$(whoami)
fi

# Obtener el directorio home del usuario original
USER_HOME=$(getent passwd "$ORIGINAL_USER" | cut -d: -f6)

# Verificar si se está ejecutando post-reinicio
if [ "$1" == "post-reboot" ]; then
    echo_info "=== Ejecutando pasos post-reinicio para configurar el clúster de Kubernetes ==="

    # Inicializar el clúster de Kubernetes
    echo_info "Inicializando el clúster de Kubernetes con kubeadm..."
    sudo kubeadm init --pod-network-cidr=10.244.0.0/16

    # Verificar si kubeadm init se ejecutó correctamente
    if [ $? -ne 0 ]; then
        echo_error "kubeadm init falló. Revisa los logs para más detalles."
        exit 1
    fi

    # Configurar kubectl para el usuario original
    echo_info "Configurando kubectl para el usuario $ORIGINAL_USER..."
    mkdir -p "$USER_HOME/.kube"
    sudo cp -i /etc/kubernetes/admin.conf "$USER_HOME/.kube/config"
    sudo chown "$ORIGINAL_USER":"$ORIGINAL_USER" "$USER_HOME/.kube/config"

    # Verificar la existencia de admin.conf
    if [ ! -f /etc/kubernetes/admin.conf ]; then
        echo_error "El archivo /etc/kubernetes/admin.conf no se encontró. Asegúrate de que kubeadm init se ejecutó correctamente."
        exit 1
    fi

    # Instalar Flannel como red de pods ejecutando kubectl como el usuario original
    echo_info "Instalando Flannel como red de pods..."
    sudo -u "$ORIGINAL_USER" kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

    # Esperar a que el DaemonSet de Flannel esté desplegado correctamente
    echo_info "Esperando a que el DaemonSet de Flannel esté desplegado correctamente..."
    sudo -u "$ORIGINAL_USER" kubectl rollout status daemonset/kube-flannel-ds -n kube-flannel --timeout=120s || {
        echo_error "Timeout esperando que el DaemonSet de Flannel esté desplegado."
        exit 1
    }

    # Verificar el estado de los nodos
    echo_info "Verificando el estado de los nodos..."
    sudo -u "$ORIGINAL_USER" kubectl get nodes

    # Generar el comando de unión y guardarlo en un archivo
    echo_info "Generando el comando de unión para los nodos worker..."
    JOIN_COMMAND=$(sudo kubeadm token create --print-join-command)
    echo "$JOIN_COMMAND" | sudo tee /etc/kubernetes/join_command.sh
    sudo chmod +x /etc/kubernetes/join_command.sh
    echo_info "El comando de unión ha sido guardado en /etc/kubernetes/join_command.sh"

    # Imprimir el comando de unión al usuario
    echo_info "El comando de unión para los nodos worker es:"
    echo_info "$JOIN_COMMAND"

    # Pausa para permitir al usuario desplegar los nodos worker
    echo_info "Ahora puedes desplegar los nodos worker utilizando el comando de unión proporcionado."
    echo_info "Presiona Enter una vez que hayas desplegado los nodos worker para continuar con la instalación de Prometheus y Grafana..."
    read -rp ">> Presiona Enter para continuar: " < /dev/tty

    # Modificar secure_path en sudoers para incluir /usr/local/bin
    echo_info "Modificando secure_path en sudoers para incluir /usr/local/bin..."
    # Usar sed para reemplazar la línea existente de secure_path o agregarla si no existe
    if sudo grep -q "^Defaults\s\+secure_path" /etc/sudoers; then
        sudo sed -i 's@^Defaults\s\+secure_path\s*=.*@Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"@' /etc/sudoers
    else
        echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' | sudo tee /etc/sudoers.d/secure_path
    fi
    echo_info "secure_path ha sido actualizado en sudoers."

    exit 0
fi

# Función para manejar la deshabilitación de SELinux de forma condicional
disable_selinux() {
    echo_info "Verificando el estado de SELinux..."
    if sestatus | grep "SELinux status:" | grep "enabled" > /dev/null 2>&1; then
        echo_info "SELinux está habilitado. Deshabilitándolo..."
        sudo setenforce 0 || echo_info "SELinux ya está en modo permisivo."
        sudo sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
        echo_info "SELinux deshabilitado."
    else
        echo_info "SELinux ya está deshabilitado."
    fi
}

# Verificar si se está ejecutando la primera parte del script
echo_info "Ejecutando pasos iniciales para configurar el nodo master de Kubernetes..."

# Actualizar el sistema
echo_info "Actualizando el sistema..."
sudo yum update -y || sudo dnf update -y

# Instalar herramientas necesarias
echo_info "Instalando herramientas necesarias..."
sudo yum install -y wget vim git curl || sudo dnf install -y wget vim git curl

# Descargar y configurar etcd
ETCD_VERSION="v3.4.34"
ETCD_ARCHIVE="etcd-${ETCD_VERSION}-linux-amd64.tar.gz"
ETCD_URL="https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/${ETCD_ARCHIVE}"

echo_info "Descargando etcd..."
wget ${ETCD_URL}

echo_info "Extrayendo etcd..."
tar zxvf ${ETCD_ARCHIVE}

echo_info "Moviendo binarios de etcd a /usr/bin..."
cd etcd-${ETCD_VERSION}-linux-amd64
sudo mv etcd /usr/bin
sudo mv etcdctl /usr/bin

echo_info "Configurando directorio de etcd..."
sudo mkdir -p /var/lib/etcd
sudo groupadd --system etcd || echo_info "Grupo 'etcd' ya existe."
sudo useradd -s /sbin/nologin --system -g etcd etcd || echo_info "Usuario 'etcd' ya existe."
sudo chown -R etcd:etcd /var/lib/etcd/

cd ..

# Desactivar swap
echo_info "Desactivando swap..."
sudo swapoff -a

echo_info "Eliminando swap del archivo /etc/fstab..."
sudo sed -i '/swap/d' /etc/fstab

# Configurar módulos y sysctl para Kubernetes
echo_info "Configurando módulos para Kubernetes..."
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

echo_info "Configurando parámetros de sysctl para Kubernetes..."
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

echo_info "Aplicando configuraciones de sysctl..."
sudo sysctl --system

# Instalar containerd
echo_info "Añadiendo repositorio de Docker..."
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo

echo_info "Instalando containerd.io..."
sudo dnf install -y containerd.io

echo_info "Habilitando y arrancando containerd..."
sudo systemctl enable containerd --now

# Configurar repositorio de Kubernetes
echo_info "Configurando repositorio de Kubernetes..."
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
EOF

# Actualizar repositorios
echo_info "Actualizando repositorios de Kubernetes..."
sudo yum update -y || sudo dnf update -y

# Instalar kubelet, kubeadm y kubectl
echo_info "Instalando kubelet, kubeadm y kubectl..."
sudo dnf install -y kubelet kubeadm kubectl

echo_info "Habilitando y arrancando kubelet..."
sudo systemctl enable kubelet --now

# Cargar módulo br_netfilter
echo_info "Cargando módulo br_netfilter..."
sudo modprobe br_netfilter

echo_info "Verificando que br_netfilter esté cargado..."
lsmod | grep br_netfilter || { echo_error "br_netfilter no está cargado"; exit 1; }

# Asegurar que br_netfilter se cargue al inicio
echo_info "Asegurando que br_netfilter se cargue al inicio..."
echo "br_netfilter" | sudo tee /etc/modules-load.d/k8s.conf

# Configurar sysctl nuevamente por si hubo cambios
echo_info "Configurando sysctl para Kubernetes..."
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

echo_info "Aplicando configuraciones de sysctl..."
sudo sysctl --system

# Deshabilitar SELinux
echo_info "Deshabilitando SELinux..."
disable_selinux

# Configurar containerd
echo_info "Generando configuración por defecto de containerd..."
sudo containerd config default | sudo tee /etc/containerd/config.toml

echo_info "Configurando SystemdCgroup en containerd..."
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

echo_info "Reiniciando containerd para aplicar cambios..."
sudo systemctl restart containerd

# Modificar secure_path en sudoers para incluir /usr/local/bin
echo_info "Modificando secure_path en sudoers para incluir /usr/local/bin..."
# Usar sed para reemplazar la línea existente de secure_path o agregarla si no existe
if sudo grep -q "^Defaults\s\+secure_path" /etc/sudoers; then
    sudo sed -i 's@^Defaults\s\+secure_path\s*=.*@Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"@' /etc/sudoers
else
    echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' | sudo tee /etc/sudoers.d/secure_path
fi
echo_info "secure_path ha sido actualizado en sudoers."

# Mensaje antes del reinicio
echo_info "Todos los pasos iniciales han sido completados."
echo_info "El sistema se reiniciará ahora para aplicar todas las configuraciones."
echo_info "Después del reinicio, debes ejecutar este script nuevamente con el parámetro 'post-reboot' para finalizar la configuración del clúster."
echo_info "Presiona Enter para continuar y reiniciar el sistema..."
read -rp ">> Presiona Enter para continuar: " < /dev/tty

# Reboot del sistema para aplicar todos los cambios
echo_info "Reiniciando el sistema para aplicar todas las configuraciones..."
sudo reboot

