#!/usr/bin/env bash

script_path=`dirname "$0"`
script_path=`cd "$script_path"; pwd`

function log() {
  echo -e $1 2>&1 | tee -a $log_path
}

function prepare() {
  # disable firewalld, You can also enable firewalld and allow the ports used by k8s
  sudo systemctl stop firewalld
  sudo systemctl disable firewalld

  # disable selinux, selinux may interfere with the normal functioning of Kubernetes
  log "Current SELinux Mode: $(getenforce)"
  # Set SELinux permissive mode
  if [ $(getenforce) == "Enforcing" ];then
    sudo setenforce 0
    sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
    log "Disable selinux, New SELinux Mode: $(getenforce)"
  fi

  # swap off, otherwise it maybe cause resource limit error
  sudo swapoff -a
  sudo sed -i '/ swap / s/^/#/' /etc/fstab

  # todo list, ntpdate should exists and host can connect to internet
  if ! which ntpdate 2>&1 > /dev/null; then
    log "install ntpdate command"
    yum localinstall -y $script_path/ntpdate/*.rpm
  fi
  ntpdate -u ntp1.aliyun.com

  # ===================================================
  # Container install and configure prerequisites
  # ref: https://kubernetes.io/docs/setup/production-environment/container-runtimes/
  # Forwarding IPv4 and letting iptables see bridged traffic
  cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

  sudo modprobe overlay
  sudo modprobe br_netfilter

  # sysctl params required by setup, params persist across reboots
  cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

  # Apply sysctl params without reboot
  sudo sysctl --system

  # Verify that the br_netfilter, overlay modules are loaded
  lsmod | grep br_netfilter
  lsmod | grep overlay
  # Verify that the following system variables are set to 1
  sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

  # opensearch需要设置vm.max_map_count>=262144
  min_value=262144
  current_value=$(sysctl -n vm.max_map_count)
  if (( $current_value < $min_value )); then
      # check /etc/sysctl.conf exists vm.max_map_count config
      if grep -q "vm.max_map_count" /etc/sysctl.conf; then
          sed -i "s/^vm.max_map_count =.*/vm.max_map_count = $min_value/" /etc/sysctl.conf
      else
          echo "vm.max_map_count = $min_value" >> /etc/sysctl.conf
      fi
      sysctl -p
  fi
}

function install_containerd() {
  yum localinstall -y $script_path/docker/*.rpm
  # using other solution, because of kubeadm init image-repository
  #containerd config default > /etc/containerd/config.toml
  # change sandbox
  #sed -i 's#sandbox_image = "registry.k8s.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6"#g' /etc/containerd/config.toml
  # change systemd cgroup
  #sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml
  sudo cp -f $script_path/config.toml /etc/containerd/config.toml
  sudo systemctl start containerd && systemctl enable containerd
  # cp nerdctl tool
  sudo chmod 755 $script_path/docker/nerdctl
  sudo cp $script_path/docker/nerdctl /usr/bin/nerdctl
}

function install_registry() {
  # docker used as backend service
  if docker ps |grep "registry:2" |grep -v grep >/dev/null; then
    log "docker registry is already running."
  else
    cat << EOF | sudo tee /etc/docker/daemon.json
{
  "registry-mirrors": [
     "http://registry.mydp.io:5000",
     "https://hub-mirror.c.163.com",
     "https://docker.mirrors.ustc.edu.cn",
     "https://registry.docker-cn.com"
   ],
   "insecure-registries": ["registry.mydp.io:5000"],
   "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
    sudo systemctl start docker && systemctl enable docker
    # import offline registry package
    sudo docker load -i $script_path/docker/registry.tar
    # start registry
    sudo docker run -d --name registry -p 5000:5000 --restart always \
        -v /opt/docker/registry2:/var/lib/registry registry:2
    # load k8s_mirror to registry
    sudo docker load -i $script_path/k8s/k8s_mirror.tar
    sudo docker push registry.mydp.io:5000/k8s_containers/kube-apiserver:v1.26.5
    sudo docker push registry.mydp.io:5000/k8s_containers/kube-controller-manager:v1.26.5
    sudo docker push registry.mydp.io:5000/k8s_containers/kube-scheduler:v1.26.5
    sudo docker push registry.mydp.io:5000/k8s_containers/kube-proxy:v1.26.5
    sudo docker push registry.mydp.io:5000/k8s_containers/etcd:3.5.6-0
    sudo docker push registry.mydp.io:5000/k8s_containers/pause:3.9
    sudo docker push registry.mydp.io:5000/k8s_containers/coredns:v1.9.3
  fi
}

function kube_reset() {
  log "start execute kubeadm reset, non-first installation"
  kubeadm reset -f
  iptables -X && iptables -F
  if which ipvsadm 2>&1 > /dev/null; then
    ipvsadm --clear
  fi
  rm -rf /etc/cni/net.d
  rm -f $HOME/.kube/config
}

function install_k8smaster() {
  hostname="$1"
  svc_cidr="$2" # default: 10.96.0.0/12
  pod_cidr="$3" # default: 10.244.0.0/16
  sudo yum localinstall -y $script_path/k8s/worker/*.rpm
  sudo systemctl start kubelet
  sudo systemctl enable kubelet
  # Determine whether kubeadm reset needs to be executed
  if [ "$4" == "reset" ]; then
    kube_reset
  fi
  log "kubeadm init param: {host: $hostname, svc_subnet: $svc_cidr, pod_subnet: $pod_cidr}"
  # install master
  kubeadm init --kubernetes-version=1.26.5 \
        --apiserver-advertise-address=$hostname \
        --image-repository=registry.mydp.io:5000/k8s_containers \
        --service-cidr=$svc_cidr \
        --pod-network-cidr=$pod_cidr
  # make sure kubectl available
  if [ $? -eq 0 ]; then
    echo "kubeadm init success, config kubectl"
    mkdir -p $HOME/.kube
    sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  fi

}

function install_k8sworker() {
  sudo yum localinstall -y $script_path/k8s/worker/*.rpm
  sudo systemctl start kubelet
  sudo systemctl enable kubelet
  sudo systemctl status kubelet

  # Determine whether kubeadm reset needs to be executed, before kubeadm join
  if [ "$1" == "reset" ]; then
    kube_reset
  fi
}

function install_flannel() {
  pod_cidr="$1"
  sudo sed -i 's#"Network": ".*"#"Network": "'"$pod_cidr"'"#g' $script_path/kube-flannel.yml
  kubectl apply -f $script_path/kube-flannel.yml
  # node not ready, restart here?
  sudo systemctl restart containerd
}

function install_ingress() {
    kubectl apply -f $script_path/ingress-nginx.yaml
}

function kube_token() {
  kubeadm token create --print-join-command --ttl=24h
}

function kube_join() {
  kubeadm join "$@"
  # node not ready, restart here?
  sudo systemctl restart containerd
}

if [ "$1" == "container" ]; then
  prepare
  install_containerd
elif [ "$1" == "registry" ]; then
  install_registry
elif [ "$1" == "master" ]; then
  prepare
  install_containerd
  install_k8smaster $2 $3 $4 $5
  install_flannel $4
  install_ingress
elif [ "$1" == "worker" ]; then
  prepare
  install_containerd
  install_k8sworker $2
elif [ "$1" == "token" ]; then
  kube_token
elif [ "$1" == "join" ]; then
  kube_join $2 $3 $4 $5 $6
else
  echo "Usage: $0 <container | registry | master ip svc_cidr pod_cidr | worker>"
fi