Skip to content

Commit 3b1ee83

Browse files
authored
Provide CHECKBOX_RUNTIME environment variable during job execution only (BugFix) (#2362)
* Set CHECKBOX_RUNTIME from within Checkbox when running Snap version Fix #2295 * Remove CHECKBOX_RUNTIME from wrapper scripts * Add unit tests for the get_execution_environment function * black * Add reference page about environment variables
1 parent 7a0164b commit 3b1ee83

7 files changed

Lines changed: 93 additions & 10 deletions

File tree

checkbox-core-snap/common_files/config/wrapper_common

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ else
3737
append_path PYTHONPATH $RUNTIME/lib/python3*/dist-packages
3838
fi
3939

40-
# make sure we always know where the content snap is especially for classic
41-
# checkbox snaps where the checkbox-runtime bind mount does not exist
42-
export CHECKBOX_RUNTIME=$(findmnt -oTARGET -n $(findmnt -oSOURCE -n $RUNTIME) | grep -P "^\/snap\/checkbox(|\d{2})\/")
43-
4440
# Tell GStreamer where to find its plugins
4541
export GST_PLUGIN_PATH=$RUNTIME/usr/lib/$ARCH/gstreamer-1.0
4642
export GST_PLUGIN_SYSTEM_PATH=$RUNTIME/usr/lib/$ARCH/gstreamer-1.0

checkbox-core-snap/common_files/config/wrapper_common_classic

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ else
4545
append_path PYTHONPATH $RUNTIME/lib/python3*/dist-packages
4646
fi
4747

48-
# make sure we always know where the content snap is especially for classic
49-
# checkbox snaps where the checkbox-runtime bind mount does not exist
50-
export CHECKBOX_RUNTIME=$RUNTIME
51-
5248
# Use a modules directory which doesn't exist so we don't load random things
5349
# which may then get deleted (or their dependencies) and potentially segfault
5450
export GIO_MODULE_DIR=$SNAP/gio/modules-dummy

checkbox-ng/plainbox/impl/execution.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,8 @@ def set_if_not_none(envvar, source):
626626
set_if_not_none("PLAINBOX_PROVIDER_DATA", job.provider.data_dir)
627627
set_if_not_none("PLAINBOX_PROVIDER_UNITS", job.provider.units_dir)
628628
set_if_not_none("CHECKBOX_SHARE", job.provider.CHECKBOX_SHARE)
629+
if os.getenv("SNAP"):
630+
set_if_not_none("CHECKBOX_RUNTIME", str(get_checkbox_runtime_path()))
629631
# Inject additional variables that are requested in the config
630632
if environ is not None:
631633
for env_var in environ:

checkbox-ng/plainbox/impl/test_execution.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
# You should have received a copy of the GNU General Public License
1717
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
1818

19-
import os
2019
import contextlib
20+
import os
2121
from pathlib import Path
2222
from unittest import TestCase, mock
2323

@@ -28,6 +28,7 @@
2828
dangerous_nsenter,
2929
get_execution_command_subshell,
3030
get_execution_command_systemd_unit,
31+
get_execution_environment,
3132
)
3233
from plainbox.impl.unit.job import InvalidJob
3334

@@ -459,3 +460,63 @@ def test_present(self):
459460
self.assertIn("og_path2", new_path)
460461
self.assertIn("some", new_path)
461462
self.assertIn("path", new_path)
463+
464+
465+
class TestGetExecutionEnvironment(TestCase):
466+
def setUp(self):
467+
self.job = mock.Mock()
468+
self.job.get_flag_set.return_value = set()
469+
self.job.provider.gettext_domain = None
470+
self.job.provider.locale_dir = None
471+
self.job.provider.extra_PYTHONPATH = []
472+
self.job.provider.extra_PATH = []
473+
self.job.provider.extra_LD_LIBRARY_PATH = []
474+
self.job.provider.extra_snap_environment = {}
475+
self.job.provider.data_dir = None
476+
self.job.provider.units_dir = None
477+
self.job.provider.CHECKBOX_SHARE = None
478+
479+
@mock.patch.dict(os.environ, {"ORIGINAL_ENV": "value"}, clear=True)
480+
@mock.patch("plainbox.impl.execution.WellKnownDirsHelper")
481+
def test_basic_environment(self, mock_well_known):
482+
mock_well_known.session_share.return_value = "/session/share"
483+
484+
env = get_execution_environment(
485+
self.job, None, "test_session", "/nest"
486+
)
487+
488+
self.assertIn("ORIGINAL_ENV", env)
489+
self.assertEqual(env["ORIGINAL_ENV"], "value")
490+
self.assertEqual(env["PLAINBOX_SESSION_SHARE"], "/session/share")
491+
self.assertIn("/nest", env["PATH"])
492+
mock_well_known.session_share.assert_called_once_with("test_session")
493+
494+
@mock.patch.dict(os.environ, {"SNAP": "/snap/checkbox24"}, clear=True)
495+
@mock.patch("plainbox.impl.execution.get_checkbox_runtime_path")
496+
@mock.patch("plainbox.impl.execution.WellKnownDirsHelper")
497+
def test_checkbox_runtime_in_snap(
498+
self, mock_well_known, mock_runtime_path
499+
):
500+
mock_well_known.session_share.return_value = "/session/share"
501+
mock_runtime_path.return_value = Path("/snap/checkbox24/current")
502+
503+
env = get_execution_environment(
504+
self.job, None, "test_session", "/nest"
505+
)
506+
507+
self.assertEqual(env["CHECKBOX_RUNTIME"], "/snap/checkbox24/current")
508+
509+
@mock.patch.dict(
510+
os.environ, {"EXISTING_VAR": "original_value"}, clear=True
511+
)
512+
@mock.patch("plainbox.impl.execution.WellKnownDirsHelper")
513+
def test_environ_dict_does_not_override_existing(self, mock_well_known):
514+
mock_well_known.session_share.return_value = "/session/share"
515+
516+
environ = {"EXISTING_VAR": "new_value"}
517+
518+
env = get_execution_environment(
519+
self.job, environ, "test_session", "/nest"
520+
)
521+
522+
self.assertEqual(env["EXISTING_VAR"], "original_value")

checkbox-ng/plainbox/impl/unit/unit.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ def get_checkbox_runtime_path():
9696
# runtime, while SNAP on the legacy arch is the frontend
9797
snap_base_n = get_snap_base().replace("core", "")
9898
# the bases of the runtime and frontend must always match
99-
runtime_name = "checkbox" + snap_base_n
10099
return Path("/snap") / ("checkbox" + snap_base_n) / "current"
101100

102101

docs/reference/envvar.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.. _envvar:
2+
3+
Environment variables set by Checkbox
4+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
6+
Checkbox sets a few environment variables during execution. These can be
7+
used in the job definition itself or even in the script called by the
8+
``command`` field of a the job.
9+
10+
``PLAINBOX_SESSION_SHARE``
11+
Path to a directory that can be used to store temporary data during the
12+
test run. This is useful if you have one test gathering data, and another
13+
one checking said data. For example, the first test would write its
14+
output to ``$PLAINBOX_SESSION_SHARE/my_test_output``, and the other one
15+
would retrieve the content of the file to analyze it.
16+
17+
``PLAINBOX_PROVIDER_DATA``
18+
Directory within the provider that contains additional data required by
19+
some jobs. For instance, the `Base provider data directory`_ contains
20+
files used to assign the GPIO pins specific to some hardware.
21+
22+
``CHECKBOX_RUNTIME``
23+
Directory where the Checkbox runtime is located. This is especially useful
24+
when in a snap environment where test authors may need to point to specific
25+
files within the runtime environment. For example, when using the
26+
checkbox24 snap, the runtime is ``/snap/checkbox24/current``.
27+
28+
.. _Base provider data directory: https://github.com/canonical/checkbox/tree/main/providers/base/data

docs/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Reference
88
glossary
99
stack
1010
launcher
11+
envvar
1112
units/index
1213
snaps
1314
submission-schema

0 commit comments

Comments
 (0)