#!/usr/bin/env bash
#    Licensed to the Apache Software Foundation (ASF) under one or more
#    contributor license agreements.  See the NOTICE file distributed with
#    this work for additional information regarding copyright ownership.
#    The ASF licenses this file to You under the Apache License, Version 2.0
#    (the "License"); you may not use this file except in compliance with
#    the License.  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
#    Set of common operations that CI needs to invoke when using Kubernetes.
#    The operations can be invoked using a provided kubeconfig file
#    and kubernetes namespace.
#
#    Specify the following environment variables to override defaults:
#    - KUBECONFIG: path to .kube/config file (default: $HOME/.kube/config)
#    - KUBERNETES_NAMESPACE: namespace to be used (default: default)
set -euxo pipefail

KUBECONFIG="${KUBECONFIG:=$HOME/.kube/config}"
KUBERNETES_NAMESPACE="${KUBERNETES_NAMESPACE:=default}"
KUBECTL="kubectl --kubeconfig=$KUBECONFIG --namespace=$KUBERNETES_NAMESPACE"

function retry() {
  local command=$1
  local max_retries=$2
  local sleep_time=$3

  for ((i = 1; i <= max_retries; i++)); do
    local output
    output=$(eval "${command}")

    local status=$?

    if [[ ${status} == 0 ]] && [[ -n  ${output} ]]; then
      echo "${output}"
      return 0
    fi

    if [[ $i == "${max_retries}" ]]; then
      echo "Command failed after ${max_retries} retries" >&2
      return 1
    fi

    sleep "${sleep_time}"
  done
}

# Invokes "kubectl apply" using specified kubeconfig and namespace.
#
# Usage: ./kubernetes.sh apply <path to .yaml file or directory with .yaml files>
function apply() {
  eval "$KUBECTL apply -R -f $1"
}

# Invokes "kubectl delete" using specified kubeconfig and namespace.
#
# Usage: ./kubernetes.sh delete <path to .yaml file>
function delete() {
  eval "$KUBECTL delete -R -f $1"
}

# Creates a namespace.
#
# Usage: ./kubernetes.sh createNamespace <namespace name>
function createNamespace() {
  eval "kubectl --kubeconfig=${KUBECONFIG} create namespace $1"
}

# Deletes whole namespace with all its contents.
#
# Usage: ./kubernetes.sh deleteNamespace <namespace name>
function deleteNamespace() {
  eval "kubectl --kubeconfig=${KUBECONFIG} delete namespace $1"
}

# Gets Load Balancer Ingress IP address.
# Blocks and retries until the IP is present or retry limit is exceeded.
#
# Usage: ./kubernetes.sh loadBalancerIP <name of the load balancer service>
function loadBalancerIP() {
  local name=$1
  local command="$KUBECTL get svc $name -ojsonpath='{.status.loadBalancer.ingress[0].ip}'"
  retry "${command}" 36 10
}

"$@"
