#!/usr/bin/env bash # ====================================================================== # # API CLIENT :: GET A CI FILE FROM PACKAGE SERVER # # ---------------------------------------------------------------------- # 2021-03-31 v1.0 <axel.hahn@iml.unibe.ch> init # 2021-04-13 v1.1 <axel.hahn@iml.unibe.ch> add support for custom config # 2021-04-15 v1.2 <axel.hahn@iml.unibe.ch> added debugging of curl request # ====================================================================== # ---------------------------------------------------------------------- # CONFIG # ---------------------------------------------------------------------- line="----------------------------------------------------------------------" bDebug=0 customconfig= . $0.cfg # ---------------------------------------------------------------------- # FUNCTIONS # ---------------------------------------------------------------------- function showhelp(){ self=$( basename $0 ) echo " CIPGK GETTER Get packages from a software sattelite of IML ci server. SYNTAX: $self [OPTIONS] OPTIONS: -c CFGFILE load custom config file after defaults in $self.cfg -d enable debug infos -e PHASE phase; overrides env variable IMLCI_PHASE -f FILE filename to get (without path); overrides env variable IMLCI_FILE -l ITEM list -o OUTFILE optional output file -p PROJECT ci project id; overrides env variable IMLCI_PROJECT -s SECRET override secret in IMLCI_PKG_SECRET -u URL URL of iml ci server without trailing /; overrides env variable IMLCI_URL VALUES: CFGFILE custom config file. It is useful to handle files of different projects on a server. PHASE is a phase of the ci server; one of preview|stage|live FILE is a filename without path that was created by ci server. OUTFILE Output file. It can countain a path. If none is given the filename will be taken from FILE and stored in current directory PROJECT project id of the ci server SECRET secret to access project data on package server. Your given secret must match the secret on package server to get access to any url. ITEM type what to list; one of phases|projects|files To list projects a phase must be set. To list files a phase and a project must be set. DEFAULTS: You don't need to set all values by command line. Use a config to set defaults $0.cfg EXAMPLES: If url, secret, project and phase are set in the config you can operate by setting the filename to request. $self -f FILE downloads FILE to the current dir. $self -f FILE -o my-own-filename.tgz downloads FILE as my-own-filename.tgz $self -f ALL there is a special file ALL; it fetches all filenames by executing a directory listing and then downloads all remote files with their original name $self -e preview -l projects list existing projects in phase preview $self -l files list existing files of current project Remark: The directory listing can be turned off on the package server and results in a 403 status. " } function makeRequest(){ local apiMethod=$1 local apiRequest=$2 local outfile=$3 local secret=$4 # local outfile=$( mktemp ) if [ $bDebug = 1 ]; then echo $line echo $apiMethod ${apiHost}${apiRequest} echo $line fi 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` moreheaders="--fail" test $bDebug = 1 && moreheaders="-i" tmpdownloadfile="${outfile}.downloading" curl \ -H "Accept: application/json" -H "Content-Type: application/json" \ -H "Date: ${apiTS}" \ -H "Authorization: demo-bash-client:${myHash}" \ -X $apiMethod \ -o "${tmpdownloadfile}" \ $moreheaders \ -s \ ${IMLCI_URL}${apiRequest} rc=$? if [ "$bDebug" = "1" ]; then cat "${tmpdownloadfile}" rm -f "${tmpdownloadfile}" exit 0 fi if [ $rc -eq 0 ]; then # echo OK. # no outfile (= request to a directory) if [ -z "$outfile" ]; then # echo # echo ----- RESPONSE BODY: cat "${tmpdownloadfile}" rm -f "${tmpdownloadfile}" else mv "${tmpdownloadfile}" "${outfile}" ls -l "${outfile}" fi else echo ERROR: Download failed. fi else curl\ -H "Accept: application/json" -H "Content-Type: application/json" \ -X $apiMethod \ -o "${tmpdownloadfile}" \ ${IMLCI_URL}${apiRequest} fi } # ---------------------------------------------------------------------- # MAIN # ---------------------------------------------------------------------- if [ $# -lt 1 ]; then showhelp exit 1 fi while getopts "c:de:f:l:o:p:s:u:" option; do case ${option} in c) customconfig="$OPTARG" ;; d) bDebug=1 ;; e) export IMLCI_PHASE=$OPTARG ;; f) export IMLCI_FILE=$OPTARG ;; l) case $OPTARG in phases) IMLCI_PHASE='' IMLCI_PROJECT='' IMLCI_FILE='' ;; projects) IMLCI_PROJECT='' IMLCI_FILE='' ;; files) IMLCI_FILE='' ;; *) echo ERROR: invalid value for option [-l] echo showhelp exit 2 esac ;; o) export IMLCI_OUTFILE=$OPTARG ;; p) export IMLCI_PROJECT=$OPTARG ;; s) export IMLCI_PKG_SECRET=$OPTARG ;; u) export IMLCI_URL=$OPTARG ;; *) echo ERROR: invalid option [${option}] echo showhelp exit 2 esac done if [ ! -z "$customconfig" ]; then if [ -r "$customconfig" ]; then . "$customconfig" || exit 2 else echo "ERROR: unable to read custom config [$customconfig]." exit 2 fi fi test -z ${IMLCI_OUTFILE} && IMLCI_OUTFILE=$IMLCI_FILE if [ $bDebug = 1 ]; then pre=">>>>>> " echo $line echo echo DEBUG INFOS echo echo "${pre} defaults in $0.cfg" cat $0.cfg 2>/dev/null echo if [ ! -z "$customconfig" ]; then echo "${pre} custom config $customconfig" cat "$customconfig" echo fi echo "${pre} Params (override default values)" echo $* echo echo "${pre} effective values" echo "IMLCI_URL = $IMLCI_URL" echo "IMLCI_PKG_SECRET = $IMLCI_PKG_SECRET" echo "IMLCI_PROJECT = $IMLCI_PROJECT" echo "IMLCI_PHASE = $IMLCI_PHASE" echo "IMLCI_FILE = $IMLCI_FILE" echo "IMLCI_OUTFILE = $IMLCI_OUTFILE" echo fi if [ "$IMLCI_FILE" = "ALL" ]; then # echo ALL files were requested ... printf "%-30s" "get list of all files... " tmpfilelist=$( mktemp ) $0 -u "${IMLCI_URL}" \ -p "${IMLCI_PROJECT}" \ -e "${IMLCI_PHASE}" \ -s "${IMLCI_PKG_SECRET}" \ -l files \ -o "${tmpfilelist}" # cat "${tmpfilelist}" cat "${tmpfilelist}" | grep "^file:" | while read fileline do # echo $line myfile=$( echo $fileline | cut -f 2- -d ':' ) printf "%-30s" "GET $myfile... " $0 -u "${IMLCI_URL}" \ -p "${IMLCI_PROJECT}" \ -e "${IMLCI_PHASE}" \ -s "${IMLCI_PKG_SECRET}" \ -f "${myfile}" done else makeRequest GET "/packages/$IMLCI_PHASE/$IMLCI_PROJECT/$IMLCI_FILE" "$IMLCI_OUTFILE" "$IMLCI_PKG_SECRET" fi