#!/usr/bin/env bash
# ======================================================================
#
# API CLIENT :: API REQUEST TO IML CI SERVER
#
# ----------------------------------------------------------------------
# 2020-07-23  v1.0  <axel.hahn@iml.unibe.ch>  first lines
# 2020-07-29  v1.1  <axel.hahn@iml.unibe.ch>  check "/" in branch; check http status 200 
# 2021-03-29  v1.2  <axel.hahn@iml.unibe.ch>  support slashes in branch names
# 2025-02-19  v1.3  <axel.hahn@iml.unibe.ch>  shell fixes; long cli parameters
# ======================================================================

# ----------------------------------------------------------------------
# CONFIG
# ----------------------------------------------------------------------

line="----------------------------------------------------------------------"
# LOG_FILE=/tmp/`basename $0`-last.log
# exec > >(tee -a ${LOG_FILE} )
# exec 2> >(tee -a ${LOG_FILE} >&2)

# ----------------------------------------------------------------------
# FUNCTIONS
# ----------------------------------------------------------------------

# Show help with parameters
function showhelp(){
  local _self; _self="$( basename "$0" )"
echo "
SYNTAX:
  -a, --action ACTION     
          set name of an action
          ... without given project and secret
              projects    show projects

          ... with project and secret
              buildinfo BRANCH
                          show infos about what happens on build
              build BRANCH
                          execute build
              phases      show status of phases
  -b, --branch BRANCH
          set custom branch to access, i.e. origin/feature-123
  -p, --project PROJECT
          project name in the ci server; overrides env variable IMLCI_PROJECT
  -s, --secret SECRET
          API secret for the given project; overrides env variable IMLCI_API_SECRET
  -u. --url URL
          URL of iml ci server without trailing /; overrides env variable IMLCI_URL

EXAMPLES:
  $_self -u https://ci.example.com -a projects
  $_self -u https://ci.example.com -p myproject -s 12345678 -a buildinfo
  $_self -u https://ci.example.com -p myproject -s 12345678 -a build
"
}


function makeRequest(){

  local apiMethod=$1
  local apiRequest=$2
  local secret=$3

  local outfile=$( mktemp )

  echo $line
  echo "$apiMethod ${IMLCI_URL}${apiRequest}"
  echo $line

  if [ ! -z "$secret" ]; then

    # --- date in http format
    LANG=en_EN
    # export TZ=GMT
    apiTS=$( date "+%a, %d %b %Y %H:%M:%S %Z" )


# --- generate data to hash: method + uri + timestamp; delimited with line break
data="${apiMethod}
${apiRequest}
${apiTS}
"

    # generate hash - split in 2 commands (piping "cut" sends additional line break)
    myHash=$( echo -n "$data" | openssl sha1 -hmac "${secret}" | cut -f 2 -d" ")
    myHash=$( echo -n "$myHash" | base64 )

    curl -i \
      -H "Accept: application/json" -H "Content-Type: application/json" \
      -H "Date: ${apiTS}" \
      -H "Authorization: demo-bash-client:${myHash}" \
      -X "$apiMethod" \
      -s \
      "${IMLCI_URL}${apiRequest}" | tee -a "$outfile"
  else
    curl -i \
      -H "Accept: application/json" -H "Content-Type: application/json" \
      -X "$apiMethod" \
      -s \
      "${IMLCI_URL}${apiRequest}" | tee -a "$outfile"
  fi

  grep "^HTTP/" "$outfile" | head -1 | grep " 200 " >/dev/null
  local rccurl=$?

  rm -f "$outfile"
  if [ $rccurl -ne 0 ]; then
    echo
    echo "ERROR: API request failed. CURL request did not get respond status code 200."
    exit 5
  fi
}


# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------

echo
echo "===== API CALL TO IML CI SERVER :: $( date ) ====="
echo

if  [ $# -eq 0 ]; then
  showhelp
  exit 1
fi

while [[ "$#" -gt 0 ]]; do case $1 in
    -a|--action)    apiAction="$2";shift; shift;;
    -b|--branch)    branch="$2";shift; shift;;
    -h|--help)      showhelp; exit 0;;
    -u|--url)       IMLCI_URL="$2";shift; shift;;
    -p|--project)   IMLCI_PROJECT="$2";shift; shift;;
    -s|--secret)    IMLCI_API_SECRET="$2";shift; shift;;
    *) if grep "^-" <<< "$1" >/dev/null ; then
        echo; echo "ERROR: Unknown parameter: $1"; echo; showhelp; exit 2
       fi
       break;
       ;;
esac; done
if  [ $# -gt 0 ]; then
  showhelp
  exit 3
fi


echo "Params: $*"
echo "IMLCI_URL = $IMLCI_URL"
echo "IMLCI_PROJECT = $IMLCI_PROJECT"
echo "IMLCI_API_SECRET = $IMLCI_API_SECRET"
echo

# task-4364: slashes are supported now
# echo $branch | grep '/.*/.*' >/dev/null && ( echo "WARNING: Do NOT use a branch containing a slash [/] in the name"; echo )


echo "ACTION: $apiAction"
case $apiAction in

  # --- projects is an access without autorization
  "projects")
    makeRequest GET  /api/v1/projects
    ;;

  # --- access WITH autorization only
  "build")
    makeRequest POST "/api/v1/project/$IMLCI_PROJECT/build/$branch" "$IMLCI_API_SECRET"
    ;;
  "buildinfo")
    makeRequest GET  "/api/v1/project/$IMLCI_PROJECT/build/$branch" "$IMLCI_API_SECRET"
    ;;
  "phases")
    makeRequest GET  "/api/v1/project/$IMLCI_PROJECT/phases"   "$IMLCI_API_SECRET"
    ;;
  *)
    echo "ERROR: unknown action [$apiAction]"
    exit 4
esac

rc=$?
echo
echo $line
date
echo rc=$rc

exit $rc