From d152a516f50307b3a1de4ce38958f181aaa52bf8 Mon Sep 17 00:00:00 2001
From: Sylvester Joosten <sjoosten@anl.gov>
Date: Thu, 30 Sep 2021 16:20:58 +0000
Subject: [PATCH] Macos support

---
 README.md  |  74 ++++++-----
 install.sh | 356 ++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 286 insertions(+), 144 deletions(-)

diff --git a/README.md b/README.md
index 4a9724ab3..7b3e04d70 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,12 @@ EIC software container
 
 Simple Installation
 ------------
+
+*The environment has been tested on linux (requires singularity v3+) and MacOS (requires
+docker)*
+
+Please follow the steps below to setup and run the container in your environment.
+
 1. Create a local directory that you want to work in, e.g `$HOME/eic`, and go into this
    directory.
 ```bash
@@ -25,44 +31,19 @@ eic-shell
 4. Within your development environment (`eic-shell`), you can install software to the
    internal `$ATHENA_PREFIX`
 
-Singularity Container Dowload for Development Usage
+Singularity Container setup for Development Usage
 -------------
 **Note: this container download script is meant for expert usage. If it is unclear to you
-why you would want to do this, you are probably looking for the single installation
+why you would want to do this, you are probably looking for the simple `jug_xl` installation
 above.**
-To download the `jug_dev:testing` base image, do
-```bash
-curl https://eicweb.phy.anl.gov/containers/eic_container/-/raw/master/download_dev.sh | bash
-```
-To download the `jug_xl:nightly` image, do
+
+You can use the same install scripts to setup other container setups, including `jug_dev`
+(the main development container). Note that for `jug_dev` there is no nighlty release, and
+the appropriate version (tag) would be `testing`.  To setup the `jug_dev:testing` environment, do
 ```bash
-curl https://eicweb.phy.anl.gov/containers/eic_container/-/raw/master/download_dev.sh | bash -s -- -c jug_xl -v nightly
+curl https://eicweb.phy.anl.gov/containers/eic_container/-/raw/master/install.sh | bash -s -- -c jug_dev -v testing
 ```
 
-Using the docker container for your CI purposes
------------------------------------------------
-
-The docker containers are publicly accessible from
-[Dockerhub](https://hub.docker.com/u/eicweb). You probably want to use the default
-`jug_xl` container. Relevant versions are:
- - `eicweb/jug_xl:nightly`: nightly release, with latest detector and reconstruction
-   version. This is probably what you want to use unless you are dispatching a large
-   simulation/reconstruciton job
- - `eicweb/jug_xl:3.0-stable`: latest stable release, what you want to use for large
-   simulation jobs (for reproducibility). Please coordinate with the software group to
-   ensure all desired software changes are present in this container.
-
-1. To load the container environment in your run scripts, you have to do nothing special.  
-   The environment is already setup with good defaults, so you can use all the programs 
-   in the container as usual and assume everything needed to run the included software 
-   is already setup.  
-
-2. If using this container as a basis for a new container, you can direction access 
-   the full container environment from a docker `RUN` shell command with no further
-   action needed. For the most optimal experience, you can install your software to
-   `/usr/local` to fully integrate with the existing environment. (Note that, internally,
-   `/usr/local` is a symlink to `/opt/view`).
-
 Included software:
 ------------------
   - Included software (for the exact versions, check the file [spack.yaml](spack.yaml) or use the command `eic-info` inside the container):
@@ -103,3 +84,32 @@ Included software:
     - igprof
   - The singularity build exports the following applications:
     - eic-shell: a development shell in the image
+
+Using the docker container for your CI purposes
+-----------------------------------------------
+
+**These instructions are old and need updating. In general we recommend using
+`eicweb/juggler:latest` for most CI usages. This image is functionally identical to
+`jug_xl:nightly`**
+
+The docker containers are publicly accessible from
+[Dockerhub](https://hub.docker.com/u/eicweb). You probably want to use the default
+`jug_xl` container. Relevant versions are:
+ - `eicweb/jug_xl:nightly`: nightly release, with latest detector and reconstruction
+   version. This is probably what you want to use unless you are dispatching a large
+   simulation/reconstruciton job
+ - `eicweb/jug_xl:3.0-stable`: latest stable release, what you want to use for large
+   simulation jobs (for reproducibility). Please coordinate with the software group to
+   ensure all desired software changes are present in this container.
+
+1. To load the container environment in your run scripts, you have to do nothing special.  
+   The environment is already setup with good defaults, so you can use all the programs 
+   in the container as usual and assume everything needed to run the included software 
+   is already setup.  
+
+2. If using this container as a basis for a new container, you can direction access 
+   the full container environment from a docker `RUN` shell command with no further
+   action needed. For the most optimal experience, you can install your software to
+   `/usr/local` to fully integrate with the existing environment. (Note that, internally,
+   `/usr/local` is a symlink to `/opt/view`).
+
diff --git a/install.sh b/install.sh
index 6e31bca90..1de24d8c8 100755
--- a/install.sh
+++ b/install.sh
@@ -1,5 +1,12 @@
 #!/bin/bash
 
+## Simple setup script that installs the container
+## in your local environment under $PREFIX/local/lib
+## and creates a simple top-level launcher script
+## that launches the container for this working directory
+## with the $ATHENA_PREFIX variable pointing
+## to the $PREFIX/local directory
+
 CONTAINER="jug_xl"
 VERSION="nightly"
 PREFIX="$PWD"
@@ -10,6 +17,7 @@ function print_the_help {
   echo "          -p,--prefix     Working directory to deploy the environment (D: $PREFIX)"
   echo "          -t,--tmpdir     Change tmp directory (D: $([[ -z "$TMPDIR" ]] && echo "/tmp" || echo "$TMPDIR"))"
   echo "          -n,--no-cvmfs   Disable check for local CVMFS (D: enabled)"
+  echo "          -c,--container  Container version (D: $CONTAINER)"
   echo "          -v,--version    Version to install (D: $VERSION)"
   echo "          -h,--help       Print this message"
   echo ""
@@ -23,7 +31,7 @@ while [ $# -gt 0 ]; do
   key=$1
   case $key in
     -p|--prefix)
-      PREFIX=$2
+      PREFIX=$(realpath $2)
       shift
       shift
       ;;
@@ -37,6 +45,11 @@ while [ $# -gt 0 ]; do
       DISABLE_CVMFS_USAGE=true
       shift
       ;;
+    -c|--container)
+      CONTAINER=$2
+      shift
+      shift
+      ;;
     -v|--version)
       VERSION=$2
       shift
@@ -54,7 +67,9 @@ while [ $# -gt 0 ]; do
   esac
 done
 
+## create prefix if needed
 mkdir -p $PREFIX || exit 1
+pushd $PREFIX
 
 if [ ! -d $PREFIX ]; then
   echo "ERROR: not a valid directory: $PREFIX"
@@ -64,125 +79,123 @@ fi
 
 echo "Setting up development environment for eicweb/$CONTAINER:$VERSION"
 
-## Simple setup script that installs the container
-## in your local environment under $PREFIX/local/lib
-## and creates a simple top-level launcher script
-## that launches the container for this working directory
-## with the $ATHENA_PREFIX variable pointing
-## to the $PREFIX/local directory
+mkdir -p $PREFIX/local/lib || exit 1
 
-mkdir -p local/lib || exit 1
+function install_linux() {
+  SINGULARITY=
+  ## check for a singularity install
+  ## default singularity if new enough
+  if [ $(type -P singularity ) ]; then
+    SINGULARITY=$(which singularity)
+    SINGULARITY_VERSION=`$SINGULARITY --version`
+    if [ ${SINGULARITY_VERSION:0:1} = 2 ]; then
+      ## too old, look for something else
+      SINGULARITY=
+    fi
+  fi
+  if [ -z $SINGULARITY ]; then
+    ## first priority: a known good install (this one is on JLAB)
+    if [ -d "/apps/singularity/3.7.1/bin/" ]; then
+      SINGULARITY="/apps/singularity/3.7.1/bin/singularity"
+    ## whatever is in the path is next
+    elif [ $(type -P singularity ) ]; then
+      SINGULARITY=$(which singularity)
+    ## cvmfs singularity is last resort (sandbox mode can cause issues)
+    elif [ -f "/cvmfs/oasis.opensciencegrid.org/mis/singularity/bin/singularity" ]; then
+      SINGULARITY="/cvmfs/oasis.opensciencegrid.org/mis/singularity/bin/singularity"
+    ## not good...
+    else
+      echo "ERROR: no singularity found, please make sure you have singularity in your \$PATH"
+      exit 1
+    fi
+  fi
+  echo " - Found singularity at $SINGULARITY"
 
-SINGULARITY=
-## check for a singularity install
-## default singularity if new enough
-if [ $(type -P singularity ) ]; then
-  SINGULARITY=$(which singularity)
+  ## get singularity version
+  ## we only care if is 2.x or not, so we can use singularity --version 
+  ## which returns 2.xxxxx for version 2
   SINGULARITY_VERSION=`$SINGULARITY --version`
+  SIF=
   if [ ${SINGULARITY_VERSION:0:1} = 2 ]; then
-    ## too old, look for something else
-    SINGULARITY=
-  fi
-fi
-if [ -z $SINGULARITY ]; then
-  ## first priority: a known good install (this one is on JLAB)
-  if [ -d "/apps/singularity/3.7.1/bin/" ]; then
-    SINGULARITY="/apps/singularity/3.7.1/bin/singularity"
-  ## whatever is in the path is next
-  elif [ $(type -P singularity ) ]; then
-    SINGULARITY=$(which singularity)
-  ## cvmfs singularity is last resort (sandbox mode can cause issues)
-  elif [ -f "/cvmfs/oasis.opensciencegrid.org/mis/singularity/bin/singularity" ]; then
-    SINGULARITY="/cvmfs/oasis.opensciencegrid.org/mis/singularity/bin/singularity"
-  ## not good...
-  else
-    echo "ERROR: no singularity found, please make sure you have singularity in your \$PATH"
-    exit 1
-  fi
-fi
-echo " - Found singularity at $SINGULARITY"
-
-## get singularity version
-## we only care if is 2.x or not, so we can use singularity --version 
-## which returns 2.xxxxx for version 2
-SINGULARITY_VERSION=`$SINGULARITY --version`
-SIF=
-if [ ${SINGULARITY_VERSION:0:1} = 2 ]; then
-  SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}.simg"
-
-  echo "WARNING: your singularity version $SINGULARITY_VERSION is ancient, we strongly recommend using version 3.x"
-  echo "We will attempt to use a fall-back SIMG image to be used with this singularity version"
-  if [ -f /gpfs02/eic/athena/${CONTAINER}-${VERSION}.simg ]; then
-    ln -sf /gpfs02/eic/athena/${CONTAINER}-${VERSION}.simg ${SIF}
+    SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}.simg"
+
+    echo "WARNING: your singularity version $SINGULARITY_VERSION is ancient, we strongly recommend using version 3.x"
+    echo "We will attempt to use a fall-back SIMG image to be used with this singularity version"
+    if [ -f /gpfs02/eic/athena/${CONTAINER}-${VERSION}.simg ]; then
+      ln -sf /gpfs02/eic/athena/${CONTAINER}-${VERSION}.simg ${SIF}
+    else
+      echo "Attempting last-resort singularity pull for old image"
+      echo "This may take a few minutes..."
+      INSIF=`basename ${SIF}`
+      singularity pull --name "${INSIF}" docker://eicweb/$CONTAINER:$VERSION
+      mv ${INSIF} $SIF
+      chmod +x ${SIF}
+      unset INSIF
+    fi
+  ## we are in sane territory, yay!
   else
-    echo "Attempting last-resort singularity pull for old image"
-    echo "This may take a few minutes..."
-    INSIF=`basename ${SIF}`
-    singularity pull --name "${INSIF}" docker://eicweb/$CONTAINER:$VERSION
-    mv ${INSIF} $SIF
-    chmod +x ${SIF}
-    unset INSIF
+    ## check if we can just use cvmfs for the image
+    SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}.sif"
+    if [ -z "$DISABLE_CVMFS_USAGE" -a -d /cvmfs/singularity.opensciencegrid.org/eicweb/${CONTAINER}:${VERSION} ]; then
+      SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}"
+      ## need to cleanup in this case, else it will try to make a subdirectory
+      rm -rf ${SIF}
+      ln -sf /cvmfs/singularity.opensciencegrid.org/eicweb/${CONTAINER}:${VERSION} ${SIF}
+    elif [ -f /cvmfs/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ]; then
+      ln -sf /cvmfs/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ${SIF}
+    elif [ -f /gpfs02/cvmfst0/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ]; then
+      ln -sf /gpfs02/cvmfst0/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ${SIF}
+    ## check if we have an internal CI image we will use for testing purposes
+    elif [ -f $PWD/.gitlab-ci/${CONTAINER}-${VERSION}.sif ]; then
+      ln -sf $PWD/.gitlab-ci/${CONTAINER}-${VERSION}.sif ${SIF}
+    ## if not, download the container to the system
+    else
+      ## get the python installer and run the old-style install
+      ## work in temp directory
+      tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
+      pushd $tmp_dir
+      wget https://eicweb.phy.anl.gov/containers/eic_container/-/raw/master/install.py
+      chmod +x install.py
+      ./install.py -f -c $CONTAINER -v $VERSION .
+      INSIF=lib/`basename ${SIF}`
+      mv $INSIF $SIF
+      chmod +x ${SIF}
+      ## cleanup
+      popd
+      rm -rf $tmp_dir
+      unset INSIF
+    fi
   fi
-## we are in sane territory, yay!
-else
-  ## check if we can just use cvmfs for the image
-  SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}.sif"
-  if [ -z "$DISABLE_CVMFS_USAGE" -a -d /cvmfs/singularity.opensciencegrid.org/eicweb/${CONTAINER}:${VERSION} ]; then
-    SIF="$PREFIX/local/lib/${CONTAINER}-${VERSION}"
-    ## need to cleanup in this case, else it will try to make a subdirectory
-    rm -rf ${SIF}
-    ln -sf /cvmfs/singularity.opensciencegrid.org/eicweb/${CONTAINER}:${VERSION} ${SIF}
-  elif [ -f /cvmfs/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ]; then
-    ln -sf /cvmfs/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ${SIF}
-  elif [ -f /gpfs02/cvmfst0/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ]; then
-    ln -sf /gpfs02/cvmfst0/eic.opensciencegrid.org/singularity/athena/${CONTAINER}_v${VERSION}.sif ${SIF}
-  ## check if we have an internal CI image we will use for testing purposes
-  elif [ -f $PWD/.gitlab-ci/${CONTAINER}-${VERSION}.sif ]; then
-    ln -sf $PWD/.gitlab-ci/${CONTAINER}-${VERSION}.sif ${SIF}
-  ## if not, download the container to the system
+
+  echo $SIF
+  ls $SIF 2>&1 > /dev/null && GOOD_SIF=1 
+  if [ -z "$SIF" -o -z "$GOOD_SIF" ]; then
+    echo "ERROR: no singularity image found"
+    exit 1
   else
-    ## get the python installer and run the old-style install
-    ## work in temp directory
-    tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
-    pushd $tmp_dir
-    wget https://eicweb.phy.anl.gov/containers/eic_container/-/raw/master/install.py
-    chmod +x install.py
-    ./install.py -f -c $CONTAINER -v $VERSION .
-    INSIF=lib/`basename ${SIF}`
-    mv $INSIF $SIF
-    chmod +x ${SIF}
-    ## cleanup
-    popd
-    rm -rf $tmp_dir
-    unset INSIF
+    echo " - Deployed ${CONTAINER} image: $SIF"
   fi
-fi
 
-echo $SIF
-ls $SIF 2>&1 > /dev/null && GOOD_SIF=1 
-if [ -z "$SIF" -o -z "$GOOD_SIF" ]; then
-  echo "ERROR: no singularity image found"
-  exit 1
-else
-  echo " - Deployed ${CONTAINER} image: $SIF"
-fi
+  ## We want to make sure the root directory of the install directory
+  ## is always bound. We also check for the existence of a few standard
+  ## locations (/scratch /volatile /cache) and bind those too if found
+  echo " - Determining additional bind paths"
+  PREFIX_ROOT="/$(realpath $PREFIX | cut -d "/" -f2)"
+  BINDPATH=$PREFIX_ROOT
+  echo "   --> $PREFIX_ROOT"
+  for dir in /work /scratch /volatile /cache; do
+    ## only add directories once
+    if [[ ${BINDPATH} =~ $(basename $dir) ]]; then
+      continue
+    fi
+    if [ -d $dir ]; then
+      echo "   --> $dir"
+      BINDPATH="${BINDPATH},$dir"
+    fi
+  done
 
-## We want to make sure the root directory of the install directory
-## is always bound. We also check for the existence of a few standard
-## locations (/scratch /volatile /cache) and bind those too if found
-echo " - Determining additional bind paths"
-PREFIX_ROOT="/$(realpath $PREFIX | cut -d "/" -f2)"
-BINDPATH=$PREFIX_ROOT
-echo "   --> $PREFIX_ROOT"
-for dir in /work /scratch /volatile /cache; do
-  if [ -d $dir ]; then
-    echo "   --> $dir"
-    BINDPATH="${BINDPATH},$dir"
-  fi
-done
-
-## create a new top-level eic-shell launcher script
-## that sets the ATHENA_PREFIX and then starts singularity
+  ## create a new top-level eic-shell launcher script
+  ## that sets the ATHENA_PREFIX and then starts singularity
 cat << EOF > eic-shell
 #!/bin/bash
 
@@ -270,8 +283,127 @@ export SINGULARITY_BINDPATH=$BINDPATH
 $SINGULARITY exec $SIF eic-shell \$@
 EOF
 
-chmod +x eic-shell
+  chmod +x eic-shell
+
+  echo " - Created custom eic-shell excecutable"
+}
+
+function install_macos() {
+  ## check for docker install
+  DOCKER=$(which docker)
+  if [ -z ${DOCKER} ]; then
+    echo "ERROR: no docker install found, docker is required for running on MacOS"
+  fi
+  echo " - Found docker at ${DOCKER}"
+
+  IMG=eicweb/${CONTAINER}:${VERSION}
+  docker pull ${IMG}
+  echo " - Deployed ${CONTAINER} image: ${IMG}"
+
+  ## We want to make sure the root directory of the install directory
+  ## is always bound. We also check for the existence of a few standard
+  ## locations (/Volumes /Users /tmp) and bind those too if found
+  echo " - Determining mount paths"
+  PREFIX_ROOT="/$(realpath $PREFIX | cut -d "/" -f2)"
+  MOUNT=""
+  echo "   --> $PREFIX_ROOT"
+  for dir in /Volumes /Users /tmp; do
+    ## only add directories once
+    if [[ ${MOUNT} =~ $(basename $dir) ]]; then
+      continue
+    fi
+    if [ -d $dir ]; then
+      echo "   --> $dir"
+      MOUNT="$MOUNT -v $dir:$dir"
+    fi
+  done
+  echo " - Docker mount directive: '$MOUNT'"
+
+  ## create a new top-level eic-shell launcher script
+  ## that sets the ATHENA_PREFIX and then starts singularity
+cat << EOF > eic-shell
+#!/bin/bash
+
+## capture environment setup for upgrades
+CONTAINER=$CONTAINER
+TMPDIR=$TMPDIR
+VERSION=$VERSION
+PREFIX=$PREFIX
+DISABLE_CVMFS_USAGE=${DISABLE_CVMFS_USAGE}
+
+function print_the_help {
+  echo "USAGE:  ./eic-shell [OPTIONS] [ -- COMMAND ]"
+  echo "OPTIONAL ARGUMENTS:"
+  echo "          -u,--upgrade    Upgrade the container to the latest version"
+  echo "          -h,--help       Print this message"
+  echo ""
+  echo "  Start the eic-shell containerized software environment."
+  echo ""
+  echo "EXAMPLES: "
+  echo "  - Start an interactive shell: ./eic-shell" 
+  echo "  - Upgrade the container:      ./eic-shell --upgrade"
+  echo "  - Execute a single command:   ./eic-shell -- <COMMAND>"
+  echo ""
+  exit
+}
+
+UPGRADE=
+
+while [ \$# -gt 0 ]; do
+  key=\$1
+  case \$key in
+    -u|--upgrade)
+      UPGRADE=1
+      shift
+      ;;
+    -h|--help)
+      print_the_help
+      exit 0
+      ;;
+    --)
+      shift
+      break
+      ;;
+    *)
+      echo "ERROR: unknown argument: \$key"
+      echo "use --help for more info"
+      exit 1
+      ;;
+  esac
+done
+
+if [ ! -z \${UPGRADE} ]; then
+  echo "Upgrading eic-shell..."
+  docker pull $IMG || exit 1
+  echo "eic-shell upgrade sucessful"
+  exit 0
+fi
+
+docker run $MOUNT -w=$PWD -it --rm -e ATHENA_PREFIX=$PREFIX/local $IMG eic-shell \$@
+EOF
+
+  chmod +x eic-shell
+
+  echo " - Created custom eic-shell excecutable"
+}
+
+## detect OS
+OS=`uname -s`
+case ${OS} in
+  Linux)
+    echo " - Detected OS: Linux"
+    install_linux
+    ;;
+  Darwin)
+    echo " - Detected OS: MacOS"
+    install_macos
+    ;;
+  *)
+    echo "ERROR: OS '${OS}' not currently supported"
+    exit 1
+    ;;
+esac
 
-echo " - Created custom eic-shell excecutable"
+popd
 echo "Environment setup succesfull"
 echo "You can start the development environment by running './eic-shell'"
-- 
GitLab