datatracker/docker/run
Henrik Levkowetz ff7571f6e8 Merged in [17486] from valery@smyslov.net:
Add docker/run modifications to support Cygwin.
 - Legacy-Id: 17506
Note: SVN reference [17486] has been migrated to Git commit f89dd2da7b
2020-03-22 16:29:11 +00:00

255 lines
8.3 KiB
Bash
Executable file

#!/bin/bash
version=0.10
program=${0##*/}
progdir=${0%/*}
if [ "$progdir" = "$program" ]; then progdir="."; fi
if [ "$progdir" = "." ]; then progdir="$PWD"; fi
parent=$(dirname $progdir)
if [ "$parent" = "." ]; then parent="$PWD"; fi
# ----------------------------------------------------------------------
function usage() {
cat <<EOF
NAME
$program - Run a docker datatracker container with suitable settings
SYNOPSIS
$program [OPTIONS] ARGS
DESCRIPTION
This is a wrapper which runs docker with suitable arguments on a
debian-based docker image which has been set up with the dependencies
needed to easily run the IETF datatracker in development mode. By
default, it expects to find the MySQL database files at
$parent/data/mysql, which is mapped inside the
container to /var/lib/mysql, and it will set up a home directory for
the current user ($USER) and map it to $HOME.
EOF
echo -e "OPTIONS"
if [ "$(uname)" = "Linux" ]; then
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | tr -s "\t|" "\t," | sed -r -e 's/\)[ \t]+([A-Z]+)=\$2[^#]*#/=\1\t/' -e 's/\)[^#]*#/\t/'
else
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | sed 's/\|.*\$2[^#]*#/ /'| sed -E 's/\|.*\)[^#]*#/ /'
fi
cat <<EOF
FILES
AUTHOR
Written by Henrik Levkowetz, <henrik@levkowetz.com>
COPYRIGHT
Copyright (c) 2015 IETF Trust and the persons identified as authors of
the code. All rights reserved. License 'Simplified BSD', as specified
in http://opensource.org/licenses/BSD-3-Clause.
EOF
}
# ----------------------------------------------------------------------
function die() {
echo -e "\n$program: error: $*" >&2
exit 1
}
function note() {
if [ -n "$VERBOSE" ]; then echo -e "$*"; fi
}
# ----------------------------------------------------------------------
function version() {
echo -e "$program $version"
}
# ----------------------------------------------------------------------
trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR
# ----------------------------------------------------------------------
# Option parsing
# Options
shortopts=dhi:m:Mp:r:t:vVu:
longopts=download-data,help,ietfdb-url=,mysqldata=,no-mysqldir,port=,docker-repo=,tag=,verbose,version,user=,
# Default values
MYSQLDIR=$parent/data/mysql
FILEDIR=$parent/../data/
PORT=8000
REPO="ietf/datatracker-environment"
DBURL=https://www.ietf.org/lib/dt/sprint/ietf_utf8.bin.tar.bz2
WHO=$(whoami)
WHOUID=$(id -u $WHO)
WHOGID=$(id -g $WHO)
if [ "$(uname)" = "Linux" ]; then
args=$(getopt -o "$shortopts" --long "$longopts" -n '$program' -- $SV "$@")
if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi
eval set -- "$args"
sed="sed -r"
else
# Darwin, BSDs
args=$(getopt -o$shortopts $SV $*)
if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi
set -- $args
sed="sed -E"
fi
while true ; do
case "$1" in
-d| --download-data) DOWNLOAD=1;; # Download and set up the database files
-h| --help) usage; exit;; # Show this help, then exit
-f| --filedir) FILEDIR=$2; shift;; # Set the desired location of drafts, charters etc.
-i| --ietfdb-url) DBURL=$2; shift;; # Use an alternative database tarball URL
-m| --mysqldir) MYSQLDIR=$2; shift;; # Set the desired location of MySQL's database files
-p| --port) PORT=$2; shift;; # Bind the container's port 8000 to external port PORT
-r| --docker-repo) REPO=$2; shift;; # Use the given docker repository, instead of the default
-t| --tag) TAG=$2; shift;; # Use this docker image tag, instead of the svn branch name
-u| --user) WHO=$2; shift;; # Run the container as the specified user
-v| --verbose) VERBOSE=1;; # Be more talkative
-V| --version) version; exit;; # Show program version, then exit
--) shift; break;;
*) die "Internal error, inconsistent option specification: '$1'";;
esac
shift
done
if [ -z "$TAG" ]; then
TAG=$(basename $(svn info $parent | grep ^URL | awk '{print $2}'))
fi
# ----------------------------------------------------------------------
# The program itself
[ -f /proc/1/cgroups ] && grep 'docker' /proc/1/cgroups && die "It looks like you're inside docker already ..."
if [ "$(uname)" = "Darwin" ]; then
APP="/Applications/Docker.app"
CMD="open -a"
elif [ "$(uname)" = "Linux" ]; then
echo "Running on Linux."
elif [[ $(uname) =~ CYGWIN.* ]]; then
echo "Running under Cygwin."
APP="Don't know how to start Docker when running under Cygwin"
CMD="echo"
MYSQLDIR=$(echo $MYSQLDIR | sed -e 's/^\/cygdrive\/\(.\)/\1:/')
WHO=$(echo $WHO | sed -e 's/^.*\\//' | tr -d \\r)
else
die "This script does not have support for your architecture ($(uname)); sorry :-("
fi
if [ "$(uname)" = "Linux" ]; then
echo "Not trying to start a virtual docker machine on Linux"
elif [ -e "$APP" ]; then
info=$(docker info 2>&1 || true)
if ! docker info 1> /dev/null 2>&1; then
echo -e "The docker VM doesn't seem to be running; docker info gave:\n $info"
echo "Will attempt to start docker by doing '\$ $CMD $APP':"
$CMD $APP
declare -i count
printf "Waiting for docker engine .."
while true; do
printf "."
sleep 2
if docker info >/dev/null 2>&1; then break; fi
count=$(( $count + 1))
if [ $count -gt 10 ]; then
die "No contact with docker engine; bailing out."
fi
done
fi
URL="http://localhost:$PORT/"
else
if [ $($machine status default | tr "A-Z" "a-z" ) != "running" ]; then
echo "The docker VM doesn't seem to be running; will attempt to start it by doing '\$ $machine start':"
$machine start || die "Failed taking up the Docker VM"
fi
if [ -f "$machine" ]; then
if [ $($machine status default | tr "A-Z" "a-z") = "running" ]; then
tmpfile=$(mktemp docker.run.XXXXXXXX)
if $machine env 2>/dev/null | grep DOCKER_ > $tmpfile; then
mv $tmpfile ~/.docker-info
elif printenv | grep DOCKER_ > $tmpfile; then
mv $tmpfile ~/.docker-info
else
rm $tmpfile
die "Failed setting the appropriate DOCKER_* environment variables."
fi
. ~/.docker-info
else
rm -f ~/.docker-info
fi
ip=$($machine ip)
URL="http://$ip:$PORT/"
fi
fi
image=$(docker ps | grep "$REPO:$TAG" | awk '{ print $1 }')
if [ "$image" ]; then
if [ "$*" ]; then
echo "Running 'cd ~/${parent#$HOME/}; $*'"
docker exec -u "$WHO" -t $image bash -i -c "cd; cd \"${parent#$HOME/}\"; $*"
else
docker exec -u "$WHO" -ti $image bash -i
fi
else
echo ""
echo "Starting a docker container for '$TAG'."
if [ -n "$DOWNLOAD" ]; then
(
cd "$(dirname $MYSQLDIR)"
wget -N "$DBURL" && tar xjf ietf_utf8.bin.tar.bz2 && chmod -R go+rwX mysql
)
[ -d "$MYSQLDIR" ] || die "The download seems to have failed; still no $MYSQLDIR. Giving up."
else
[ -d "$MYSQLDIR" ] || die "Expected $MYSQLDIR to exist, but it\ndidn't. Use '$program -d' to download and unpack the database."
fi
if ! docker images "$REPO" | grep -q "$TAG"; then
echo "Fetching docker image '$REPO:$TAG'"
if ! docker pull "$REPO:$TAG"; then
docker pull "$REPO:latest" || die "Failed to pull down the '$REPO:latest' docker image"
id=$(docker images "$REPO" | grep latest | awk '{print $3}')
echo "Tagging $REPO:latest as $REPO:$TAG for use as environment for this branch."
docker tag $id "$REPO:$TAG"
fi
fi
echo -e "\nThe web interface for 'runserver' should appear on $URL\n"
echo -e "User $WHO ($WHOUID:$WHOGID)"
if [ -z "$MYSQLDIR" ]; then
docker run -ti -p $PORT:8000 -v "$HOME:/home/$WHO" \
-e USER="$WHO" -e DATADIR="${parent#$HOME/}/data" -e CWD="${PWD#$HOME/}" \
-e TAG="$TAG" -e FILEDIR=${FILEDIR#$HOME} -e UID="$WHOUID" -e GID="$WHOGID" \
"$REPO:$TAG" "$@"
else
docker run -ti -p $PORT:8000 -v "$HOME:/home/$WHO" -v "$MYSQLDIR:/var/lib/mysql"\
-e USER="$WHO" -e DATADIR="${parent#$HOME/}/data" -e CWD="${PWD#$HOME/}" \
-e TAG="$TAG" -e FILEDIR=${FILEDIR#$HOME} -e UID="$WHOUID" -e GID="$WHOGID" \
"$REPO:$TAG" "$@"
fi
echo ""
echo "Committing changes in the container to an image:"
image=$( docker images -q $REPO:$TAG)
latest=$(docker ps -lq -f "ancestor=$image")
docker commit $latest $REPO:$TAG
echo ""
echo "Cleaning up containers and images"
docker rm $latest
DANGLING=$( docker images -f dangling=true -q )
if [ -n "$DANGLING" ]; then
echo "Dangling images: $DANGLING"
docker rmi -f $DANGLING
fi
fi