#!/bin/bash
#
# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
# Licensed under the GNU General Public License Version 3 as shown at https://www.gnu.org/licenses/gpl-3.0.txt.

whitelist="install
status
delete
upgrade
"

set -e

release="installed-state"
delete_stale_resources="yes"
while [[ $# -gt 0 ]]; do
  flag="$1"
  case $flag in
    -c | --kubeconfig )
       kubecfg="$2"
       shift
       shift
    ;;
    -n | --namespace )
       namespace="$2"
       shift
       shift
    ;;
    -l | --delete-legacy-resources )
       cleanup_legacy_resources="$2"
       shift
       shift
    ;;
    -v | --version )
       # Only used in the "install" path
       desired_istio_install_version="$2"
       shift
       shift
     ;;
    -o | --current-istio-profile )
       # Only used in the "install" path
       current_version_profile="$2"
       shift
       shift
    ;;
    -a | --action )
       act="$2"
       shift
       shift
    ;;
    -i | --istio-profile )
       istio_profile="$2"
       shift
       shift
    ;;
    -I | --istio-custom-profile )
       istio_custom_profile_stanza="-f \"$2\""
       shift
       shift
    ;;
    -g | --grafana-profile )
       grafana_profile="$2"
       shift
       shift
    ;;
    -p | --prometheus-profile )
       prometheus_profile="$2"
       shift
       shift
    ;;
    -r | --release )
        # If the release is the empty string, set the variable to
	# "installed-state".  If it is not the empty string, for example
	# 'bar', set the variable to "installed-profile-<release>"
	# e.g. "installed-state-bar"
    	release="installed-state-$2"

	# Only clean up the straggler resources if this is the primary
	# release (i.e. when the release is the empty string).
	delete_stale_resources="no"
	shift
	shift
    ;;
    *)
       echo "invalid argument $1" >> /dev/stderr
       exit 1
    ;;
  esac
done

# Returns not found so we can mark the resource as uninstalled
if [ ! -f /usr/local/bin/istioctl ]; then
    echo "istioctl not found" >> /dev/stderr
    exit 1
fi

# Validate input
if ! echo "$whitelist" | grep -q -x "$act"; then
    echo "$act cannot be performed by this script"
    exit 1
fi

echo "kubecfg: $kubecfg namespace: $namespace act: $act cleanup_legacy_resources: $cleanup_legacy_resources"
tmp_verArr=( ${desired_istio_install_version//-/ } )
externalVerArr=( ${tmp_verArr[0]//./ } )

export KUBECONFIG="$kubecfg"

if [[ "${act}" == "delete" ]]; then
    # TODO: Generate from the manfest we installed with rather than the default
    set +e
    /usr/local/bin/istioctl manifest generate -f "${istio_profile}" $istio_custom_profile_stanza | kubectl delete --ignore-not-found=true -f -
    kubectl delete --ignore-not-found --namespace "$namespace" IstioOperator "$release"
    set -e
    if [[ "$delete_stale_resources" == "yes" ]]; then
        kubectl delete --ignore-not-found=true ClusterRoleBinding -l app=istio-init
        kubectl delete --ignore-not-found=true ClusterRoleBinding -l release=istio
        kubectl delete --ignore-not-found=true ClusterRoleBinding istio-multi

        kubectl delete --ignore-not-found=true ServiceAccount istio-multi -n istio-system
        kubectl delete --ignore-not-found=true ServiceAccount istio-init-service-account  -n istio-system

        kubectl delete --ignore-not-found=true ClusterRole -l app=istio-init
        kubectl delete --ignore-not-found=true ClusterRole -l release=istio
        kubectl delete --ignore-not-found=true ClusterRole istio-reader

        # Delete the CRD Jobs
        kubectl get job --ignore-not-found=true -n istio-system | grep istio-init-crd | awk '{ print $1 }' | xargs --no-run-if-empty -n1 kubectl --ignore-not-found=true delete job -n istio-system

        kubectl delete ns --ignore-not-found=true istio-system
    fi
fi

if [[ "${act}" == "install" ]]; then
	kubectl get namespace "$namespace" || kubectl create namespace "$namespace"

    if [[ ${desired_istio_install_version} == "1.5"* ]]; then
        # Is == 1.5
	    /usr/local/bin/istioctl manifest apply --skip-confirmation -f "${istio_profile}"
    else
        # Is >= 1.6
	    /usr/local/bin/istioctl install --skip-confirmation -f "${istio_profile}" $istio_custom_profile_stanza
    fi
fi

if [[ "${act}" == "status" ]]; then
    #/usr/local/bin/istioctl proxy-status
    kubectl -n "$namespace" get istiooperator "$release"
fi

if [[ "${act}" == "upgrade" ]]; then
    # Using --force allows us to upgrade from 1.4.10 -> 1.5.10 "$@"
    # From istio-1.13 onwards, istioctl upgrade is an alias to istioctl install, so, currentVersionProfile no longer required
    # Upstream changes: https://github.com/istio/istio/issues/35951
    if [[ (${externalVerArr[0]} -eq 1 && ${externalVerArr[1]} -le 12) || ${externalVerArr[0]} -gt 1 ]]; then
      /usr/local/bin/istioctl upgrade --force -y -f "${istio_profile}" --currentVersionProfile  "${current_version_profile}"
    else
      /usr/local/bin/istioctl upgrade --force -y -f "${istio_profile}" $istio_custom_profile_stanza
    fi

    if [[ "${cleanup_legacy_resources}" != "" ]]; then
        set +e
        kubectl -n istio-system delete --ignore-not-found=true deployment istio-citadel istio-galley istio-pilot istio-policy istio-sidecar-injector istio-telemetry
        kubectl -n istio-system delete --ignore-not-found=true service istio-citadel istio-policy istio-sidecar-injector istio-telemetry
        kubectl -n istio-system delete --ignore-not-found=true horizontalpodautoscaler.autoscaling/istio-pilot horizontalpodautoscaler.autoscaling/istio-telemetry
        kubectl -n istio-system delete --ignore-not-found=true pdb istio-citadel istio-galley istio-pilot istio-policy istio-sidecar-injector istio-telemetry
        kubectl -n istio-system delete --ignore-not-found=true deployment istiocoredns
        kubectl -n istio-system delete --ignore-not-found=true service istiocoredns

        kubectl delete --ignore-not-found=true policies.authentication.istio.io --all-namespaces --all
        kubectl delete --ignore-not-found=true meshpolicies.authentication.istio.io --all
        set -e
    fi

    # From 1.8.x onwards, addon components needs to be installed separately
    if [[ (${externalVerArr[0]} -eq 1 && ${externalVerArr[1]} -ge 8) || ${externalVerArr[0]} -gt 1 ]]; then
        # This is required only during transition from 1.2.x to 1.3.x to remove istioctl/kubectl managed addons
        # TODO remove this hack when 1.2.x support ends
        if [[ "$(helm list -n istio-system --all|grep grafana|awk '{print $1}')" == "" ]]; then
          set +e
          kubectl delete -f "${grafana_profile}" --force
          kubectl delete -f "${prometheus_profile}" --force
          set -e
        fi
    fi
fi
