#!/bin/bash
# This script will create kuberneties cluster and install ingress controller.

#set -x
#printenv | sort
#echo ; echo

# passing configuration file eg : az10-create_aks_cluster.sh  bnz-uat.conf | az10-create_aks_cluster.sh  bnz-prd.conf | az10-create_aks_cluster.sh tst.conf
path_script="$(readlink -f "$0")"
path_dir="${path_script%/*}"
source ${1:-$path_dir/az-dev.conf}
fn=`basename "$0"`

if [ -f "$2" ]; then #Local debug credentials in 2nd file not in git
  echo " ##!!!## source second file $2"
  source $2
  #
  if [[ "$DebugAZlogin" = true ]]; then
    echo "#$fn: az login --service-principal --username $SP_DEPLOY_ID --tenant $TENANT"
    az login  --service-principal \
              --username $SP_DEPLOY_ID \
              --password $SP_DEPLOY_SECRET \
              --tenant $TENANT
    echo "#$fn: az account set --subscription $SUBSCRIPTIONID"
    az account set --subscription $SUBSCRIPTIONID
  fi
fi


#Pick default pub ssh key if not set.
AKSCLUSTERSSHKEYPATH="${AKSCLUSTERSSHKEYPATH:-$path_dir/pub_key.pub}"

# check the resouces availability from az pipeline
# Optional: RESERVEDPUBIPADDR / RESERVEDPUBIPADDRNAME / (SKU set to Standard for LB and IP's)
for resource in TENANT SUBSCRIPTIONID AKSENVIRONMENT CH AKSCLUSTERNAME AKSCLUSTERNODECOUNT AKSCLUSTERADDONS RESOURCELOCATION ;
do
  if [ -z "${!resource}" ]; then
    echo "####$fn: $resource Not found. Check pipeline variables"
    exit 1;
  fi
done

aksResourceGroup=${AKSCLUSTERRESOURCEGROUP:-aks-$AKSCLUSTERNAME}

pubIPResGrp=${RESERVEDPUBIPRESOURCEGROUP:-$aksResourceGroup}
echo "####$fn:#### 1/2 get aks_pub_ip ,  then helm ingres with pub_ip ####"
# ip should have been created already by az_script-05, just retrieve ip.

aksClusterPubIPName=${RESERVEDPUBIPADDRNAME:-$AKSCLUSTERNAME-$AKSENVIRONMENT-ip-public}
if [ -z "$RESERVEDPUBIPADDRNAMEINGRESS" ]; then
    ## If Basic, use ip above , if Standard LB need seperate ingress ip
    aksClusterPubIPsku=$(az network public-ip show --resource-group $pubIPResGrp \
                                                  --name $aksClusterPubIPName \
                                                  --query sku \
                                                  --output tsv)
    rc=$? ; if [[ rc -ne 0 ]]; then echo "####$fn: rc=$rc Cluster IP should exist by now, cant find Ingress IP --name=$aksClusterPubIPName" ; exit 1 ; fi
    #IF Standard (not Basic) LB use seperate inbound and outbound ip's
    if [[ "$aksClusterPubIPsku" == "Standard" ]]; then
      echo "####$fn: sku=$aksClusterPubIPsku for $aksClusterPubIPName , use new seperate ip for Ingress , pubIPResGrp=$pubIPResGrp"
      aksClusterPubIngressIPName=$AKSCLUSTERNAME-$AKSENVIRONMENT-ip-pub-ingress
      ## Does ip exist ?
    else
      echo "####$fn: sku=$aksClusterPubIPsku for $aksClusterPubIPName, use same ip for ingress , pubIPResGrp=$pubIPResGrp"
      aksClusterPubIngressIPName=$aksClusterPubIPName
    fi
    #Sku Standard or Basic  (If not set use SKU retrieved from cluster IP)
    aksLbSku="${AKSCLUSTERLBSKU:-$aksClusterPubIPsku}"
else
    aksClusterPubIngressIPName=$RESERVEDPUBIPADDRNAMEINGRESS
    #Sku Standard or Basic
    aksLbSku="${AKSCLUSTERLBSKU:-Standard}"
    echo "####$fn: use env RESERVEDPUBIPADDRNAMEINGRESS=$aksClusterPubIngressIPName , pubIPResGrp=$pubIPResGrp"
fi

# get the pub ip address 1/2
aksClusterPubIP=$(az network public-ip show --resource-group $pubIPResGrp \
                                            --name $aksClusterPubIngressIPName \
                                            --query ipAddress \
                                            --output tsv)
rc=$?
if [[ rc -ne 0 ]]; then
    echo "####$fn: rc=$rc , couldn't find ip --name $aksClusterPubIngressIPName create it. sku=$aksClusterPubIPsku"
    if [[ "$aksClusterPubIPsku" == "Basic" ]]; then
        echo "####$fn: ERR wrong sku ? and no ip.  This should not happen."
        exit 1
    fi
    echo "####$fn: create ingress ip pubIPResGrp=$pubIPResGrp aksClusterPubIPName=$aksClusterPubIPName RESOURCELOCATION=$RESOURCELOCATION aksLbSku=$aksLbSku "
    az network public-ip create \
        --resource-group $pubIPResGrp \
        --name $aksClusterPubIngressIPName \
        --allocation-method static \
        --location $RESOURCELOCATION \
        --sku $aksLbSku
    # get the pub ip address 2/2 again
    aksClusterPubIP=$(az network public-ip show \
                        --resource-group $pubIPResGrp \
                        --name $aksClusterPubIngressIPName \
                        --query ipAddress \
                        --output tsv )
    rc=$?
    if [[ rc -ne 0 ]]; then
        echo "####$fn: ERROR: rc=$rc created ip , still cant get it aksClusterPubIngressIPName=$aksClusterPubIngressIPName ?"
        exit 1
    fi
fi
# query and check the pub ip address
if [ -z "$aksClusterPubIP" ]; then
  echo "####$fn: aksClusterPubIP can't be empty!!! Error on public IP creation"
  exit 1;
fi
echo "###$fn: ip for LB (ingress) - aksClusterPubIP=$aksClusterPubIP"
#Set lock on ingress ip if sku=Standard (2 ips)
if [[ "$aksClusterPubIPsku" == "Standard" ]]; then
        echo "####$fn: az lock show --name deleteLock-$aksClusterPubIngressIPName --resource-group $pubIPResGrp --resource-name $aksClusterPubIngressIPName --resource-type Microsoft.Network/publicIPAddresses -o table"
        #az lock show --name deleteLock-$aksClusterPubIPName --resource-group $aksResourceGroup -o table
        az lock show  --name deleteLock-$aksClusterPubIngressIPName \
                      --resource-group $pubIPResGrp \
                      --resource-name $aksClusterPubIngressIPName \
                      --resource-type Microsoft.Network/publicIPAddresses \
                      -o table
                      #--subscription "Non-Prod"
        rc=$?;
        if [[ $rc -ne 0 ]]; then
          # get the pub ip subscription id (used to add lock to pub ID below)
          aksClusterPubIpID=$(az network public-ip show --resource-group $pubIPResGrp \
                                                  --name $aksClusterPubIngressIPName \
                                                  --query id \
                                                  --output tsv)
          echo "####$fn: Adding Delete lock to $aksClusterPubIngressIPName along with $aksClusterPubIP using id $aksClusterPubIpID"
          az lock create  --name deleteLock-$aksClusterPubIngressIPName \
                          --lock-type CanNotDelete \
                          --resource $aksClusterPubIpID
        fi
fi

############################################################################
echo
echo "####$fn:#### 2/2 helm ingress deployment ###"
############################################################################
## moved az aks - credentials to create_aks_cluster step.
context=$(kubectl config current-context )
if [[ "$context" != "$AKSCLUSTERNAME" ]]; then
  echo "####$fn: ERR the current kubectl context not AKSCLUSTERNAME=$AKSCLUSTERNAME , it is $context"
  exit 1
fi

# check able to see the cluster
az aks show --name $AKSCLUSTERNAME --resource-group $aksResourceGroup --query name --output tsv | grep -o $AKSCLUSTERNAME
rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: aks $AKSCLUSTERNAME cluster not able to access"; exit $rc; fi

#Set INGRESSCOUNT to 0 to prevent creation
replicaCount=${INGRESSCOUNT:-2}

if [[ $replicaCount -ne 0 ]]; then
    echo "####$fn: create ingress crontroller, if it does not exist with correct ip and RG  replicaCount=$replicaCount , INGRESSCOUNT=$INGRESSCOUNT"
    echo "####$fn: replicaCount=$replicaCount get kube-system services"
    kubectlServices=$( kubectl --namespace kube-system get services -o wide )
    rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: ERROR: kubectl --namespace kube-system get services -o wide"; exit $rc; fi

    ingressName=$( echo "$kubectlServices" | grep -o "^.\+ingress-controller" )
    rct=$?
    if [[ $rct -eq 0 ]]; then
        echo "####$fn: found ingressName=$ingressName now describe it look for aksClusterPubIP=$aksClusterPubIP"
        ingressDescribe=$(kubectl --namespace kube-system describe service $ingressName )
        rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: ERROR: kubectl --namespace kube-system describe service $ingressName"; exit $rc; fi

        #Test for IP and RG
        echo "$ingressDescribe" | grep "$aksClusterPubIP" || echo "####$fn: can't find ip in ingress."
        (( rct += $? ))
        echo "$ingressDescribe" | grep "azure-load-balancer-resource-group:.*$pubIPResGrp" || echo "####$fn: can't find RG in ingress."
        ((rct += $? ))

    fi
    #See if there is a reason to deploy / redepoy ingress
    if [[ $rct -ne 0 ]]; then
        # echo "####$fn: got rct=$rct now helm deploy ingress, could not find aksClusterPubIP=$aksClusterPubIP or RG pubIPResGrp=$pubIPResGrp in Annotations"
        # kubConfigPath=$(ls $HOME/.kube/config)
        # maxTimeOut=1800
        # echo
        #     echo "####$fn: Download and install helm HELMVERSION=$HELMVERSION"
        #     if [[ $HELMVERSION =~ ^v2.*$ ]]; then
        #       echo "####$fn: curl download old v2 get_helm.sh and run ... HELMVERSION=\"$HELMVERSION\""
        #       curl -L -o get_helm.sh https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get
        #       helmv=2
        #     else
        #       echo "####$fn: curl download new v3 get_helm.sh and run ... HELMVERSION=\"$HELMVERSION\""
        #       curl -L -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
        #       echo "####$fn: got helm3 download script .."
        #       helmv=3
        #     fi
            # chmod +x get_helm.sh
            # if [[ "$HELMVERSION" == "" ]] || [[ "$HELMVERSION" == "v2" ]] || [[ "$HELMVERSION" == "v3" ]]; then
            #   ( set -x ; ./get_helm.sh )
            # else
            #   if [[ $helmv -eq 2 ]]; then
            #     #2020-05-27 v2 helm install failed in bac-uat cp: cannot create regular file '/usr/local/bin/tiller': Permission denied
            #     ( set -x ; ./get_helm.sh --version $HELMVERSION )
            #   else
            #     ( set -x ; ./get_helm.sh --no-sudo --version $HELMVERSION )
            #   fi
            # fi
            # rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: ERROR: ./get_helm.sh , HELMVERSION=\"$HELMVERSION\""; exit $rc; fi
            # (set -x ; helm version --client )
            # #Use tilerless helm2 or helm3

            # if [ "$helmv" = "2" ] ; then
            #   echo '#$fn: Using Tillerless Helm plugin'
            #   export HELM_TILLER_HISTORY_MAX=3;
            #   helm init --client-only
            #   helm plugin install https://github.com/rimusz/helm-tiller
            #   helm tiller start-ci
            #   export HELM_HOST=127.0.0.1:44134
            # fi
            ## helm install and verion now handled by
        HELMLOCAL=true
        currentHelmVersion=$( helm version --client --short 2>&1 | grep "^v")
        rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: ERROR getting helm version ???" ; exit $rc; fi
        if [[ "$currentHelmVersion" =~ "v2\." ]] ; then
          helmv=2
        else
          helmv=3
        fi
        echo "####$fn: Helm$helmv   currentHelmVersion=$currentHelmVersion"

        echo "####$fn: Helm$helmv installed, now upgrade/install \"stable/nginx-ingress\" ip:$aksClusterPubIP and rg:$pubIPResGrp RELEASE:$AKSCLUSTERNAME$AKSENVIRONMENT kubConfigPath:$kubConfigPath"
        maxTimeOut=1800
        kubConfigPath=$(ls $HOME/.kube/config)
        if [ "$helmv" = "2" ] ; then
        helm upgrade  $AKSCLUSTERNAME$AKSENVIRONMENT \
                      stable/nginx-ingress \
                      --install --atomic \
                      --namespace kube-system \
                      --set controller.service.loadBalancerIP="$aksClusterPubIP" \
                      --set controller.replicaCount=$replicaCount \
                      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="$pubIPResGrp" \
                      --timeout $maxTimeOut \
                      --tiller-connection-timeout $maxTimeOut \
                      --kubeconfig $kubConfigPath
        else
        ( set -x
        echo "####$fn: helm3 add and update repo to get lates stable nginx-ingress"
        helm repo add stable https://kubernetes-charts.storage.googleapis.com/
        helm repo list
        helm repo update
        helm search repo /nginx-ingress
        echo "####$fn: helm3 upgrade ...."
        #Note: Helm3 now requires unit for timeout - see https://itnext.io/breaking-changes-in-helm-3-and-how-to-fix-them-39fea23e06ff
        helm upgrade  $AKSCLUSTERNAME$AKSENVIRONMENT \
                      stable/nginx-ingress \
                      --install --atomic \
                      --namespace kube-system \
                      --set controller.service.loadBalancerIP="$aksClusterPubIP" \
                      --set controller.replicaCount=$replicaCount \
                      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="$pubIPResGrp" \
                      --timeout ${maxTimeOut}s \
                      --kubeconfig $kubConfigPath
        )
        # Note: To expose tcp (from Sham pr)  - needs configmap name: tcp-controller-configmap
        #    channelNameSpace=$CH-$AKSENVIRONMENT
        #    --set controller.extraArgs.tcp-services-configmap=$channelNameSpace/tcp-controller-configmap \
        #    --set controller.service.nodePorts.tcp="name: proxied-tcp-27017, port: 27017, targetPort: 27017, protocol: TCP" \
        #    --set controller.service.nodePorts.tcp.proxied-tcp-6379="port: 6379, targetPort: 6379, protocol: TCP" \
        #
        fi
        rc=$?; if [[ $rc -ne 0 ]]; then echo; echo "####$fn: aks $AKSCLUSTERNAME ingress-controller creation issue"; exit $rc; fi
        sleep 10
    else
        echo
        echo "####$fn: ingress update skipped values fine ip:$aksClusterPubIP and rg:$pubIPResGrp"
    fi
else
  echo
  echo "####$fn: NO ingress, replicaCount=$replicaCount , INGRESSCOUNT=$INGRESSCOUNT"
  echo "####$fn: will allow inf-hsmweb to be used"
  echo
fi
echo "####$fn: kubectl --namespace kube-system get services -o wide | grep ingress-controller "
kubectl --namespace kube-system get services -o wide | grep ingress-controller

echo "####$fn: helm status --namespace kube-system $AKSCLUSTERNAME$AKSENVIRONMENT ..."
helm status --namespace kube-system $AKSCLUSTERNAME$AKSENVIRONMENT | grep "NAME: \|LAST DEPLOYED: \|NAMESPACE: \|STATUS: "
rc=$?; if [[ $rc -ne 0 ]]; then echo "####$fn: no deployment found for ingress, probably done under previous version."; fi

echo "####$fn: helm ls --namespace kube-system"
helm ls --namespace kube-system

# if [[ "$HELMLOCAL" = true ]] && [[ "$helmv" = "2" ]] ; then
#   echo "####$fn: helm2 tiller stop"
# 	helm tiller stop
# fi
