diff --git a/tests/getfile.sh b/tests/getfile.sh new file mode 100755 index 0000000000000000000000000000000000000000..6bd3a5b8b7e98cb710cbb69b4de01ed0e531b5a2 --- /dev/null +++ b/tests/getfile.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash +# ====================================================================== +# +# API CLIENT :: GET A CI FILE FROM PACKAGE SERVER +# +# Source: https://git-repo.iml.unibe.ch/iml-open-source/imldeployment-client/ +# ---------------------------------------------------------------------- +# 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 +# 2021-10-14 v1.3 <axel.hahn@iml.unibe.ch> add nanoseconds in hashed base data +# 2023-02-14 v1.4 <axel.hahn@unibe.ch> compatibility to openssl v3 +# ====================================================================== + +# ---------------------------------------------------------------------- +# CONFIG +# ---------------------------------------------------------------------- + +version="v1.4" +about="CI PACKAGE GETTER $version; +(c) 2021 Institute for Medical Education (IML); University of Bern; +GNU GPL 3.0" + +line="----------------------------------------------------------------------" +bDebug=0 +customconfig= + +. $0.cfg + +# ---------------------------------------------------------------------- +# FUNCTIONS +# ---------------------------------------------------------------------- + +function showhelp(){ +self=$( basename $0 ) +echo "$line +$about +$line + +Get packages from a software sattelite of IML ci server. + +SYNTAX: + + $self [OPTIONS] + +OPTIONS: + + -h Show this help + -v Show version + + -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. +" +} + +# make an http request to fetch the software +# +# param string method; should be GET +# param string request url (without protocol and server) +# param string optional: filename for output data +# param string optional: secret; default: it will be generated +# +# global int bDebug (0|1) +# global string line string for a line with dashes +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.%N %Z") + + +# --- generate data to hash: method + uri + timestamp; delimited with line break +data="${apiMethod} +${apiRequest} +${apiTS} +" + # these ase non critical data ... it does not show the ${secret} + if [ "$bDebug" = "1" ]; then + echo "RAW data for hashed secret:" + echo "$data" + fi + + # generate hash - split in 2 commands (piping "cut" sends additional line break) + myHash=$(echo -n "$data" | openssl dgst -sha1 -hex -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: 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. + exit 1 + 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:hl:o:p:s:u:v" option; do + case ${option} in + c) customconfig="$OPTARG" ;; + d) bDebug=1 ;; + e) export IMLCI_PHASE=$OPTARG ;; + f) export IMLCI_FILE=$OPTARG ;; + h) showhelp + exit 0 + ;; + 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 ;; + v) echo $about; exit 0 ;; + *) + 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 diff --git a/tests/getfile.sh.cfg b/tests/getfile.sh.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f614f3d13e4104fe390e6f2be7fc093510f9dfa4 --- /dev/null +++ b/tests/getfile.sh.cfg @@ -0,0 +1,4 @@ +# +IMLCI_PKG_SECRET=myapikey +IMLCI_URL=http://localhost:8001 +IMLCI_PHASE=test diff --git a/tests/readme.md b/tests/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..9d2cd996bfd3e3721c6ce2893e7dee433c558984 --- /dev/null +++ b/tests/readme.md @@ -0,0 +1,9 @@ +# Hints + +getfile.sh is part of the deployment clients that fatches the packages from package server. +To get/ update the script + +wget -O getfile.sh "https://git-repo.iml.unibe.ch/iml-open-source/imldeployment-client/-/raw/master/bin/getfile.sh?ref_type=heads" +chmod 755 getfile.sh + +see also ../docs/40_Usage.md.