#!/bin/bash

# Do not exit with 1 since the server is working
die() { echo $@ >&2; exit 0; }

if [ $(CreoleGet hapy_init_k8s_service non) = 'non' ]
then
    die "kubernetes application disabled"
fi

echo "Initialise kubernetes... "

XPATH="/var/lib/one/remotes/datastore/xpath.rb"

K8S_APP="Kubernetes 1.23 - KVM"
IMAGE_DS=$(CreoleGet one_ds_image_name "default")
IMAGE_SIZE="$(CreoleGet hapy_k8s_service_disk_size 50)G"
CPU_RATIO=$(CreoleGet hapy_k8s_service_cpu_ratio 2)
VCPU_COUNT=$(CreoleGet hapy_k8s_service_vcpu_count 2)
MEMORY=$(CreoleGet hapy_k8s_service_memory 3072)
NETWORK_NAME=$(CreoleGet hapy_k8s_service_network_name)
NETWORK_UNAME=$(onevnet show -x "${NETWORK_NAME}" \
     | /var/lib/one/remotes/datastore/xpath.rb //UNAME | tr -d '\0')

NETWORK_TYPE=$(onevnet show -x "${NETWORK_NAME}" \
     | /var/lib/one/remotes/datastore/xpath.rb //AR/TYPE | tr -d '\0')

if [ -z "${NETWORK_TYPE}" ]
then
    die "Error: your network '${NETWORK_NAME}' must have IP address range, none defined."
elif [ "${NETWORK_TYPE}" = 'ETHER' ]
then
    die "Error: your network '${NETWORK_NAME}' must have IP address range instead of l2/ETHER one."
fi

VM_TEMPLATE='CONTEXT=[
  NETWORK="YES",
  ONEAPP_K8S_ADDRESS="$ONEAPP_K8S_ADDRESS",
  ONEAPP_K8S_ADMIN_USERNAME="$ONEAPP_K8S_ADMIN_USERNAME",
  ONEAPP_K8S_HASH="$ONEAPP_K8S_HASH",
  ONEAPP_K8S_LOADBALANCER_CONFIG="$ONEAPP_K8S_LOADBALANCER_CONFIG",
  ONEAPP_K8S_LOADBALANCER_RANGE="$ONEAPP_K8S_LOADBALANCER_RANGE",
  ONEAPP_K8S_NODENAME="$ONEAPP_K8S_NODENAME",
  ONEAPP_K8S_PODS_NETWORK="$ONEAPP_K8S_PODS_NETWORK",
  ONEAPP_K8S_PORT="$ONEAPP_K8S_PORT",
  ONEAPP_K8S_TAINTED_MASTER="$ONEAPP_K8S_TAINTED_MASTER",
  ONEAPP_K8S_TOKEN="$ONEAPP_K8S_TOKEN",
  REPORT_READY="$ONEGATE_ENABLE",
  SSH_PUBLIC_KEY="$USER[SSH_PUBLIC_KEY]",
  TOKEN="$ONEGATE_ENABLE" ]
CPU="##CPU_RATIO##"
DISK=[
  IMAGE="##K8S_APP##",
  IMAGE_UNAME="oneadmin" ]
GRAPHICS=[
  LISTEN="0.0.0.0",
  TYPE="vnc" ]
INPUTS_ORDER="ONEGATE_ENABLE,ONEAPP_K8S_ADDRESS,ONEAPP_K8S_TOKEN,ONEAPP_K8S_HASH,ONEAPP_K8S_NODENAME,ONEAPP_K8S_PORT,ONEAPP_K8S_TAINTED_MASTER,ONEAPP_K8S_PODS_NETWORK,ONEAPP_K8S_ADMIN_USERNAME,ONEAPP_K8S_LOADBALANCER_RANGE,ONEAPP_K8S_LOADBALANCER_CONFIG"
MEMORY="##MEMORY##"
NAME="##K8S_APP##"
NIC = [
  NETWORK = "##NETWORK_NAME##",
  NETWORK_UNAME = "##NETWORK_UNAME##",
  SECURITY_GROUPS = "0" ]
OS=[
  ARCH="x86_64" ]
USER_INPUTS=[
  ONEAPP_K8S_ADDRESS="O|text|Master node address/network (CIDR subnet)",
  ONEAPP_K8S_ADMIN_USERNAME="O|text|UI dashboard admin account (default admin-user)",
  ONEAPP_K8S_HASH="O|text|Secret hash (to join node into the cluster)",
  ONEAPP_K8S_LOADBALANCER_CONFIG="O|text64|Custom LoadBalancer config",
  ONEAPP_K8S_LOADBALANCER_RANGE="O|text|LoadBalancer IP range (default none)",
  ONEAPP_K8S_NODENAME="O|text|Master node name",
  ONEAPP_K8S_PODS_NETWORK="O|text|Pods network in CIDR (default 10.244.0.0/16)",
  ONEAPP_K8S_PORT="O|text|Kubernetes API port (default 6443)",
  ONEAPP_K8S_TAINTED_MASTER="O|boolean|Master node acts as control-plane only (default no)",
  ONEAPP_K8S_TOKEN="O|password|Secret token (to join node into the cluster)",
  ONEGATE_ENABLE="M|boolean|Enable OneGate reporting? (req. for multi-node)| |NO" ]
VCPU="##VCPU_COUNT##"'

FLOW_TEMPLATE='{
  "name": "##SERVICE_NAME##",
  "deployment": "straight",
  "description": "",
  "roles": [
    {
      "name": "master",
      "cardinality": 1,
      "vm_template": ##VM_TEMPLATE_ID##,
      "elasticity_policies": [],
      "scheduled_policies": []
    },
    {
      "name": "worker",
      "cardinality": 1,
      "vm_template": ##VM_TEMPLATE_ID##,
      "parents": [
        "master"
      ],
      "elasticity_policies": [],
      "scheduled_policies": []
    }
  ],
  "custom_attrs": {
    "ONEGATE_ENABLE": "M|boolean|Enable OneGate reporting? (req. for multi-node)| |YES"
  },
  "ready_status_gate": true
}'

# Must always exists
. /var/lib/one/remotes/scripts_common.sh

if ! oneimage show "${K8S_APP}" > /dev/null 2>&1
then
    # The image disk does not exist
    if onetemplate show "${K8S_APP}" > /dev/null 2>&1
    then
        echo -n "Remove VM template without disk image... "
        if onetemplate delete "${K8S_APP}"
        then
            echo "OK"
        else
            die "Error: unable to remove old '${K8S_APP}' template"
        fi
    fi

    echo "Import '${K8S_APP}' application from OpenNebula market... "
    if ! onemarketapp export --datastore "${IMAGE_DS}" "${K8S_APP}" "${K8S_APP}"
    then
        die "Error: unable to import '${K8S_APP}' from marketplace"
    fi

    echo -n "Waiting the download of image disk '${K8S_APP}'"
    START=$(date +%s)
    while :
    do
        NOW=$(date +s)
        if [ $(oneimage show "${K8S_APP}" | awk '/^STATE/ {print $3}') = 'lock' ]
        then
            if [ $(( NOW - START )) -gt 600 ]
            then
                die " too long waiting for image (10 minutes), image may be in error"
            fi

            echo -n "."
            sleep 2
        else
            echo " OK"
            break
        fi
    done
fi

TMP_TEMPLATE=$(mktemp --tmpdir vm-template.XXXXXX)
echo "${VM_TEMPLATE}" \
    | sed -e "s,##K8S_APP##,${K8S_APP}," \
          -e "s,##CPU_RATIO##,${CPU_RATIO}," \
          -e "s,##VCPU_COUNT##,${VCPU_COUNT}," \
          -e "s,##MEMORY##,${MEMORY}," \
          -e "s,##NETWORK_NAME##,${NETWORK_NAME}," \
          -e "s,##NETWORK_UNAME##,${NETWORK_UNAME}," \
          > "${TMP_TEMPLATE}"

if onetemplate show "${K8S_APP}" > /dev/null 2>&1
then
    echo -n "Update '${K8S_APP}' VM template... "
    if onetemplate update "${K8S_APP}" "${TMP_TEMPLATE}"
    then
        rm -f "${TMP_TEMPLATE}"
        echo "OK"
    else
        die "error"
    fi
else
    echo -n "Create ${K8S_APP} VM template... "
    if onetemplate create "${TMP_TEMPLATE}"
    then
        rm -f "${TMP_TEMPLATE}"
    else
        die "error"
    fi
fi

if CreoleGet activer_oneflow non | grep -qs oui \
   && CreoleGet activer_onegate non | grep -qs oui
then
    VM_TEMPLATE_ID=$(onetemplate show -x "${K8S_APP}" | ${XPATH} '//ID' | tr -d '\0')
    TMP_TEMPLATE=$(mktemp --tmpdir oneflow-template.XXXXXX)
    echo "${FLOW_TEMPLATE}" \
        | sed -e "s,##VM_TEMPLATE_ID##,${VM_TEMPLATE_ID}," \
              -e "s,##SERVICE_NAME##,${K8S_APP}," \
              > "${TMP_TEMPLATE}"

    if oneflow-template show "${K8S_APP}" > /dev/null 2>&1
    then
        echo -n "Update '${K8S_APP}' OneFlow service template... "
        if oneflow-template update "${K8S_APP}" "${TMP_TEMPLATE}"
        then
            rm -f "${TMP_TEMPLATE}"
            echo "OK"
        else
            die "error"
        fi
    else
        echo -n "Create '${K8S_APP}' OneFlow service template... "
        if oneflow-template create "${TMP_TEMPLATE}"
        then
            rm -f "${TMP_TEMPLATE}"
        else
            die "error"
        fi
    fi
fi
