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

#set -x #Debug
#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 "###$fn: !!!## 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

echo "###$fn: Home is : $HOME"
echo "###$fn: Running path : $PWD"
# running user
echo "###$fn: whoami=$(whoami)"

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

# check the resouces availability from az pipeline
for resource in SP_DEPLOY_ID SP_DEPLOY_SECRET SP_K8S_ID SP_K8S_SECRET TENANT SUBSCRIPTIONID AKSENVIRONMENT CH CHANNELTAG AKSCLUSTERNAME AKSCLUSTERNODECOUNT AKSCLUSTERADDONS RESOURCELOCATION ;
do
  if [ -z "${!resource}" ]; then
    echo "###$fn: $resource Not found. Check pipeline variables"
    exit 1
  fi
done

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

echo "###$fn: check the cluster status $ az aks show --name $AKSCLUSTERNAME --resource-group $aksResourceGroup --output table"
aks_cluster_status=$(az aks show --name $AKSCLUSTERNAME --resource-group $aksResourceGroup --output table)
rc=$?
if [[ $rc -ne 0 ]]; then
  echo "###$fn: #az aks show returned a error rc=$rc  $ az aks show --name $AKSCLUSTERNAME --resource-group $aksResourceGroup --output table"
  echo "$aks_cluster_status"
  #exit $rc
fi

# Check if cluster exists
echo "$aks_cluster_status" | grep "^$AKSCLUSTERNAME"
rc=$?
if [[ $rc -eq 0 ]]; then
  CLUSTERSTATE="existing k8s cluster"
  echo "###$fn: cluster $AKSCLUSTERNAME exists now check for Succeeded."
  echo "$aks_cluster_status" | grep "^$AKSCLUSTERNAME" | grep -o "Succeeded"
  rc=$?
  if [[ $rc -ne 0 ]]; then
    CLUSTERSTATE="existing k8s ERROR status Try to redeploy cluster"
    echo
    echo "# az aks show  -> cluster $AKSCLUSTERNAME exists but deployment not in Succeeded state !!"
    echo "$aks_cluster_status"
    echo "# retry the deployment .... see if it fixes the azure error ...."
    # exit 1
  else
    ## EXIT POINT 1/2
    echo "###$fn: exit cluster $AKSCLUSTERNAME exists and is deployed succesfully."
    ##Set credentials for other steps.
    echo "####$fn: get k8s credentials for cluster --name=$AKSCLUSTERNAME"
    az aks get-credentials --resource-group $aksResourceGroup \
                            --name $AKSCLUSTERNAME \
                            --overwrite-existing

    kubectl config current-context
    exit 0
  fi
else
  CLUSTERSTATE="create new cluser"
fi

##If we get here there is no cluster in Azure, or it is not Succeeded
  # it will handle the cluster provisioningState == Failed or not deployed (exit code 3) or Resource group 'aks-xxxx' could not be found (exit code 1).
  # if provisioningState == Failed it try to update/fix the cluster
  echo
  echo "###$fn: state:\"$CLUSTERSTATE\" $AKSCLUSTERNAME in RG=$aksResourceGroup"

  aksClusterTags="environment=$AKSENVIRONMENT $CHANNELTAG"

  ## Move to az_script-05 need RG for IP
  # echo "###$fn: az group create --name $aksResourceGroup --location $RESOURCELOCATION"
  # az group create --name $aksResourceGroup --location $RESOURCELOCATION --tags $aksClusterTags

  # Use a static IP address outside of the node resource group
  # Assign role to SP/ID before we deploy the cluster
  # https://docs.microsoft.com/en-us/azure/aks/static-ip

  echo "###$fn: give SP:$SP_K8S_ID access to scope /subscriptions/$SUBSCRIPTIONID/resourceGroups/$aksResourceGroup"
  az role assignment create \
    --assignee $SP_K8S_ID \
    --role "Network Contributor" \
    --scope /subscriptions/$SUBSCRIPTIONID/resourceGroups/$aksResourceGroup

  echo "###$fn: list role assignment for SP/ID:$SP_K8S_ID after assignment $aksResourceGroup"
  az role assignment list --assignee "$SP_K8S_ID" \
                          --resource-group $aksResourceGroup

  # create aks cluster with autoscaler
  #  auto scaler is a preview feature 201907 - https://docs.microsoft.com/bs-latn-ba/azure/aks/cluster-autoscaler
  #  az extension add --name aks-preview
  #20190924 change default to true
  if [ "$ENABLESECURITYPOLICY" != "false" ] ; then
    echo "###$fn:ENABLESECURITYPOLICY=$ENABLESECURITYPOLICY () Create a virtual network and subnet state:\"$CLUSTERSTATE\""
    (set -x;
    az network vnet create \
        --resource-group $aksResourceGroup \
        --location $RESOURCELOCATION \
        --name $aksBaseName-vnet \
        --address-prefixes 10.0.0.0/8 \
        --subnet-name $aksBaseName-k8s-subnet \
        --subnet-prefix 10.240.0.0/16
    )
    # Get the virtual network resource ID
    VNET_ID=$(az network vnet show --resource-group $aksResourceGroup --name $aksBaseName-vnet --query id -o tsv)
    echo "###$fn: Give SP access to virtual net resource. --assignee $SP_K8S_ID --scope $VNET_ID --role Contributor"
    az role assignment create --assignee $SP_K8S_ID --scope $VNET_ID --role Contributor
    echo "###$fn: Now List $ az role assignment list --all --assignee $SP_K8S_ID"
    az role assignment list --all --assignee $SP_K8S_ID
    # Get the virtual network subnet resource ID
    extraoptions=""
    if [[ "$K8S_VERSION" = "" ]];
    then
        extraoptions=""
    else
        if [[ ${#K8S_VERSION} -gt 12 ]];
        then
            echo "###$fn: ERR \$K8S_VERSION to long ${#K8S_VERSION}> 12 char value: \"$K8S_VERSION\""
            #bug6016
            extraoptions=""
        else
            printf -v extraoptions '%s --kubernetes-version %s ' "$extraoptions" "$K8S_VERSION"
            echo "###$fn: Set k8s version to \"$extraoptions\""
        fi
    fi

    SUBNET_ID=$(az network vnet subnet show --resource-group $aksResourceGroup --vnet-name $aksBaseName-vnet --name $aksBaseName-k8s-subnet --query id -o tsv)

    echo "####$fn:#### get aks_pub_ip for cluster creation ####"
    # ip should have been created already by az_script-05, just retrieve ip.

    aksClusterPubIPName=${RESERVEDPUBIPADDRNAME:-$AKSCLUSTERNAME-$AKSENVIRONMENT-ip-public}
    pubIPResGrp=${RESERVEDPUBIPRESOURCEGROUP:-$aksResourceGroup}

    echo "####$fn: env pubIPResGrp=$pubIPResGrp , aksClusterPubIPName=$aksClusterPubIPName , Optional: RESERVEDPUBIPRESOURCEGROUP=$RESERVEDPUBIPRESOURCEGROUP"
    aksLbSku=$(az network public-ip show --resource-group $pubIPResGrp \
                                                  --name $aksClusterPubIPName \
                                                  --query sku \
                                                  --output tsv)
    aksClusterPubIP=$(az network public-ip show --resource-group $pubIPResGrp \
                                                --name $aksClusterPubIPName \
                                                --query ipAddress \
                                                --output tsv)
    # get the pub ip subscription id (used to add lock to pub ID below)
    aksClusterPubIpID=$(az network public-ip show --resource-group $pubIPResGrp \
                                                --name $aksClusterPubIPName \
                                                --query id \
                                                --output tsv)
    echo "####$fn: IP aksLbSku=$aksLbSku , aksClusterPubIP=$aksClusterPubIP , aksClusterPubIpID=$aksClusterPubIpID"
    if [ -z "$aksClusterPubIP" ]; then
      echo "####$fn: aksClusterPubIP can't be empty!!! Error on public IP creation"
      exit 1;
    fi

    if [[ "$aksLbSku" == "Standard" ]]; then
      echo "###$fn: For LB=Standard, add  --load-balancer-outbound-ips \"$aksClusterPubIpID\" , and --api-server-authorized-ip-ranges \"\" "
      printf -v extraoptions '%s --load-balancer-outbound-ips %s '    "$extraoptions" "$aksClusterPubIpID"
      ## printf -v extraoptions '%s --api-server-authorized-ip-ranges "" ' "$extraoptions"
      echo "###$fn: extraoptions=${extraoptions}"
        # --load-balancer-idle-timeout 5
        # --load-balancer-outbound-ports 8000
        # --load-balancer-outbound-ip-prefixes
    fi

    echo "###$fn: create k8s --name $AKSCLUSTERNAME Node[Cnt,min,max]=[$AKSCLUSTERNODECOUNT,$AKSAUTOSCALERMIN,$AKSAUTOSCALERMAX] state:\"$CLUSTERSTATE\" $extraoptions"
    ( set -x;
      az aks create --resource-group $aksResourceGroup \
        --node-resource-group $aksBaseName-k8s-nodes \
        --name $AKSCLUSTERNAME \
        --node-count $AKSCLUSTERNODECOUNT \
        --enable-addons $AKSCLUSTERADDONS \
        --ssh-key-value $AKSCLUSTERSSHKEYPATH \
        --location $RESOURCELOCATION \
        --node-vm-size $AKSCLUSTERVMSIZE \
        --network-plugin azure \
        --service-cidr 10.0.0.0/16 \
        --dns-service-ip 10.0.0.10 \
        --docker-bridge-address 172.17.0.1/16 \
        --vnet-subnet-id $SUBNET_ID \
        --network-policy azure \
        --enable-pod-security-policy \
        --service-principal $SP_K8S_ID \
        --client-secret $SP_K8S_SECRET \
        --workspace-resource-id $LOGWORKSPACE \
        --tags "$aksClusterTags" \
        --enable-vmss \
        --enable-cluster-autoscaler \
        --min-count $AKSAUTOSCALERMIN \
        --max-count $AKSAUTOSCALERMAX \
        --vm-set-type VirtualMachineScaleSets \
        --load-balancer-sku "$aksLbSku" ${extraoptions}


    )
  else ###ERROR
    echo "###$fn: create k8s cluster - NO security policy  state:\"$CLUSTERSTATE\" "
    echo "## no security policy - NOT SUPPORTED ANYMORE - Fix $fn"
    exit 1
    (set -x;
    az aks create --resource-group $aksResourceGroup \
                  --node-resource-group $aksBaseName-k8s-nodes \
                  --name $AKSCLUSTERNAME \
                  --node-count $AKSCLUSTERNODECOUNT \
                  --enable-addons $AKSCLUSTERADDONS \
                  --ssh-key-value $AKSCLUSTERSSHKEYPATH \
                  --location $RESOURCELOCATION \
                  --node-vm-size $AKSCLUSTERVMSIZE \
                  --tags $aksClusterTags  \
                  --enable-vmss \
                  --enable-cluster-autoscaler \
                  --min-count $AKSAUTOSCALERMIN \
                  --max-count $AKSAUTOSCALERMAX \
                  --vm-set-type VirtualMachineScaleSets \
                  --load-balancer-sku $aksLbSku \
                  --api-server-authorized-ip-ranges "" \
                  --service-principal $SP_K8S_ID \
                  --client-secret $SP_K8S_SECRET \
                  --workspace-resource-id $LOGWORKSPACE
    )
  fi
  rc=$?
  if [[ $rc -ne 0 ]]; then
    echo
    echo -e "###$fn:\n aks $AKSCLUSTERNAME cluster creation error rc=$rc - exit"
    exit $rc
  fi

  echo -e "###$fn:\n sleep 20s ..."
  sleep 20
  echo "###$fn: az aks list -o table"
  az aks list -o table

  # check given aks cluster has been created (before helm deployment next)
  aks_cluster_status=$(az aks show --name $AKSCLUSTERNAME --resource-group $aksResourceGroup --output table)
  echo "$aks_cluster_status" | grep "^$AKSCLUSTERNAME" | grep -o "Succeeded"
  rc=$?
  # exist if given aks cluster not created
  if [[ $rc -ne 0 ]]; then
    echo
    echo "$aks_cluster_status"
    echo "###$fn: aks $AKSCLUSTERNAME cluster not created succesfully - exit"
    exit $rc
  fi

## EXIT POINT 2/2
##Set credentials for other steps.
echo "####$fn: get k8s credentials for cluster --name $AKSCLUSTERNAME"
az aks get-credentials --resource-group $aksResourceGroup \
                        --name $AKSCLUSTERNAME \
                        --overwrite-existing

kubectl config current-context