#!/bin/bash

function provision_fyre_help() {
  [[ -n "$1" ]] && echo_warning "$1"
  reset_colors
  cat << EOM
Usage:
  mas provision-fyre [options]

Where ${COLOR_YELLOW}specified${TEXT_RESET} each option may also be defined by setting the appropriate environment variable.
When no options are specified on the command line, interactive-mode will be enabled by default.

FYRE Credentials (Required):
  -u, --username ${COLOR_YELLOW}FYRE_USERNAME${TEXT_RESET}            FYRE username
  -a, --apikey ${COLOR_YELLOW}FYRE_APIKEY${TEXT_RESET}                FYRE API key

Cluster Configuration (Required):
  -p, --product-id ${COLOR_YELLOW}FYRE_PRODUCT_ID${TEXT_RESET}        FYRE product group ID that will own the cluster
  -q, --quota-type ${COLOR_YELLOW}FYRE_QUOTA_TYPE${TEXT_RESET}        Declare the quota to use when provisioning the cluster ("quick_burn" or "product_group")
  -c, --cluster-name ${COLOR_YELLOW}CLUSTER_NAME${TEXT_RESET}         Name of the cluster to be provisioned (lowercase only)
  -t, --cluster-platform ${COLOR_YELLOW}CLUSTER_PLATFORM${TEXT_RESET} Cluster platform ("x", "p", "pvm", "z", default is "x")
  -v, --ocp-version ${COLOR_YELLOW}OCP_VERSION${TEXT_RESET}           OCP version to use (e.g 4.15, 4.16)
  -d, --description ${COLOR_YELLOW}FYRE_DESCRIPTION${TEXT_RESET}      Description of the OCP cluster
  -l, --location ${COLOR_YELLOW}FYRE_SITE${TEXT_RESET}                FYRE site where cluster will be provisioned (default is "svl")

Cluster Configuration (Optional):
      --enable-fips                                                   Enable FIPS settings in this Fyre cluster
      --enable-ipv6                                                   Enable IPV6 settings in this Fyre cluster. When enabled, site will be automatically changed to 'rtp'.

Fyre Quick Burn Worker Node Configuration (Optional, only takes effect when quota-type is set to "quickburn"):
      --cluster-size ${COLOR_YELLOW}FYRE_CLUSTER_SIZE${TEXT_RESET}    When Fyre Quick Burn, defines the size category ("medium" or "large")

Worker Node Configuration (Optional, only takes effect when quota-type is set to "product_group"):
      --worker-count ${COLOR_YELLOW}FYRE_WORKER_COUNT${TEXT_RESET}                        Number of worker nodes to provision (default 2)
      --worker-cpu ${COLOR_YELLOW}FYRE_WORKER_CPU${TEXT_RESET}                            How many CPUs to allocate per worker node (default 8)
      --worker-memory ${COLOR_YELLOW}FYRE_WORKER_MEMORY${TEXT_RESET}                      How much memory to allocate per worker node (default 32)
      --worker-additional-disks ${COLOR_YELLOW}FYRE_WORKER_ADDITIONAL_DISKS${TEXT_RESET}  Comma-seperated list of sizes for additional disks to attach (e.g. "200,200" to attach two 400gb additional disks)

Storage Provisioner Configuration:
      --storage ${COLOR_YELLOW}OCP_STORAGE_PROVIDER${TEXT_RESET}                         Choose optional storage provider (nfs, odf, or longhorn)
      --nfs-image-registry-size ${COLOR_YELLOW}FYRE_NFS_IMAGE_REGISTRY_SIZE${TEXT_RESET} Defines the image registry storage size when configured to use NFS (default 100gb). The size allocated cannot be superior of storage available in the Fyre Infrastructure node.

Turbonomic Integration:
      --turbonomic-name ${COLOR_YELLOW}TURBONOMIC_TARGET_NAME${TEXT_RESET}               Target name in Turbonomic
      --turbonomic-url ${COLOR_YELLOW}TURBONOMIC_SERVER_URL${TEXT_RESET}                 Turbonomic server URL
      --turbonomic-version ${COLOR_YELLOW}TURBONOMIC_SERVER_VERSION${TEXT_RESET}         Turbonomic server version
      --turbonomic-username ${COLOR_YELLOW}TURBONOMIC_USERNAME${TEXT_RESET}              Turbonomic username
      --turbonomic-password ${COLOR_YELLOW}TURBONOMIC_PASSWORD${TEXT_RESET}              Turbonomic password

Other Commands:
      --no-confirm        Provision the cluster without prompting for confirmation
  -h, --help              Show this help message

EOM
  [[ -n "$1" ]] && exit 1 || exit 0
}

function provision_fyre_noninteractive() {
  # Default to provisioning with NFS storage enabled on amd64
  if [[ -z "$CLUSTER_PLATFORM" ]]; then
    CLUSTER_PLATFORM=x
  fi

  while [[ $# -gt 0 ]]
  do
    key="$1"
    shift
    case $key in
      # Authentication
      -u|--username)
        FYRE_USERNAME=$1 && shift
        ;;
      -a|--apikey)
        FYRE_APIKEY=$1 && shift
        ;;

      # Product Group & Quota Type
      -p|--product-id)
        FYRE_PRODUCT_ID=$1 && shift
        ;;
      -q|--quota-type)
        FYRE_QUOTA_TYPE=$1 && shift
        ;;

      # Cluster Definition
      -c|--cluster-name)
        CLUSTER_NAME=$1 && shift
        ;;
      -t|--cluster-platform)
        CLUSTER_PLATFORM=$1 && shift
        ;;
      -v|--ocp-version)
        OCP_VERSION=$1 && shift
        ;;
      -d|--description)
        FYRE_CLUSTER_DESCRIPTION=$1 && shift
        ;;
      -l|--location)
        FYRE_SITE=$1 && shift
        ;;

      # Cluster Definition - optional
      --enable-fips)
        OCP_FIPS_ENABLED=true
        ;;
      --enable-ipv6)
        ENABLE_IPV6=true
        ;;

      # Worker configuration
      --worker-count)
        FYRE_WORKER_COUNT=$1 && shift
        ;;
      --worker-cpu)
        FYRE_WORKER_CPU=$1 && shift
        ;;
      --worker-memory)
        FYRE_WORKER_MEMORY=$1 && shift
        ;;
      --worker-additional-disks)
        FYRE_WORKER_ADDITIONAL_DISKS=$1 && shift
        ;;

      # Quickburn configuration
      --cluster-size)
        FYRE_CLUSTER_SIZE=$1 && shift
        ;;

      # Storage Configuration
      --storage)
        OCP_STORAGE_PROVIDER=$1 && shift
        ;;
      --nfs-image-registry-size)
        IMAGE_REGISTRY_STORAGE_SIZE=$1 && shift
        ;;

      # Turbonomic
      --turbonomic-name)
        TURBONOMIC_TARGET_NAME=$1 && shift
        ;;
      --turbonomic-url)
        TURBONOMIC_SERVER_URL=$1 && shift
        ;;
      --turbonomic-version)
        TURBONOMIC_SERVER_VERSION=$1 && shift
        ;;
      --turbonomic-username)
        TURBONOMIC_USERNAME=$1 && shift
        ;;
      --turbonomic-password)
        TURBONOMIC_PASSWORD=$1 && shift
        ;;

      # Other options
      --no-confirm)
        NO_CONFIRM=true
        ;;
      -h|--help)
        provision_fyre_help
        ;;
      *)
        # unknown option
        echo -e "${COLOR_RED}Usage Error: Unsupported option \"${key}\"${TEXT_RESET}\n"
        provision_fyre_help
        exit 1
        ;;
      esac
  done

  # Check all args have been set
  [[ -z "$FYRE_USERNAME" ]] && provision_fyre_help "FYRE_USERNAME is not set"
  [[ -z "$FYRE_APIKEY" ]] && provision_fyre_help "FYRE_APIKEY is not set"
  [[ -z "$CLUSTER_NAME" ]] && provision_fyre_help "CLUSTER_NAME is not set"
  [[ -z "$OCP_VERSION" ]] && provision_fyre_help "OCP_VERSION is not set"
  [[ -z "$FYRE_CLUSTER_DESCRIPTION" ]] && provision_fyre_help "FYRE_CLUSTER_DESCRIPTION is not set"
  [[ -z "$FYRE_PRODUCT_ID" ]] && provision_fyre_help "FYRE_PRODUCT_ID is not set"
  [[ -z "$FYRE_QUOTA_TYPE" ]] && provision_fyre_help "FYRE_QUOTA_TYPE is not set"

  if [[ -z "$FYRE_SITE" ]]; then
    FYRE_SITE=svl
  fi

  # IPV6 supported only in rtp site
  if [[ "$ENABLE_IPV6" == "true" ]]; then
    FYRE_SITE=rtp
  fi

  [[ "$FYRE_SITE" != "svl" && "$FYRE_QUOTA_TYPE" == "quick_burn" ]] && provision_fyre_help "Quickburn is only available in svl"
}

function provision_fyre_interactive() {
  if [[ "$FYRE_USERNAME" != "" && "$FYRE_APIKEY" != "" ]]; then
    prompt_for_confirm_default_yes "Re-use saved authentication details for user '$FYRE_USERNAME'?" REUSE_FYRE_AUTH
    if [[ "$REUSE_FYRE_AUTH" == "false" ]]; then
      prompt_for_input "Fyre Username" FYRE_USERNAME
      prompt_for_secret "Fyre API Key" FYRE_APIKEY
    fi
  else
    prompt_for_input "Fyre Username" FYRE_USERNAME
    prompt_for_secret "Fyre API Key" FYRE_APIKEY
  fi

  if [[ ! -z "$1" ]]; then
    CLUSTER_NAME=$1
  fi
  prompt_for_input "Cluster Name" CLUSTER_NAME

  echo
  echo "OCP Version:"
  echo "  1. 4.19"
  echo "  2. 4.18"
  echo "  3. 4.17"
  echo "  4. 4.16"
  prompt_for_input "Select Version" OCP_VERSION_SELECTION "1"

  case $OCP_VERSION_SELECTION in
    1|4.19)
      export OCP_VERSION=4.19
      ;;
    2|4.18)
      export OCP_VERSION=4.18
      ;;
    3|4.17)
      export OCP_VERSION=4.17
      ;;
    4|4.16)
      export OCP_VERSION=4.16
      ;;
    *)
      # Print out a warning as there could be a typo
      echo_warning "    Using custom OCP version ($OCP_VERSION_SELECTION)"
      export OCP_VERSION=$OCP_VERSION_SELECTION
      ;;
  esac

  echo
  echo "OCP Cluster Platform:"
  echo "  1. x - X86 (amd64)"
  echo "  2. z - Zlinux (s390x)"
  echo "  3. p - Power (ppc64e)"
  prompt_for_input "Select Cluster Plaform" CLUSTER_PLATFORM_SELECTION "x"

  case $CLUSTER_PLATFORM_SELECTION in
    1|x)
      export CLUSTER_PLATFORM=x
      ;;
    2|z)
      export CLUSTER_PLATFORM=z
      ;;
    3|p)
      export CLUSTER_PLATFORM=p
      ;;
    *)
      echo -e "${COLOR_RED}Usage Error: Invalid cluster platform selection: ${CLUSTER_PLATFORM_SELECTION}${TEXT_RESET}\n"
      exit 1
      ;;
  esac

  prompt_for_input "Cluster Description" FYRE_CLUSTER_DESCRIPTION
  prompt_for_input "FYRE Product ID" FYRE_PRODUCT_ID
  prompt_for_input "FYRE Site" FYRE_SITE

  prompt_for_confirm "Use Product Group Quota?" USE_PRODUCT_GROUP_QUOTA
  if [[ "$USE_PRODUCT_GROUP_QUOTA" == "true" ]]; then
    FYRE_QUOTA_TYPE="product_group"
    prompt_for_number "Number of Worker Nodes" FYRE_WORKER_COUNT "3"
    prompt_for_number "Worker Node CPU (max 16)" FYRE_WORKER_CPU "8"
    prompt_for_number "Worker Node Memory (max 64)" FYRE_WORKER_MEMORY "16"
    prompt_for_input "Worker Additional Disk Sizes (GB, comma-seperated list)" FYRE_WORKER_ADDITIONAL_DISKS
    prompt_for_confirm "Enable FIPS? " OCP_FIPS_ENABLED
    prompt_for_confirm "Enable IPV6? " ENABLE_IPV6
  else
    FYRE_QUOTA_TYPE="quick_burn"
    if [[ "$FYRE_SITE" != "svl" ]]; then
      echo -e "${COLOR_RED}Usage Error: QuickBurn is only supported in svl${TEXT_RESET}\n"
      exit 1
    fi

    echo
    echo "Fyre cluster size:"
    echo "  1. medium"
    echo "  2. large"
    prompt_for_input "Select the Fyre cluster size" FYRE_CLUSTER_SIZE_SELECTION "1"

    if [[ "$FYRE_CLUSTER_SIZE_SELECTION" == "1" ]]; then
      FYRE_CLUSTER_SIZE=medium
    elif [[ "$FYRE_CLUSTER_SIZE_SELECTION" == "2" ]]; then
      FYRE_CLUSTER_SIZE=large
    else
      echo -e "${COLOR_RED}Usage Error: QuickBurn only supports size definitions medium or large${TEXT_RESET}\n"
      exit 1
    fi
  fi

  echo
  echo_h2 "Storage Provider:"
  echo "  1. None"
  echo "  2. Longhorn"
  echo "  3. NFS"
  echo "  4. ODF"
  prompt_for_input "Select the storage provider to setup" OCP_STORAGE_PROVIDER_SELECTION "1"

  if [[ "$OCP_STORAGE_PROVIDER_SELECTION" == "1" ]]; then
    OCP_STORAGE_PROVIDER=""
  elif [[ "$OCP_STORAGE_PROVIDER_SELECTION" == "2" ]]; then
    OCP_STORAGE_PROVIDER="longhorn"
  elif [[ "$OCP_STORAGE_PROVIDER_SELECTION" == "3" ]]; then
    OCP_STORAGE_PROVIDER="nfs"
  elif [[ "$OCP_STORAGE_PROVIDER_SELECTION" == "4" ]]; then
    OCP_STORAGE_PROVIDER="odf"
  fi

  echo
  echo_h2 "Turbonomic Integration:"
  echo "Leave name empty if you do not want to enable Turbonomic integration in this cluster"
  prompt_for_input "Turbonomic Name" TURBONOMIC_TARGET_NAME
  if [[ "$TURBONOMIC_TARGET_NAME" != "" ]]; then
    prompt_for_input "Server URL" TURBONOMIC_SERVER_URL
    prompt_for_input "Server Version" TURBONOMIC_SERVER_VERSION
    prompt_for_input "Username" TURBONOMIC_USERNAME
    prompt_for_secret "Password" TURBONOMIC_PASSWORD
  fi

}

function provision_fyre() {
  # Take the first parameter off (it will be provision-fyre)
  shift
  if [[ $# -gt 0 ]]; then
    provision_fyre_noninteractive "$@"
  else
    provision_fyre_interactive
  fi

  # Fyre will provision a cluster with lowercase name so force to lowercase now
  old=$CLUSTER_NAME
  declare -l new=$CLUSTER_NAME
  if [[ $old != $new ]] ; then
    echo
    echo_warning "Cluster name converted to lowercase"
    CLUSTER_NAME=$new
  fi

  # Ensure all environment variables are available to ansible-playbook
  export FYRE_USERNAME
  export FYRE_APIKEY
  export FYRE_PRODUCT_ID
  export FYRE_QUOTA_TYPE

  export CLUSTER_TYPE=fyre
  export CLUSTER_NAME
  export OCP_VERSION
  export CLUSTER_PLATFORM
  export FYRE_CLUSTER_DESCRIPTION
  export FYRE_CLUSTER_SIZE
  export FYRE_SITE

  export FYRE_WORKER_COUNT
  export FYRE_WORKER_CPU
  export FYRE_WORKER_MEMORY
  export FYRE_WORKER_ADDITIONAL_DISKS
  export OCP_FIPS_ENABLED
  export ENABLE_IPV6

  export OCP_STORAGE_PROVIDER

  export TURBONOMIC_TARGET_NAME
  export TURBONOMIC_SERVER_URL
  export TURBONOMIC_SERVER_VERSION
  export TURBONOMIC_USERNAME
  export TURBONOMIC_PASSWORD

  echo
  reset_colors
  echo_h2 "Review Settings"

  echo "${TEXT_DIM}"
  echo_h2 "FYRE Authentication" "    "
  echo_reset_dim "Username .................. ${COLOR_MAGENTA}${FYRE_USERNAME}"

  reset_colors
  echo "${TEXT_DIM}"
  echo_h2 "FYRE Accounting" "    "
  echo_reset_dim "Product Group ID .......... ${COLOR_MAGENTA}${FYRE_PRODUCT_ID}"
  echo_reset_dim "Quota Type ................ ${COLOR_MAGENTA}${FYRE_QUOTA_TYPE}"
  echo_reset_dim "Site ...................... ${COLOR_MAGENTA}${FYRE_SITE}"

  reset_colors
  echo "${TEXT_DIM}"
  echo_h2 "Cluster Configuration" "    "
  echo_reset_dim "Name ...................... ${COLOR_MAGENTA}${CLUSTER_NAME}"
  echo_reset_dim "Description ............... ${COLOR_MAGENTA}${FYRE_CLUSTER_DESCRIPTION}"
  echo_reset_dim "OCP Version ............... ${COLOR_MAGENTA}${OCP_VERSION}"

  if [[ "${FYRE_QUOTA_TYPE}" == "product_group" ]]; then
    reset_colors
    echo "${TEXT_DIM}"
    echo_h2 "Worker Configuration" "    "
    echo_reset_dim "Worker Node Count ......... ${COLOR_MAGENTA}${FYRE_WORKER_COUNT:-Default}"
    echo_reset_dim "Worker Node CPU ........... ${COLOR_MAGENTA}${FYRE_WORKER_CPU:-Default}"
    echo_reset_dim "Worker Node Memory ........ ${COLOR_MAGENTA}${FYRE_WORKER_MEMORY:-Default}"
    echo_reset_dim "Worker Node Disks ......... ${COLOR_MAGENTA}${FYRE_WORKER_ADDITIONAL_DISKS:-None}"
    echo_reset_dim "Enable FIPS? .............. ${COLOR_MAGENTA}${OCP_FIPS_ENABLED:-None}"
    echo_reset_dim "Enable IPV6? .............. ${COLOR_MAGENTA}${ENABLE_IPV6:-None}"
  fi

  reset_colors
  echo "${TEXT_DIM}"
  echo_h2 "Storage" "    "
  echo_reset_dim "Storage Provider ............ ${COLOR_MAGENTA}${OCP_STORAGE_PROVIDER}"

  if [[ "${TURBONOMIC_TARGET_NAME}" != "" ]]; then
    reset_colors
    echo "${TEXT_DIM}"
    echo_h2 "Turbonomic Integration" "    "
    echo_reset_dim "Target Name ................. ${COLOR_MAGENTA}${TURBONOMIC_TARGET_NAME}"
    echo_reset_dim "Server URL .................. ${COLOR_MAGENTA}${TURBONOMIC_SERVER_URL}"
    echo_reset_dim "Server Version .............. ${COLOR_MAGENTA}${TURBONOMIC_SERVER_VERSION}"
  fi

  echo
  reset_colors
  if [[ "$NO_CONFIRM" != "true" ]]; then
    prompt_for_confirm "Proceed with these settings" || exit 0
  fi

  ansible-playbook ibm.mas_devops.ocp_fyre_provision
  result=$?

  if [[ "$result" == "0" ]]; then
    echo ""
    echo "IBM DevIT Fyre OCP cluster is ready to use"
    OCP_CONSOLE_ROUTE=$(oc -n openshift-console get route console -o=jsonpath='{.spec.host}')
    echo "Connected to OCP cluster: https://$OCP_CONSOLE_ROUTE"

    # Collect the information necessary for a Slack notification to be generated
    curl -k -u "$FYRE_USERNAME:$FYRE_APIKEY" -H "Content-type: application/json" https://ocpapi.svl.ibm.com/v1/ocp/$CLUSTER_NAME > /tmp/fyre-$CLUSTER_NAME.json
    export OCP_USERNAME=$(jq -r .clusters[0].ocp_username /tmp/fyre-$CLUSTER_NAME.json)
    export OCP_PASSWORD=$(jq -r .clusters[0].kubeadmin_password /tmp/fyre-$CLUSTER_NAME.json)
    export OCP_CONSOLE_URL="https://$OCP_CONSOLE_ROUTE"
    rm /tmp/fyre-$CLUSTER_NAME.json
  fi
  mas-devops-notify-slack --action ocp-provision-fyre --rc $result
  exit $result
}
