#!/bin/bash
export TEXTDOMAINDIR='/usr/share/locale'
export TEXTDOMAIN='podsec-k8s'

export PROGRAMM=$0
if [ $USER != 'root' -o $(id -u) != 0 -o $(id -g) != 0 ]
then
  echo "$(gettext 'Script') $PROGRAMM $(gettext 'must be run as root user')" >&2
  exit 1
fi

source podsec-u7s-functions
source podsec-get-platform

getPlatform # Устанавливает переменную U7S_PLATFORM
installKubeadm # Устанавливает требуемую доступную версию kubeadm и переменную U7S_KUBEVERSION при ее отсутствии
setRegistryName # устанавливает имя регистратора образов в переменнную U7S_REGISTRY_PLATFORM
usermod -G kube -a u7s-admin

source /etc/podsec/u7s/env/u7s_flags

ifs=$IFS
getoptPars=$(formGetoptPars)

opts=$(getopt -n kubeadm $getoptPars -- "$@" 2>&1)
if [ ! $? ]  # Анализ параметров обнаружил ошибки
then
  echo $opts >&2
  exit 1
fi

set -- $opts
pars=""
haveHelpFlag=
while [ $# -gt 0 ]
do
  if [ $1 = '--' ]; then break; fi
  pars+=" $1"
  if [ $1 = '-h' -o $1 = '--help' ]
  then
    haveHelpFlag='y'
  fi
  shift
done
shift

nativeCommand=  # Команда передаваемая "родному" kubeadm
if [ $# -eq 0 ]
then
  nativeCommand="/usr/bin/kubeadm"
fi
eval cmd=$1
shift

subcommand=; while [ $# -gt 0 ]; do subcommand+="${1:1:-1} "; shift; done # Убрать лишние кавычки
if [ -n "$subcommand" ]
then
  subcommand=${subcommand:0:-1}
fi

if [ -n "$haveHelpFlag" ]
then
  nativeCommand="/usr/bin/kubeadm $cmd $subcommand -h"
  machinectl shell u7s-admin@ /usr/libexec/podsec/u7s/bin/nsenter_u7s $nativeCommand
  exit $?
fi

set -- $pars
U7S_KUBEADMFLAGS=
# Обработать общесистемные параметры
while [ $# -gt 0 ]
do
  par=${1:1}
  if [ ${par:0:1} == '-' ]
  then # long-параметр
    par=${par:1}
  fi
  eval ${KFLAGS[$par]}  # Установить переменную FLAG_xxxx
  shift
  if [ -z ${KFLAGSBOOLEAN[$par]} ]; then shift; fi  # LONG PARS - shift value
done

if [ $cmd != 'init' -a $cmd != 'join' ] # Команда ни init ни join
then
  nativeCommand="/usr/bin/kubeadm $cmd $subcommand $pars"
  machinectl shell u7s-admin@ /usr/libexec/podsec/u7s/bin/nsenter_u7s $nativeCommand
  exit $?
fi

# Обработать команд init, join

getKuberImages $(uname -m ) '/share/usernetes/containers/storage/' u7s-admin

etcdDataDir='/var/lib/podsec/u7s/etcd/member'
if [ -d  $etcdDataDir ]
then
  echo "$(gettext 'An etcd cluster data directory was found on the server') $etcdDataDir $(gettext 'from previous deployment. Clear directory? y/N'):" >&2
  read reply
  if [ "$reply" = 'y' ]
  then
    rm -rf $etcdDataDir
  else
    exit 1
  fi
fi
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/90-ipforward.conf


# controlPlane=
U7S_TOKEN=
caCertHash=
certificatesDir=
dnsDomain='cluster.local'
tokenTTL=
FileDiscovery=
bootstrapToken=
tlsBootstrapToken=

# Сформировать неподдержиывемые в kubeconf флаги и передать их флагами в родной kubeadm в переменной U7S_KUBEADMFLAGS
nonKubeconfFlags='
  v
  dry-run
  ignore-preflight-errors
  skip-certificate-key-print
  skip-token-print
  upload-certs
  discovery-token-unsafe-skip-ca-verification
'

for flag in $nonKubeconfFlags
do
  var="FLAG_$(echo $flag | sed -e 's/-/_/g')"
  eval "val=\$$var"
  if [ -n "$val" ] # Флаг $flag указан в параметрах
  then
    if [ ${#flag} -gt 1 ]
    then
      Flag="--$flag"
    else
      Flag="-$flag"
    fi
    if [ -n "${KFLAGSBOOLEAN[$flag]}" ] # булевый флаг (есть-нет)
    then
      U7S_KUBEADMFLAGS+=" $Flag"
    else
      U7S_KUBEADMFLAGS+=" $Flag $val"
    fi
  fi
done

if [ -z "$FLAG_apiserver_advertise_address" ]
then
  FLAG_apiserver_advertise_address=$(getExtIP)
fi
extDev=$(getExtDev $FLAG_apiserver_advertise_address)

# Обработать флаги init, join
if [ $cmd == 'init' ]
then
  controlPlane="initMaster"
  if [ -z "$FLAG_control_plane_endpoint" ]
  then
    FLAG_control_plane_endpoint="$FLAG_apiserver_advertise_address:$FLAG_apiserver_bind_port"
  fi
else # cmd = 'join'
  U7S_TOKEN=$FLAG_token
  FLAG_control_plane_endpoint=$subcommand
  caCertHash=$FLAG_discovery_token_ca_cert_hash
  if [ -n "$FLAG_control_plane" ]
  then
    controlPlane="master"
    certificateKey=$FLAG_certificate_key
  fi
fi

if [ -z "$FLAG_apiserver_bind_port" ]
then
  FLAG_apiserver_bind_port=6443
fi


if [ -z "$podNetworkCidr" ]
then
  : ${U7S_CNI_PLUGIN:=flannel}
  case $U7S_CNI_PLUGIN in
  flannel)
    podNetworkCidrIP='10.244.0.0'
    podNetworkMask='16';;
  calico)
    podNetworkCidrIP='192.168.0.0'
    podNetworkMask='16';;
  esac
  podNetworkCidr="$podNetworkCidrIP/$podNetworkMask"
fi
if [ -n "$FLAG_pod_network_cidr" ]
then
  getCidr $FLAG_pod_network_cidr
  podNetworkCidrIP=$CIDRIP
  podNetworkMask=$CIDRMASK
else
  : ${U7S_CNI_PLUGIN:=flannel}
  case $U7S_CNI_PLUGIN in
  flannel)
    podNetworkCidrIP='10.244.0.0'
    podNetworkMask='16';;
  calico)
    podNetworkCidrIP='192.168.0.0'
    podNetworkMask='16';;
  esac
  FLAG_pod_network_cidr="$podNetworkCidrIP/$podNetworkMask"
fi

if [ -n "$FLAG_pod_service_cidr" ]
then
  getCidr $FLAG_pod_service_cidr
  podNetworkCidrIP=$CIDRIP
  podNetworkMask=$CIDRMASK
  getCidr FLAG_pod_service_cidr
  serviceCidrIP=$CIDRIP
  serviceMask=$CIDRMASK
else
  serviceCidrIP='10.96.0.0'
  serviceMask='12'
  FLAG_pod_service_cidr="$serviceCidrIP/$serviceMask"
fi

uid=`id -u u7s-admin`

cp /etc/podsec/u7s/config/ENV /etc/podsec/u7s/config/env
envDir="$XDG_CONFIG_HOME=/var/lib/u7s-admin/.config/usernetes"
# Настройка использования образа $U7S_REGISTRY/U7S_PAUSE_IMAGE при запуска pod'ов в podman (podman pod init)
pause_image="$U7S_REGISTRY/$U7S_PAUSE_IMAGE"
echo "$(gettext 'Configuring image usage') $pause_image $(gettext 'when starting pods in podman (podman pod init)')" >&2
sed -i -e 's|#infra_image =.*|infra_image = "'$pause_image'"|' /usr/share/containers/containers.conf

kubernetesClusterIP=$(getKubernetesClusterIP $FLAG_pod_service_cidr)
kubernetesClusterDNS="${kubernetesClusterIP}0"
slirp4IP="${kubernetesClusterIP}00"

IFS=:
set -- $apiServerEndpoint
IFS=$ifs
apiServerEndpointIP=$1
apiServerEndpointPort=$2

U7S_EXTIP=$FLAG_apiserver_advertise_address

export U7S_PODNETWORKCIDRIP=$podNetworkCidrIP
export U7S_SERVICECIDR=$FLAG_pod_service_cidr
unset U7S_ARCHIMAGES

checkNetCrossing

echo  "
U7S_KUBEVERSION=$U7S_KUBEVERSION
U7S_KUBEADMFLAGS='$U7S_KUBEADMFLAGS'
U7S_PLATFORM=$U7S_PLATFORM
U7S_ALTREGISTRY=$U7S_ALTREGISTRY
U7S_REGISTRY=$U7S_REGISTRY
U7S_FLANNEL_REGISTRY=$U7S_FLANNEL_REGISTRY
U7S_FLANNEL_TAG=$U7S_FLANNEL_TAG
U7S_REGISTRY_PLATFORM=$U7S_REGISTRY_PLATFORM
U7S_IMAGES='$U7S_IMAGES'
U7S_PAUSE_IMAGE='$U7S_PAUSE_IMAGE'
U7S_UID=$uid
U7S_EXTIP=$U7S_EXTIP
U7S_APISERVER_ADVERTISE_ADDRESS=$FLAG_apiserver_advertise_address
U7S_APISERVER_BIND_PORT=$FLAG_apiserver_bind_port
U7S_EXTDEV=$extDev
U7S_CONTROLPLANE=$controlPlane
U7S_APISERVERENDPOINT=$FLAG_control_plane_endpoint
U7S_TOKEN=$FLAG_token
U7S_CACERTHASH=$FLAG_discovery_token_ca_cert_hash
U7S_CERIFICATEKEY=$FLAG_certificate_key
U7S_SERVICECIDR=$U7S_SERVICECIDR
U7S_SERVICECIDRIP=$serviceCidrIP
U7S_SERVICEMASK=$serviceMask
U7S_PODNETWORKCIDR=$FLAG_pod_network_cidr
U7S_PODNETWORKCIDRIP=$U7S_PODNETWORKCIDRIP
U7S_PODNETWORKMASK=$podNetworkMask
U7S_CNI_PLUGIN=$U7S_CNI_PLUGIN
U7S_ROOTLESSKIT_FLAGS=--cidr=$U7S_SERVICECIDR
U7S_KUBERNETESCLUSTERIP=$kubernetesClusterIP
U7S_KUBERNETESCLUSTERDNS=$kubernetesClusterDNS
U7S_SLIRP4IP=$slirp4IP
U7S_CONTROLPLANEENDPOINT=$controlPlaneEndpoint
U7S_SKIP_PHASES=$U7S_SKIP_PHASES
_CONTAINERS_ROOTLESS_UID=$uid
_CONTAINERS_USERNS_CONFIGURED=1
" >> /etc/podsec/u7s/config/env

kubeflannelYMLToALT $U7S_FLANNEL_REGISTRY $U7S_FLANNEL_TAG > /etc/kubernetes/manifests/kube-flannel.yml

mkdir -p /etc/kubernetes/audit
cp /etc//podsec/u7s/audit/policy.yaml /etc/kubernetes/audit
chown -R u7s-admin:u7s-admin /etc/kubernetes/audit

if ! /bin/grep u7s-admin /etc/subuid >/dev/null 2>&1
then
  # Сформировать /etc/subuid, /etc/subgid для системного user путем временного создания обычного пользователя
  /usr/sbin/useradd -M u7s_admin_temp
  /bin/sed -e 's/u7s_admin_temp/u7s-admin/' -i /etc/subuid
  /bin/sed -e 's/u7s_admin_temp/u7s-admin/' -i /etc/subgid
  /usr/sbin/userdel u7s_admin_temp
fi

mkdir -p /var/lib/crio/

# Чистим предыдущий конфиг kuber
rm -f /etc/kubernetes/*.conf \
  /etc/kubernetes/manifests/*.yaml \
  /etc/kubernetes/pki/*.??? \
  /etc/kubernetes/pki/etcd/*.??? 2>/dev/null

case $U7S_CNI_PLUGIN in
flannel)
  rm -rf /etc/cni
  # Copy CNI config to /etc/cni/net.d (Likely to be hardcoded in CNI installers)
  mkdir -p /etc/cni/net.d
  cp -f /etc/podsec/u7s/config/cni_net.d/* /etc/cni/net.d
  cp -f /etc/podsec/u7s/config/flannel/cni_net.d/* /etc/cni/net.d
  mkdir -p /run/flannel
  ;;
'calico')
  cp -f /etc/cni/net.d/100-crio-bridge.conflist.sample /etc/cni/net.d/100-crio-bridge.conflist
  ;;
esac

chown -R u7s-admin:u7s-admin /usr/libexec/cni /etc/cni/net.d/
if ! machinectl shell u7s-admin@ /bin/sh /usr/libexec/podsec/u7s/bin/kubeadm.sh $cmd 2>/dev/null
then
  echo "$(gettext 'Cluster deployment failed')." >&2
  echo "$(gettext 'Login as user u7s-admin'):" >&2
  echo "machinectl shell u7s-admin@ /bin/bash"
  echo "$(gettext 'and check the status with the command') 'systemctl --user u7s.service' $(gettext 'and system logs with command') journalctl" >&2
  pstree -pal
  exit 1
fi

# Настроить режим монтирования  /var/lib/kubelet
machinectl shell u7s-admin@ /usr/libexec/podsec/u7s/bin/nsenter_u7s mount --make-rshared /var/lib/kubelet/
machinectl shell u7s-admin@ /usr/libexec/podsec/u7s/bin/nsenter_u7s findmnt -o TARGET,PROPAGATION /var/lib/kubelet

# machinectl shell u7s-admin@ /sbin/systemctl --user start u7s.target 2>/dev/null
/sbin/systemctl enable  u7s.service
/sbin/systemctl start u7s.service

if [ -z "$controlPlane" ] # WORKER node
then
  exit 0
fi

adminConf="/etc/kubernetes/admin.conf"

if [ ! -s $adminConf ]
then
  echo "$(gettext 'The cluster administrator configuration file is not generated')!" >&2
  exit 2
fi

mkdir -p /root/.kube/
cp -f $adminConf /root/.kube/config
chmod 600 /root/.kube/config
chmod 700 /root/.kube/

# Запустить CNI plugin's
if [ "$controlPlane" = 'initMaster' ]
then
  	case $U7S_CNI_PLUGIN in
    'flannel')
      until kubectl apply -f /etc/kubernetes/manifests/kube-flannel.yml 2>/dev/null; do sleep 1; done
      ;;
    'calico')
      until kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/tigera-operator.yaml 2>/dev/null;  do sleep 1; done
      until kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/custom-resources.yaml 2>/dev/null;  do sleep 1; done
      ;;
    esac
fi

# Настроить в /kubernetes/manifests/kube-apiserver.yaml аудит API-запросов
tuneAudit
# Перезапустить сервисы
/sbin/systemctl stop u7s.service
/sbin/systemctl start u7s.service


mkdir -p ~u7s-admin/.kube/
cp -f $adminConf ~u7s-admin/.kube/config
chmod 600 ~u7s-admin/.kube/config
chmod 700 ~u7s-admin/.kube/
chown -R u7s-admin:u7s-admin ~u7s-admin/.kube
