diff --git a/Dockerfile b/Dockerfile index eaa9371..e4fc76c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,4 @@ -# To build the image: -# docker build --tag vasl-templates . -# Add "--build-arg ENABLE_TESTS=1" to allow the test suite to be run against a container. -# -# To run a container: -# docker run --rm -it --name vasl-templates \ -# -p 5010:5010 \ -# -v .../vasl-6.4.3.vmod:/data/vasl.vmod \ -# -v .../vasl-extensions:/data/vasl-extensions \ -# vasl-templates -# If you have Chapter H data, add the following: -# -v .../chapter-h-notes:/data/chapter-h-notes +# NOTE: Use the run-container.sh script to build and launch this container. FROM python:alpine3.6 diff --git a/docker/config/site.cfg b/docker/config/site.cfg index 7b2ac9e..c72edbe 100644 --- a/docker/config/site.cfg +++ b/docker/config/site.cfg @@ -2,7 +2,3 @@ FLASK_HOST = 0.0.0.0 IS_CONTAINER = 1 - -VASL_MOD = /data/vasl.vmod -VASL_EXTNS_DIR = /data/vasl-extensions/ -CHAPTER_H_NOTES_DIR = /data/chapter-h-notes/ diff --git a/run-container.sh b/run-container.sh new file mode 100755 index 0000000..1ac59a1 --- /dev/null +++ b/run-container.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# Helper script that builds and launches the Docker container. + +# --------------------------------------------------------------------- + +function print_help { + echo "`basename "$0"` {options}" + echo " Build and launch the \"vasl-templates\" container." + echo + echo " -p --port Web server port number." + echo " -v --vasl-vmod Path to the VASL .vmod file." + echo " -e --vasl-extensions Path to the VASL extensions directory." + echo " -h --chapter-h Path to the Chapter H notes directory." + echo + echo " -t --tag Docker tag." + echo " -d --detach Detach from the container and let it run in the background." + echo " --no-build Launch the container as-is (i.e. without rebuilding it first)." +} + +# --------------------------------------------------------------------- + +# initialize +cd `dirname "$0"` +PORT=5010 +VASL_MOD_LOCAL= +VASL_MOD= +VASL_EXTNS_LOCAL= +VASL_EXTNS= +CHAPTER_H_NOTES_LOCAL= +CHAPTER_H_NOTES= +TAG=latest +DETACH= +NO_BUILD= + +# parse the command-line arguments +if [ $# -eq 0 ]; then + print_help + exit 0 +fi +params="$(getopt -o p:v:e:h:t:d -l port:,vasl-vmod:,vasl-extensions:,chapter-h:,tag:,detach,no-build,help --name "$0" -- "$@")" +if [ $? -ne 0 ]; then exit 1; fi +eval set -- "$params" +while true; do + case "$1" in + -p | --port) + PORT=$2 + shift 2 ;; + -v | --vasl-vmod) + VASL_MOD_LOCAL=$2 + shift 2 ;; + -e | --vasl-extensions) + VASL_EXTNS_LOCAL=$2 + shift 2 ;; + -h | --chapter-h) + CHAPTER_H_NOTES_LOCAL=$2 + shift 2 ;; + -t | --tag) + TAG=$2 + shift 2 ;; + -d | --detach ) + DETACH=--detach + shift 1 ;; + --no-build ) + NO_BUILD=1 + shift 1 ;; + --help ) + print_help + exit 0 ;; + -- ) shift ; break ;; + * ) + echo "Unknown option: $1" >&2 + exit 1 ;; + esac +done + +# check if a VASL .vmod file has been specified +if [ -n "$VASL_MOD_LOCAL" ]; then + if [ ! -f "$VASL_MOD_LOCAL" ]; then + echo "Can't find the VASL .vmod file: $VASL_MOD_LOCAL" + exit 1 + fi + VASL_MOD=/data/vasl.vmod + VASL_MOD_VOLUME="--volume `readlink -f "$VASL_MOD_LOCAL"`:$VASL_MOD" + VASL_MOD_ENV="--env VASL_MOD=$VASL_MOD" +fi + +# check if a VASL extensions directory has been specified +if [ -n "$VASL_EXTNS_LOCAL" ]; then + if [ ! -d "$VASL_EXTNS_LOCAL" ]; then + echo "Can't find the VASL extensions directory: $_EXTNS_DIR_LOCAL" + exit 1 + fi + VASL_EXTNS=/data/vasl-extensions/ + VASL_EXTNS_VOLUME="--volume `readlink -f "$VASL_EXTNS_LOCAL"`:$VASL_EXTNS" + VASL_EXTNS_ENV="--env VASL_EXTNS_DIR=$VASL_EXTNS" +fi + +# check if a Chapter H notes directory has been specified +if [ -n "$CHAPTER_H_NOTES_LOCAL" ]; then + if [ ! -d "$CHAPTER_H_NOTES_LOCAL" ]; then + echo "Can't find the Chapter H notes directory: $CHAPTER_H_NOTES_LOCAL" + exit 1 + fi + CHAPTER_H_NOTES=/data/chapter-h-notes/ + CHAPTER_H_NOTES_VOLUME="--volume `readlink -f "$CHAPTER_H_NOTES_LOCAL"`:$CHAPTER_H_NOTES" + CHAPTER_H_NOTES_ENV="--env CHAPTER_H_NOTES_DIR=$CHAPTER_H_NOTES" +fi + +# build the container +if [ -z "$NO_BUILD" ]; then + echo Building the container... + docker build . --tag vasl-templates:$TAG 2>&1 \ + | sed -e 's/^/ /' + if [ $? -ne 0 ]; then exit 10 ; fi + echo +fi + +# launch the container +echo Launching the container... +docker run \ + --publish $PORT:5010 \ + --name vasl-templates \ + $VASL_MOD_VOLUME $VASL_EXTNS_VOLUME $CHAPTER_H_NOTES_VOLUME \ + $VASL_MOD_ENV $VASL_EXTNS_ENV $CHAPTER_H_NOTES_ENV \ + $DETACH \ + -it --rm \ + vasl-templates:$TAG \ + 2>&1 \ +| sed -e 's/^/ /' diff --git a/vasl_templates/webapp/__init__.py b/vasl_templates/webapp/__init__.py index 6897f6b..e28b008 100644 --- a/vasl_templates/webapp/__init__.py +++ b/vasl_templates/webapp/__init__.py @@ -22,7 +22,8 @@ def _on_startup(): load_default_template_pack() # configure the VASL module - fname = app.config.get( "VASL_MOD" ) + # NOTE: The Docker container configures this setting via an environment variable. + fname = app.config.get( "VASL_MOD", os.environ.get("VASL_MOD") ) if fname: from vasl_templates.webapp.vasl_mod import set_vasl_mod #pylint: disable=cyclic-import from vasl_templates.webapp.main import startup_msg_store #pylint: disable=cyclic-import diff --git a/vasl_templates/webapp/static/help/index.html b/vasl_templates/webapp/static/help/index.html index e4570ed..65d21f2 100644 --- a/vasl_templates/webapp/static/help/index.html +++ b/vasl_templates/webapp/static/help/index.html @@ -76,16 +76,13 @@ and then connect to it in a browser at http://localhost:5010.

Running a Docker container

-

If you have Docker installed, the webapp can be run in a container: +

If you have Docker installed, the webapp can be run in a container e.g.

-docker run --rm -it --name vasl-templates \ - -p 5010:5010 \ - -v /home/pacman-ghost/vasl/vasl-6.4.4.vmod:/data/vasl.vmod \ - -v /home/pacman-ghost/vasl/extensions/:/data/vasl-extensions \ - vasltemplates/images:latest +./run-container.sh --port 5010 \ + --vasl-vmod ~/vasl/vasl-6.4.4.vmod \ + --vasl-extensions ~/vasl/extensions/ \ + --chapter-h ~/vasl/chapter-h/
-To include Chapter H data, add the following: -
-v /home/pacman-ghost/vasl/chapter-h:/data/chapter-h-notes

Then open a browser and connect to the webapp at http://localhost:5010.

Note that some features (e.g. updating and analyzing VASL scenario files) may not be available.

If you have SElinux enabled, it may prevent the container from accessing files on the host. Access can be allowed like this: @@ -503,29 +500,6 @@ export JSHINT_RHINO=~/bin/jshint-2.6.3/dist/jshint-rhino.js
Note that both of these are run as part of a normal pytest run. -

Docker

- -

The webapp can be run using Docker. To create an image, cd to the project root and build the image e.g. -

-docker build --tag vasl-templates . -
-
To allow the test suite to be run against the container, add --build-arg ENABLE_TESTS=1 to the command.
- -

Then run the container: -

-docker run --rm -it --name vasl-templates \ - -p 5010:5010 \ - -v /home/pacman-ghost/vasl/vasl-6.4.4.vmod:/data/vasl.vmod \ - -v /home/pacman-ghost/vasl/extensions/:/data/vasl-extensions \ - vasl-templates -
-
The "Update VASL scenario" and "Analyze VASL scenario" features are currently not available in a container.
- -

Note that if you have SElinux enabled, it may prevent the container from accessing files on the host, in which case access can be allowed like this: -

-chcon -Rt svirt_sandbox_file_t /home/pacman-ghost/vasl/ -
-

Creating a pre-compiled package

It is possible to compile the desktop application down to a single binary. This is typically done for the benefit of Windows users, but also works for other platforms. From the root directory of the repo: diff --git a/vasl_templates/webapp/vasl_mod.py b/vasl_templates/webapp/vasl_mod.py index 3c7431b..f1b9cdd 100644 --- a/vasl_templates/webapp/vasl_mod.py +++ b/vasl_templates/webapp/vasl_mod.py @@ -25,7 +25,8 @@ def set_vasl_mod( vmod_fname, msg_store ): globvars.vasl_mod = None if vmod_fname: # load and install the specified VASL module - extns_dir = app.config.get( "VASL_EXTNS_DIR" ) + # NOTE: The Docker container configures this setting via an environment variable. + extns_dir = app.config.get( "VASL_EXTNS_DIR", os.environ.get("VASL_EXTNS_DIR") ) extns = _load_vasl_extns( extns_dir, msg_store ) try: vasl_mod = VaslMod( vmod_fname, DATA_DIR, extns ) diff --git a/vasl_templates/webapp/vo_notes.py b/vasl_templates/webapp/vo_notes.py index c79c984..c5c2950 100644 --- a/vasl_templates/webapp/vo_notes.py +++ b/vasl_templates/webapp/vo_notes.py @@ -32,7 +32,8 @@ def load_vo_notes( msg_store ): #pylint: disable=too-many-statements,too-many-lo """Load the Chapter H vehicle/ordnance notes.""" # locate the data directory - dname = app.config.get( "CHAPTER_H_NOTES_DIR" ) + # NOTE: The Docker container configures this setting via an environment variable. + dname = app.config.get( "CHAPTER_H_NOTES_DIR", os.environ.get("CHAPTER_H_NOTES_DIR") ) if dname: # NOTE: If the Chapter H directory has been configured but is incorrect, we want to keep going, # since this may well happen when running in a container (the directory has to be always configured,