diff --git a/bin/scitas-motd-update b/bin/scitas-motd-update old mode 100644 new mode 100755 index 2926dd7..bf14494 --- a/bin/scitas-motd-update +++ b/bin/scitas-motd-update @@ -1,78 +1,150 @@ #!/bin/bash +### Global variables +APPNAME="$(basename ${0})" +PID="${$}" + +### Functions +# Logging template +log() { echo "$(date) $(hostname -s) ${APPNAME}[${PID}]: ${1}" > /dev/${2:-stdout}; } + +### locking wizardry taken from https://gist.github.com/przemoc/571091 + +## Copyright (C) 2009 Przemyslaw Pawelczyk +## License: GNU General Public License v2, v3 +# +# Lockable script boilerplate + +### HEADER ### + +if [ -w /var/lock ] +then + LOCKFILE="/var/lock/`basename $0`" +else + LOCKFILE="/tmp/`basename $0`.lock" +fi +LOCKFD=99 + +# PRIVATE +_lock() { flock -$1 $LOCKFD; } +_no_more_locking() { _lock u; _lock xn && rm -f $LOCKFILE; } +_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; } + +# ON START +_prepare_locking + +# PUBLIC +exlock_now() { _lock xn; } # obtain an exclusive lock immediately or fail +exlock() { _lock x; } # obtain an exclusive lock +shlock() { _lock s; } # obtain a shared lock +unlock() { _lock u; } # drop a lock + +### BEGIN OF SCRIPT ### + +# Simplest example is avoiding running multiple instances of script. +if ! exlock_now +then + log "failed to aquire lock. Exiting!" + exit 1 +fi + +# Remember! Lock file is removed when one of the scripts exits and it is +# the only script holding the lock or lock is not acquired at all. + +### End of locking wizardry + # Location of the configuration file -SMOTD_CONFIG="../etc/scitas-motd.conf" +SMOTD_CONFIG=${SMOTD_CONFIG:-/etc/scitas-motd.conf} -# Read configuration values +# Read configuration options if [ -r ${SMOTD_CONFIG} ] then . ${SMOTD_CONFIG} fi -# Check that all the required values are set -REQUIRED_OPTIONS="SMOTD_GITREPO" +# Check that all the required configuration options are set +REQUIRED_OPTIONS="SMOTD_URL" MISSING_OPTION=false for option in ${REQUIRED_OPTIONS} do if [ ! -v ${option} ] then - echo "[ERROR] Missing configuration value: '${option}'" > /dev/stderr + log "[ERROR] Missing configuration value: '${option}'" stderr MISSING_OPTION=true fi done if ${MISSING_OPTION} then - echo "[ERROR] Missing configuration options, update ${SMOTD_CONFIG}" > /dev/stderr + log "[ERROR] Missing configuration options, update ${SMOTD_CONFIG}" stderr exit 1 fi -# Check if git is available -SMOTD_GIT=${SMOTD_GIT:-git} -${SMOTD_GIT} --version 1&>2 /dev/null +# Set every other option to the defaults +SMOTD=${SMOTD:-/etc/motd.scitas} +SMOTD_CURL=${SMOTD_CURL:-curl} +SMOTD_CURL_OPT=${SMOTD_CURL_OPT:-"--location --fail --silent --max-time 30"} +SMOTD_CURL_SUFFIX=${SMOTD_CURL_SUFFIX} +SMOTD_WORKDIR=${SMOTD_WORKDIR:-/var/run/scitas-motd} + +# Check if curl is available +${SMOTD_CURL} --version 2>&1 > /dev/null if [ ! $? ] then - echo "[ERROR] git (${SMOTD_GIT}) not available!" > /dev/stderr + log "[ERROR] curl (${SMOTD_CURL}) not available!" stderr exit 1 fi -# -# Checkout the repository and/or update it -# -SMOTD_GITDIR=${SMOTD_GITDIR:-/var/lib/scitas-motd} -if [ -v ${SMOTD_GITBRANCH} ] +# Getting the list of basenames for the fragments +rm -f "${SMOTD_WORKDIR}/fragments" +mkdir -p ${SMOTD_WORKDIR} +${SMOTD_CURL} ${SMOTD_CURL_OPT} \ + "${SMOTD_URL}/fragments${SMOTD_CURL_SUFFIX}" \ + --output "${SMOTD_WORKDIR}/fragments" 2>&1 > /dev/null +if [ ! $? ] then - GIT_BRANCH_OPT="--branch ${SMOTD_GITBRANCH}" -else - GIT_BRANCH_OPT="" + log "[ERROR] Failed to get the fragments list from: ${SMOTD_URL}" stderr + exit 1 fi -if [ -d ${SMOTD_GITDIR} && ! -d ${SMOTD_GITDIR}/.git ] || [ ! -a ${SMOTD_GITDIR} ] -then - # Assuming it's either an empty directory, or it does not exist - ${SMOTD_GIT} clone ${GIT_BRANCH_OPT} ${SMOTD_GITREPO} ${SMOTD_GITDIR} - RC=$? - if ! ${RC} +# Getting the fragments, all the listed fragments listed are mandatory +while read frag +do + FOUND=false + # from general to more specific, more specific wins + for suffix in '' ".${SMOTD_CLUSTER}" ".$(hostname -s)" + do + ${SMOTD_CURL} ${SMOTD_CURL_OPT} \ + "${SMOTD_URL}/${frag}${suffix}${SMOTD_CURL_SUFFIX}" \ + --output "${SMOTD_WORKDIR}/${frag}" 2>&1 > /dev/null \ + && FOUND=true + done + # it's ok as long as any one of the fragments is found + if ! ${FOUND} then - echo "[ERROR] Error while cloning repository. Maybe ${SMOTD_GITDIR} is not empty?" > /dev/stderr + log "[ERROR] Couldn't get the fragment '${frag}' from ${SMOTD_URL}" stderr exit 1 fi -elif [ -d ${SMOTD_GITDIR} && -d ${SMOTD_GITDIR}/.git ] +done < "${SMOTD_WORKDIR}/fragments" + +currtime=$(date +%Y%m%d.%H%M%S) +tmpmotd="${SMOTD_WORKDIR}/motd.scitas.${currtime}" + +rm -f "${tmpmotd}" +mkdir -p $(dirname "${tmpmotd}") +echo "###########################################################" \ + >> "${tmpmotd}" +while read frag +do + cat "${SMOTD_WORKDIR}/${frag}" >> "${tmpmotd}" + echo "###########################################################" \ + >> "${tmpmotd}" +done < "${SMOTD_WORKDIR}/fragments" + +if ! diff --brief --new-file ${SMOTD} ${tmpmotd} > /dev/null then - # Assuming it already exists and is a git repo - GIT_OPTIONS="--git-dir=${SMOTD_GITDIR}/.git --work-tree=${SMOTD_GITDIR}" - # For safety let's reset the origin URL - # TODO: check return codes - ${SMOTD_GIT} ${GIT_OPTIONS} remote origin set-url ${SMOTD_GITREPO} - ${SMOTD_GIT} ${GIT_OPTIONS} fetch origin - - # TODO: test corner cases (different states of the repo) - GIT_REF=${SMOTD_GIT} ${GIT_OPTIONS} show-ref --hash refs/remotes/origin/${SMOTD_GITBRANCH:-HEAD} - ${SMOTD_GIT} ${GIT_OPTIONS} reset --quiet --hard ${GIT_REF} + mv "${tmpmotd}" ${SMOTD} else - # It must already exist and not be a directory - echo "[ERROR] ${SMOTD_GITDIR} exists and is not a directory!" > /dev/sdterr - exit 1 + rm -f "${tmpmotd}" fi - exit 0 diff --git a/etc/scitas-motd.conf b/etc/scitas-motd.conf index be163b5..cc43320 100644 --- a/etc/scitas-motd.conf +++ b/etc/scitas-motd.conf @@ -1,26 +1,32 @@ -# This file contains the configuration for the scitas-motd tools -# The only mandatory option is the remote Git repository containing the MOTDs +## This file contains the configuration for the scitas-motd tools +## The only mandatory option is the remote Git repository containing the MOTDs -# working mode (options: web|git) -SMOTD_MODE=web +## (NOT USED) working mode (options: web) +# SMOTD_MODE=web -# git executable to use -# SMOTD_GIT=git +## the remote url repository to use +SMOTD_URL=https://scitasadm.epfl.ch/scitas-motd/ -# the remote git repository to use -SMOTD_GITREPO=git@c4science.ch:scitas/scitas-motd +## Where the downloaded fragments are stored, this is disposable as +## the fragments are always re-downloaded. +# SMOTD_WORKDIR=/var/run/scitas-motd -# the branch to checkout -# SMOTD_GITBRANCH=master +## the file to be created by merging the different levels of MOTD +# SMOTD=/etc/motd.scitas -# the path into which to checkout the repository -# beware git clone will create any missing directories in the path -# SMOTD_GITWORKDIR=/var/lib/scitas-motd -SMOTD_GITWORKDIR=/home/rmsilva/tmp/var/run/scitas-motd +## curl-compatible binary for downloads +# SMOTD_CURL=curl -# the file to be created by merging the different levels of MOTD -# SMOTD=/etc/motd.scitas -SMOTD=/home/rmsilva/tmp/etc/motd.scitas +## curl options: +# --location # follow redirects +# --fail # try to handle 404 responses at least +# --silent # do not output anything +# --max-time 30 # take at most 30 seconds for the command +# SMOTD_CURL_OPT="--location --fail --silent --max-time 30" + +## the suffix allows us to work through some quirks of c4science for example +# SMOTD_CURL_SUFFIX="?view=raw" # the c4science suffix which gives a raw file +# SMOTD_CURL_SUFFIX="" -# the cluster name +## the cluster name # SMOTD_CLUSTER=deneb