From b22c714ec583914381cffdbbdb7d8e932ec64f96 Mon Sep 17 00:00:00 2001 From: Taka Date: Thu, 12 Nov 2020 00:35:14 +0000 Subject: [PATCH] Got VASSAL running inside the Docker container. --- .dockerignore | 1 + Dockerfile | 6 +- docker/config/debug.cfg | 1 + docker/config/logging.yaml | 20 +++- docker/config/site.cfg | 1 + docker/run.sh | 3 +- run-container.sh | 106 +++++++++++++++------ vasl_templates/webapp/snippets.py | 3 + vasl_templates/webapp/tests/remote.py | 10 ++ vasl_templates/webapp/tests/test_vassal.py | 102 +++++++++++--------- vasl_templates/webapp/vassal.py | 15 ++- 11 files changed, 185 insertions(+), 83 deletions(-) diff --git a/.dockerignore b/.dockerignore index c19ebc0..8b0f204 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,5 +3,6 @@ ! setup.py ! requirements*.txt ! vasl_templates/ +! vassal-shim/release/ ! docker/ ! LICENSE.txt diff --git a/Dockerfile b/Dockerfile index 67777a0..e5737ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,9 +5,10 @@ FROM centos:8 AS base -# update packages and install Python +# update packages and install Python and Java RUN dnf -y upgrade-minimal && \ dnf install -y python36 && \ + curl -s "https://download.java.net/java/GA/jdk15.0.1/51f4f36ad4ef43e39d0dfdbaf6549e32/9/GPL/openjdk-15.0.1_linux-x64_bin.tar.gz" | tar -C /usr/bin/ -xz && \ dnf clean all # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -40,12 +41,13 @@ RUN wget -qO- "https://download.mozilla.org/?product=firefox-latest-ssl&os=linux echo "exclude=firefox" >> /etc/dnf/dnf.conf # install geckodriver -RUN url=$( curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep -Eoh 'https.*linux64\.tar\.gz' ) && \ +RUN url=$( curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep -Poh 'https.*linux64\.tar\.gz(?!\.)' ) && \ curl -sL "$url" | tar -C /usr/bin/ -xz # install the application WORKDIR /app COPY vasl_templates vasl_templates +COPY vassal-shim/release/vassal-shim.jar vassal-shim/release/ COPY setup.py requirements.txt requirements-dev.txt LICENSE.txt ./ RUN pip install -e . diff --git a/docker/config/debug.cfg b/docker/config/debug.cfg index ff6ef35..9f06056 100644 --- a/docker/config/debug.cfg +++ b/docker/config/debug.cfg @@ -1,4 +1,5 @@ [Debug] +TEST_VASSAL_ENGINES = /test-data/vassal/ TEST_VASL_MODS = /test-data/vasl-vmods/ TEST_VASL_EXTNS_DIR = /test-data/vasl-extensions/ diff --git a/docker/config/logging.yaml b/docker/config/logging.yaml index a0f8cc5..a9011d9 100644 --- a/docker/config/logging.yaml +++ b/docker/config/logging.yaml @@ -19,13 +19,25 @@ handlers: loggers: werkzeug: level: "WARNING" - handlers: [ "console" ] + handlers: [ "file" ] vasl_mod: level: "WARNING" - handlers: [ "console", "file" ] + handlers: [ "file" ] update_vsav: level: "WARNING" - handlers: [ "console", "file" ] + handlers: [ "file" ] + analyze_vsav: + level: "WARNING" + handlers: [ "file" ] + analyze_vlog: + level: "WARNING" + handlers: [ "file" ] + webdriver: + level: "WARNING" + handlers: [ "file" ] + downloads: + level: "WARNING" + handlers: [ "file" ] control_tests: - level: "DEBUG" + level: "INFO" handlers: [ "console", "file" ] diff --git a/docker/config/site.cfg b/docker/config/site.cfg index 09d9ddc..a00fca3 100644 --- a/docker/config/site.cfg +++ b/docker/config/site.cfg @@ -3,4 +3,5 @@ FLASK_HOST = 0.0.0.0 IS_CONTAINER = 1 +JAVA_PATH = /usr/bin/jdk-15.0.1/bin/java WEBDRIVER_PATH = /usr/bin/geckodriver diff --git a/docker/run.sh b/docker/run.sh index 4fa525b..8632ea7 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -1,7 +1,8 @@ #!/bin/sh -# set up the display (so we can run a webdriver) +# set up the display (so we can run VASSAL and a webdriver) export ENV=10 +export DISPLAY=:10.0 Xvfb :10 -ac 1>/tmp/xvfb.log 2>/tmp/xvfb.err & # run the webapp server diff --git a/run-container.sh b/run-container.sh index b5fbe02..eed7d63 100755 --- a/run-container.sh +++ b/run-container.sh @@ -5,29 +5,32 @@ 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 " -u --user-files Path to the user files 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)." - echo " --build-network Docker network to use when building the container." - echo " --run-network Docker network to use when running the container." - echo cat </dev/null 2>&1 ; then + echo "Can't find the template pack: $TEMPLATE_PACK_LOCAL" + exit 1 + fi + TEMPLATE_PACK=/data/template-pack + TEMPLATE_PACK_VOLUME="--volume `readlink -f "$TEMPLATE_PACK_LOCAL"`:$TEMPLATE_PACK" + TEMPLATE_PACK_ENV="--env DEFAULT_TEMPLATE_PACK=$TEMPLATE_PACK" +fi + # check if a user files directory has been specified if [ -n "$USER_FILES_LOCAL" ]; then if [ ! -d "$USER_FILES_LOCAL" ]; then @@ -160,8 +212,8 @@ echo Launching the \"$TAG\" container... docker run \ --publish $PORT:5010 \ --name vasl-templates \ - $VASL_MOD_VOLUME $VASL_EXTNS_VOLUME $CHAPTER_H_NOTES_VOLUME $USER_FILES_VOLUME \ - $VASL_MOD_ENV $VASL_EXTNS_ENV $CHAPTER_H_NOTES_ENV $USER_FILES_ENV \ + $VASSAL_VOLUME $VASL_MOD_VOLUME $VASL_BOARDS_VOLUME $VASL_EXTNS_VOLUME $CHAPTER_H_NOTES_VOLUME $USER_FILES_VOLUME $TEMPLATE_PACK_VOLUME \ + $VASSAL_ENV $VASL_MOD_ENV $VASL_BOARDS_ENV $VASL_EXTNS_ENV $CHAPTER_H_NOTES_ENV $USER_FILES_ENV $TEMPLATE_PACK_ENV \ $RUN_NETWORK $DETACH \ -it --rm \ vasl-templates:$TAG \ diff --git a/vasl_templates/webapp/snippets.py b/vasl_templates/webapp/snippets.py index 419e14b..b707700 100644 --- a/vasl_templates/webapp/snippets.py +++ b/vasl_templates/webapp/snippets.py @@ -58,6 +58,9 @@ def load_default_template_pack(): #pylint: disable=too-many-locals data["templates"]["extras/"+key] = val # check if a default template pack has been configured + # NOTE: The Docker container configures this setting via an environment variable. + global default_template_pack + default_template_pack = os.environ.get( "DEFAULT_TEMPLATE_PACK", default_template_pack ) if default_template_pack: dname = default_template_pack data["_path_"] = dname diff --git a/vasl_templates/webapp/tests/remote.py b/vasl_templates/webapp/tests/remote.py index 39b1a6f..64cc8be 100644 --- a/vasl_templates/webapp/tests/remote.py +++ b/vasl_templates/webapp/tests/remote.py @@ -19,7 +19,9 @@ import pytest from vasl_templates.webapp import app, globvars from vasl_templates.webapp.config.constants import DATA_DIR +from vasl_templates.webapp.vassal import VassalShim from vasl_templates.webapp.vasl_mod import set_vasl_mod +from vasl_templates.webapp.utils import TempFile from vasl_templates.webapp import main as webapp_main from vasl_templates.webapp import snippets as webapp_snippets from vasl_templates.webapp import scenarios as webapp_scenarios @@ -260,6 +262,14 @@ class ControlTests: app.config["VASSAL_DIR"] = vengine return self + def _get_vsav_dump( self, bin_data=None ): #pylint: disable=no-self-use + """Dump a VSAV file.""" + with TempFile( mode="wb" ) as temp_file: + temp_file.write( bin_data ) + temp_file.close( delete=False ) + vassal_shim = VassalShim() + return vassal_shim.dump_scenario( temp_file.name ) + def _set_vo_notes_dir( self, dtype=None ): """Set the vehicle/ordnance notes directory.""" if dtype == "real": diff --git a/vasl_templates/webapp/tests/test_vassal.py b/vasl_templates/webapp/tests/test_vassal.py index 18e1c9d..00e44ae 100644 --- a/vasl_templates/webapp/tests/test_vassal.py +++ b/vasl_templates/webapp/tests/test_vassal.py @@ -9,10 +9,8 @@ import typing.re #pylint: disable=import-error import pytest -from vasl_templates.webapp.vassal import VassalShim from vasl_templates.webapp.vasl_mod import compare_version_strings from vasl_templates.webapp.utils import TempFile, change_extn -from vasl_templates.webapp import globvars from vasl_templates.webapp.tests.utils import \ init_webapp, refresh_webapp, select_menu_option, get_stored_msg, set_stored_msg, set_stored_msg_marker, wait_for, \ new_scenario, set_player @@ -21,13 +19,6 @@ from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario, # --------------------------------------------------------------------- -class DummyVaslMod: - """Dummy VaslMod class that lets us run the VASSAL shim locally (to dump scenarios).""" - def __init__( self, fname ): - self.filename = fname - -# --------------------------------------------------------------------- - @pytest.mark.skipif( not pytest.config.option.vasl_mods, reason="--vasl-mods not specified" ) #pylint: disable=no-member @pytest.mark.skipif( not pytest.config.option.vassal, reason="--vassal not specified" ) #pylint: disable=no-member @pytest.mark.skipif( pytest.config.option.short_tests, reason="--short-tests specified" ) #pylint: disable=no-member @@ -114,7 +105,7 @@ def test_full_update( webapp, webdriver ): # NOTE: We could arguably only do this once, but updating scenarios is the key functionality of the VASSAL shim, # and so it's worth checking that every VASSAL+VASL combination understands its input correctly. fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/full.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) _check_vsav_dump( vsav_dump, { "scenario": "Somewhere", "players": re.compile( r"American:.*Belgian:" ), @@ -150,7 +141,7 @@ def test_full_update( webapp, webdriver ): # check the results temp_file.write( updated_vsav_data ) temp_file.close( delete=False ) - updated_vsav_dump = _dump_vsav( temp_file.name ) + updated_vsav_dump = _dump_vsav( control_tests, temp_file.name ) expected = { "scenario": "Modified scenario name (<>{}\"'\\)", "players": re.compile( r"American:.*Belgian:" ), @@ -234,12 +225,14 @@ def test_latw_autocreate( webapp, webdriver ): # check the VASL scenario fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/empty.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) _check_vsav_dump( vsav_dump, {}, ignore_labels ) # update the scenario (German/Russian, no date) load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3 } + ) _check_vsav_dump( updated_vsav_dump, { # nb: no LATW labels should have been created }, ignore_labels ) @@ -248,7 +241,9 @@ def test_latw_autocreate( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "10/01/1943" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 4 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 4 } + ) _check_vsav_dump( updated_vsav_dump, { "german/pf": "Panzerfaust", }, ignore_labels ) @@ -257,14 +252,18 @@ def test_latw_autocreate( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "01/01/1944" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 5 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 5 } + ) _check_vsav_dump( updated_vsav_dump, { "german/pf": "Panzerfaust", "german/atmm": "ATMM check:", }, ignore_labels ) # update the scenario (British/American, no date) load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3 } + ) _check_vsav_dump( updated_vsav_dump, { # nb: no LATW labels should have been created }, ignore_labels ) @@ -273,7 +272,9 @@ def test_latw_autocreate( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1945" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3 } + ) _check_vsav_dump( updated_vsav_dump, { # nb: no LATW labels should have been created }, ignore_labels ) @@ -304,7 +305,7 @@ def test_latw_update( webapp, webdriver ): # check the VASL scenario fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/latw.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) _check_vsav_dump( vsav_dump, { "german/psk": "Panzerschrek", "german/atmm": "ATMM check:", # nb: the PF label has no snippet ID "russian/mol-p": "TH#", # nb: the MOL label has no snippet ID @@ -317,7 +318,9 @@ def test_latw_update( webapp, webdriver ): # NOTE: We changed the MOL-P template (to add custom list bullets), so the snippet is different # to when this test was originally written, and so #updated changed from 2 to 3. # NOTE: Same thing happened when we factored out the common CSS into common.css :-/ Sigh... - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 5 } + ) _check_vsav_dump( updated_vsav_dump, { "german/pf": "Panzerfaust", # nb: the PF label now has a snippet ID "german/psk": "Panzerschrek", "german/atmm": "ATMM check:", @@ -330,7 +333,9 @@ def test_latw_update( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1943" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 2 } + ) _check_vsav_dump( updated_vsav_dump, { # NOTE: We used to delete the PSK/ATMM/MOL-P labels, but this no longer happens with player-owned labels. "german/psk": "Panzerschrek", "german/atmm": "ATMM check:", @@ -360,7 +365,7 @@ def test_dump_vsav( webapp, webdriver ): # dump the VASL scenario fname = os.path.join( os.path.split(__file__)[0], "fixtures/dump-vsav/labels.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) # check the result fname = change_extn( fname, ".txt" ) @@ -392,7 +397,7 @@ def test_update_legacy_labels( webapp, webdriver ): # dump the VASL scenario # NOTE: We implemented snippet ID's in v0.5, this scenario is the "Hill 621" example from v0.4. fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/hill621-legacy.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) labels = _get_vsav_labels( vsav_dump ) assert len( [ lbl for lbl in labels if "vasl-templates:id" not in lbl ] ) == 20 assert len( [ lbl for lbl in labels if "vasl-templates:id" in lbl ] ) == 0 #pylint: disable=len-as-condition @@ -402,7 +407,9 @@ def test_update_legacy_labels( webapp, webdriver ): saved_scenario = json.load( open( fname2, "r" ) ) load_scenario( saved_scenario ) expected = 5 if enable_vo_notes else 1 - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": expected, "updated": 20 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": expected, "updated": 20 } + ) # check the results # nb: the update process should create 1 new label (the "Download from MMP" scenario note) @@ -474,7 +481,7 @@ def test_update_legacy_latw_labels( webapp, webdriver ): # dump the VASL scenario # NOTE: This scenario contains LATW labels created using v0.4 i.e. they have no snippet ID's. fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/latw-legacy.vsav" ) - vsav_dump = _dump_vsav( fname ) + vsav_dump = _dump_vsav( control_tests, fname ) labels = _get_vsav_labels( vsav_dump ) assert len( [ lbl for lbl in labels if "vasl-templates:id" not in lbl ] ) == 8 assert len( [ lbl for lbl in labels if "vasl-templates:id" in lbl ] ) == 0 #pylint: disable=len-as-condition @@ -486,7 +493,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "12/31/1945" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 5 } + ) _check_vsav_dump( updated_vsav_dump, { "german/pf": "Panzerfaust", "german/psk": "Panzerschrek", "german/atmm": "ATMM check:", "russian/mol": "Kindling Attempt:", "russian/mol-p": "TH#", @@ -499,7 +508,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ): load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1945" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 2 } + ) _check_vsav_dump( updated_vsav_dump, { "british/piat": "PIAT", "american/baz": "Bazooka ('45)", @@ -510,7 +521,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ): # update the VSAV (some LATW are active) load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 5 } + ) _check_vsav_dump( updated_vsav_dump, { "german/pf": "Panzerfaust", "german/psk": "Panzerschrek", "german/atmm": "ATMM check:", "russian/mol": "Kindling Attempt:", "russian/mol-p": "TH#", @@ -521,7 +534,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ): # update the VSAV (some LATW are active) load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "" } } ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 3, "updated": 2 } + ) _check_vsav_dump( updated_vsav_dump, { "british/piat": "PIAT", "american/baz": "Bazooka", @@ -566,7 +581,9 @@ def test_player_owned_labels( webapp, webdriver ): # - scenario (timestamp) # - players (new American player) fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/player-owned-labels-legacy.vsav" ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "updated": 4 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "updated": 4 } + ) _check_vsav_dump( updated_vsav_dump , { "german/ob_setup_1.1": "german setup #1", "american/ob_setup_2.1": "american setup #1", @@ -580,7 +597,9 @@ def test_player_owned_labels( webapp, webdriver ): # - players (new American player) # The existing Russian OB setup label should be ignored and left in-place. fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/player-owned-labels.vsav" ) - updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 1, "updated": 2 } ) + updated_vsav_dump = _update_vsav_and_dump( control_tests, fname, + { "created": 1, "updated": 2 } + ) _check_vsav_dump( updated_vsav_dump , { "german/ob_setup_1.1": "german setup #1", "american/ob_setup_2.1": "american setup #1", @@ -819,13 +838,6 @@ def run_vassal_tests( control_tests, func, test_all, min_vasl_version=None ): else: assert False, "Can't find a valid combination of VASSAL and VASL." - # FUDGE! If we are running the tests against a remote server, we still need to be able to run - # the VASSAL shim locally (to dump VASSAL save files), so we need to set up things up enough - # for this to work. - if control_tests.server_url: - vasl_mods_local = control_tests._do_get_vasl_mods() #pylint: disable=protected-access - globvars.vasl_mod = DummyVaslMod( random.choice( vasl_mods_local ) ) - # run the test for each VASSAL+VASL for vassal_engine in vassal_engines: control_tests.set_vassal_engine( vengine=vassal_engine ) @@ -836,9 +848,9 @@ def run_vassal_tests( control_tests, func, test_all, min_vasl_version=None ): vasl_version = mo.group() if min_vasl_version and compare_version_strings( vasl_version, min_vasl_version ) < 0: continue - control_tests.set_vasl_mod( vmod=vasl_mod ) if not is_valid_combo( vassal_engine, vasl_mod ): continue + control_tests.set_vasl_mod( vmod=vasl_mod ) func() # --------------------------------------------------------------------- @@ -878,25 +890,25 @@ def _update_vsav( fname, expected ): return updated_vsav_data -def _update_vsav_and_dump( fname, expected ): +def _update_vsav_and_dump( control_tests, fname, expected ): """Update a VASL scenario and dump the result.""" - # update the VASL + # update the VSAV updated_vsav_data = _update_vsav( fname, expected ) # dump the updated VSAV with TempFile() as temp_file: temp_file.write( updated_vsav_data ) temp_file.close( delete=False ) - return _dump_vsav( temp_file.name ) + return _dump_vsav( control_tests, temp_file.name ) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def _dump_vsav( fname ): +def _dump_vsav( control_tests, fname ): """Dump a VASL scenario file.""" - # NOTE: This is run locally, even if we're running the tests against a remote server. - vassal_shim = VassalShim() - return vassal_shim.dump_scenario( fname ) + with open( fname, "rb" ) as fp: + vsav_data = fp.read() + return control_tests.get_vsav_dump( bin_data=vsav_data ) def _check_vsav_dump( vsav_dump, expected, ignore=None ): """"Check that a VASL scenario dump contains what we expect.""" diff --git a/vasl_templates/webapp/vassal.py b/vasl_templates/webapp/vassal.py index ed3a60f..fc5f08f 100644 --- a/vasl_templates/webapp/vassal.py +++ b/vasl_templates/webapp/vassal.py @@ -289,7 +289,7 @@ class VassalShim: def __init__( self ): #pylint: disable=too-many-branches # locate the VASSAL engine - vassal_dir = app.config.get( "VASSAL_DIR" ) + vassal_dir = self._get_vassal_dir() if not vassal_dir: raise SimpleError( "The VASSAL installation directory has not been configured." ) self.vengine_jar = None @@ -323,7 +323,7 @@ class VassalShim: @staticmethod def get_version(): """Get the VASSAL version.""" - vassal_dir = app.config.get( "VASSAL_DIR" ) + vassal_dir = VassalShim._get_vassal_dir() if not vassal_dir: return None # FUDGE! We can't capture the output on Windows, get the result in a temp file instead :-/ @@ -471,7 +471,8 @@ class VassalShim: @staticmethod def get_boards_dir(): """Get the configured boards directory.""" - boards_dir = app.config.get( "BOARDS_DIR" ) + # NOTE: The Docker container configures this setting via an environment variable. + boards_dir = app.config.get( "BOARDS_DIR", os.environ.get("VASL_BOARDS_DIR") ) if not boards_dir: raise SimpleError( "The VASL boards directory has not been configured." ) if not os.path.isdir( boards_dir ): @@ -513,7 +514,7 @@ class VassalShim: @staticmethod def check_vassal_version( msg_store ): """Check the version of VASSAL.""" - if not app.config.get( "VASSAL_DIR" ) or not msg_store: + if not VassalShim._get_vassal_dir() or not msg_store: return try: version = VassalShim.get_version() @@ -528,6 +529,12 @@ class VassalShim: version ) + @staticmethod + def _get_vassal_dir(): + """Get the VASSAL installation directory.""" + # NOTE: The Docker container configures this setting via an environment variable. + return app.config.get( "VASSAL_DIR", os.environ.get("VASSAL_DIR") ) + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class VassalShimError( Exception ):