diff --git a/R/defaults/main.yml b/R/defaults/main.yml index a9a3abb9..957e2008 100644 --- a/R/defaults/main.yml +++ b/R/defaults/main.yml @@ -21,6 +21,15 @@ r_packages_main_state: present r_packages_state: '{{ r_packages_main_state }}' r_plugins_from_deb: True r_packages_cleanup: False +r_packages_updater: False +# They need to be flat text files available via http +# 1 package per line +#r_debian_packages_list_url +# package[:cran mirror] +# The CRAN mirror URL is optional +#r_cran_packages_list_url +# user/package_name +#r_github_packages_list_url r_source_plugins_dest_dir: /var/cache/R diff --git a/R/tasks/main.yml b/R/tasks/main.yml index b03dddba..8a22d0bf 100644 --- a/R/tasks/main.yml +++ b/R/tasks/main.yml @@ -2,3 +2,4 @@ - include: r-packages_cleanup.yml when: r_packages_cleanup - include: r-installation.yml +- include: r-packages-updater.yml diff --git a/R/tasks/r-packages-updater.yml b/R/tasks/r-packages-updater.yml new file mode 100644 index 00000000..97a1f6f3 --- /dev/null +++ b/R/tasks/r-packages-updater.yml @@ -0,0 +1,27 @@ +--- +- block: + - name: Install the R packages updater script + template: src=update_r_packages.sh.j2 dest=/usr/local/bin/update_r_packages owner=root group=root mode=0755 + + - name: Cron job that installs new R packages, if any + cron: name="install new R packages" user=root cron_file=install-r-packages minute="*/10" job="/usr/local/bin/update_r_packages install" state=present + + - name: Cron job that upgrades existing R packages and installs new ones, if any + cron: name="install new R packages" user=root cron_file=upgrade-r-packages hour="3" job="/usr/local/bin/update_r_packages upgrade" state=present + + when: r_packages_updater + tags: [ 'r_software', 'r_pkg', 'r_plugins', 'r_plugins_github', 'r_cran_pkgs', 'r_github_pkgs' ] + + +- block: + - name: Remove the R packages updater script + file: dest=/usr/local/bin/update_r_packages state=absent + + - name: Remove the cron job that installs new R packages + cron: name="install new R packages" user=root minute="*/10" cron_file=install-r-packages job="/usr/local/bin/update_r_packages install" state=absent + + - name: Remove the cron job that upgrades existing R packages and installs new ones + cron: name="install new R packages" user=root cron_file=upgrade-r-packages hour="3" job="/usr/local/bin/update_r_packages upgrade" state=absent + + when: not r_packages_updater + tags: [ 'r_software', 'r_pkg', 'r_plugins', 'r_plugins_github', 'r_cran_pkgs', 'r_github_pkgs' ] diff --git a/R/templates/Rprofile.site.j2 b/R/templates/Rprofile.site.j2 index 660168d7..3a6136d4 100644 --- a/R/templates/Rprofile.site.j2 +++ b/R/templates/Rprofile.site.j2 @@ -4,26 +4,9 @@ ## Copyright (C) 2008 Dirk Eddelbuettel and GPL'ed ## ## see help(Startup) for documentation on ~/.Rprofile and Rprofile.site - # - # NOTE: managed by ansible - # - -# ## Example of .Rprofile -# options(width=65, digits=5) -# options(show.signif.stars=FALSE) -# setHook(packageEvent("grDevices", "onLoad"), -# function(...) grDevices::ps.options(horizontal=FALSE)) -# set.seed(1234) -# .First <- function() cat("\n Welcome to R!\n\n") -# .Last <- function() cat("\n Goodbye!\n\n") - -# ## Example of Rprofile.site -# local({ -# # add MASS to the default packages, set a CRAN mirror -# old <- getOption("defaultPackages"); r <- getOption("repos") -# r["CRAN"] <- "http://my.local.cran" -# options(defaultPackages = c(old, "MASS"), repos = r) -#}) +# +# NOTE: managed by ansible +# local({r <- getOption("repos") r["CRAN"] <- "{{ r_cran_mirror_site }}" options(repos=r) diff --git a/R/templates/update_r_packages.sh.j2 b/R/templates/update_r_packages.sh.j2 new file mode 100644 index 00000000..029573eb --- /dev/null +++ b/R/templates/update_r_packages.sh.j2 @@ -0,0 +1,177 @@ +#!/bin/bash + +RETVAl= +PARAMS=$# +ACTION=$1 +PROCNUM=$$ +OLDPROC= +OLDPROC_RUNNING= +LOCKDIR=/var/run +LOCK_FILE=$LOCKDIR/.update_r_pkgs.lock +TMP_FILES_DIR=/var/tmp/r_pkgs_update +# We cannot answer questions +DEBIAN_FRONTEND=noninteractive +R_CRAN_MIRROR={{ r_cran_mirror_site }} +# - debian packages list format: +# one package per line +DEB_PKGS_SKIP=0 +DEBIAN_PKGS_LIST_URL={{ r_debian_packages_list_url | default('') }} +PKGS_LIST= +# - R packages list format: +# name[:mirror] +CRAN_PKGS_SKIP=0 +R_PKGS_LIST_URL={{ r_cran_packages_list_url | default('') }} +R_PKGS_LIST= +# - R packages from github list format: +# - owner/package +GITHUB_PKGS_SKIP=0 +R_PKGS_FROM_GITHUB_LIST_URL={{ r_github_packages_list_url | default('') }} +R_PKGS_GITHUB= + +trap "{ logger 'update_r_packages: trap intercepted, exiting.' ; cleanup ; exit 15 }" SIGHUP SIGINT SIGTERM + +function cleanup() { + logger "update_r_packages: cleaning up" + rm -f $LOCK_FILE + rm -fr $TMP_FILES_DIR +} + +function usage() { + if [ $PARAMS -ne 1 ] ; then + echo "Need at least an argument: 'upgrade' or 'install'." + echo "- 'upgrade' installs new packages and upgrades the existin ones when needed." + echo "- 'install' installs new packages." + cleanup + exit 1 + fi +} + +function get_args() { + if [ "$ACTION" != "upgrade" -a "$ACTION" != "install" ] ; then + usage + fi +} + +function fail() { + logger "Something went wrong, exiting." + cleanup + exit 1 +} + + +function init_env() { + if [ -f $LOCK_FILE ] ; then + OLDPROC=$( cat $LOCK_FILE ) + OLDPROC_RUNNING=$( ps auwwx | grep -v grep | grep $OLDPROC ) + RETVAL=$? + if [ $RETVAL -eq 0 ] ; then + logger "update_r_packages: $OLDPROC_RUNNING" + logger "update_r_packages: another process is running, exiting." + exit 0 + else + logger "update_r_packages: lock file exist but the process not. Continuing." + rm -fr $TMP_FILES_DIR + fi + fi + RETVAL= + echo "$PROCNUM" > $LOCK_FILE + mkdir -p $TMP_FILES_DIR +} + +function get_data_files() { + # Get the packages list + if [ -z $DEBIAN_PKGS_LIST_URL ] ; then + DEB_PKGS_SKIP=1 + logger "update_r_packages: the debian packages list is not available." + else + PKGS_LIST=$( mktemp $TMP_FILES_DIR/rdebs.XXXXXXX ) + logger "update_r_packages: getting the debian packages list." + wget -q -o /dev/null -O $PKGS_LIST $DEBIAN_PKGS_LIST_URL + fi + if [ -z $R_PKGS_LIST_URL ] ; then + CRAN_PKGS_SKIP=1 + logger "update_r_packages: the CRAN packages list is not available." + else + R_PKGS_LIST=$( mktemp $TMP_FILES_DIR/rpkgs.XXXXXXX ) + logger "update_r_packages: getting the R packages list that will be installed from CRAN" + wget -q -o /dev/null -O $R_PKGS_LIST $R_PKGS_LIST_URL + fi + if [ -z $R_PKGS_FROM_GITHUB_LIST_URL ] ; then + GITHUB_PKGS_SKIP=1 + logger "update_r_packages: the Github packages list is not available." + else + R_PKGS_GITHUB=$( mktemp $TMP_FILES_DIR/rpkgsgithub.XXXXXXX ) + logger "update_r_packages: getting the R packages list that will be installed from github" + wget -q -o /dev/null -O $R_PKGS_GITHUB $R_PKGS_FROM_GITHUB_LIST_URL + fi +} + +function debian_pkgs() { + if [ $DEB_PKGS_SKIP -eq 0 ] ; then + # Update the apt cache and install the packages in non interactive mode + logger "update_r_packages: Installing the debian dependencies" + if [ -z "$(find /var/cache/apt/pkgcache.bin -mmin -360)" ]; then + apt-get update -q >/dev/null 2>&1 + else + logger "update_r_packages: APT cache not updated" + fi + xargs -a <(awk '/^\s*[^#]/' "$PKGS_LIST") -r -- apt-get install -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" + else + logger "update_r_packages: skipping the debian packages installation" + fi +} + +function r_cran_pkgs() { + if [ $CRAN_PKGS_SKIP -eq 0 ] ; then + logger "update_r_packages: Installing R packages from CRAN" + for l in $( cat $R_PKGS_LIST ) ; do + pkg=$( echo $l | cut -d : -f 1 ) + is_mirror_ret= + is_mirror=$( echo $l | grep ':' ) + is_mirror_ret=$? + if [ $is_mirror_ret -eq 0 ] ; then + mirror=$( echo $l | cut -d : -f 2 ) + else + mirror=$R_CRAN_MIRROR + fi + if [ "$ACTION" == "upgrade" ] ; then + Rscript --slave --no-save --no-restore-history -e "install.packages(pkgs='$pkg', repos=c('$mirror/'));" + else + Rscript --slave --no-save --no-restore-history -e "if (! ('$pkg' %in% installed.packages()[,'Package'])) { install.packages(pkgs='$pkg', repos=c('$mirror/')); }" + fi + done + else + logger "update_r_packages: skipping the R CRAN packages installation" + fi +} + +function r_github_pkgs() { + if [ $GITHUB_PKGS_SKIP -eq 0 ] ; then + logger "update_r_packages: Installing R packages from Github" + for l in $( cat $R_PKGS_GITHUB ) ; do + pkg=$( echo $l | cut -d "/" -f 2 ) + user=$( echo $l | cut -d "/" -f 1 ) + if [ "$ACTION" == "upgrade" ] ; then + Rscript --slave --no-save --no-restore-history -e "require(devtools); require(methods); install_github('$l');" + else + Rscript --slave --no-save --no-restore-history -e "if (! ('$pkg' %in% installed.packages()[,'Package'])) { require(devtools); require(methods) ; install_github('$l'); }" + fi + done + else + logger "update_r_packages: skipping the R GitHub packages installation" + fi +} + +######### +# Main +# + +usage +get_args +init_env +get_data_files +debian_pkgs +r_cran_pkgs +r_github_pkgs +cleanup +exit 0