Adding a new Runner
I use "runner" and "manager" pretty much inter-changeably on this site
because, for the purposes of denv
, the difference between the two is
not of great importance.
Requirements
There are two main features that a program needs to satisfy in order
to be usable by denv
as a container-interaction backend.
- Download Images from a Registry
- Check if an Image is already Downloaded
- Run the Image as a Container
Usually container "runners" are specifically focused on doing the last task (and only that one) while "managers" can do all of these tasks and more (like building images, pushing images to a registry, tagging images, etc...).
The main reason I use manager and runner interchangeably here is because
we do not use a lot of the features managers provide and so I could easily
forsee denv
supporting a runner whose download/check mechanism is some
curl
or wget
shell scripting nonsense rather than a call to the runner
program itself.
Running the Image
This section expands a bit on the requirements on the runner when running an image. For specifics, one will need to look at the denv source itself to see how the currently-supported runners run images as containers.
denv
wishes to integrate the containerized environment with the host
environment in several ways so that the user, while developing within a
denv, can easily use programs within the denv as if they are installed
within the host system. This leads to a few requirements on the program
that runs the images.
- User Ownership: any files written when in the denv should be owned by the user once they exit the denv
- Launching GUI Programs: the user should be able to launch a GUI program from within the denv
- Network and Port Connection: the user should be able to use the host
network and connect to ports on
localhost
within the denv - Home Directory: the in-denv home directory should be set to the workspace outside of the denv
- Environment Variables: the user is able to configure which environment variables to pass into the denv, so the runner needs to be able to define environment variables for the spawned container at runtime
What to Test
If you are developing a new runner to be wrapped by denv
, the natural next
question to ask is how should I test that it is functional.
First and foremost, make sure your additions to denv
still pass the
non-interactive tests.
./ci/check
./ci/test <your-runner>
These can be enabled in your fork of denv so that they run automatically on GitHub
when you push to a branch on your fork. In order for GitHub to be able to test
your runner, you will need to install it into the GitHub runner during the testing
workflow (.github/workflows/test.yml
) and add it to the runners-to-test.json
file in the include
list.
Tracking New Releases in Test
I've written up a "dependabot" that will check the latest release of certain GitHub repositories and update the testing workflow with those releases if a new one is found. In order to follow new releases of the runner being added, you must make changes in two places of the CI infrastructure.
- Add the runner repository (OWNER/REPO) under the
track
key in its entry inci/runners-to-test.json
. - Make sure your installation procedure will depend (and can handle) the version changing.
Right now, this is done for sylabs/singularity and apptainer/apptainer so look to those runners within the testing infrastructure as examples.
Besides the non-interactive tests, there are some additional, manual tests that I haven't figured out how to automate since they check interactions between the host and denv environments.
Make sure GUI Programs can be launched
There is a small image that can be used to test whether GUI programs can be run from within a denv. Launching from a in-denv shell, launching it directly from outside the denv, and launching without sharing environment variables should work properly.
I haven't found a quick and easy way to test this, but look at the
test/gui
directory for my notes on how I've tested this in the past.
As a first pass, you can attempt to run the xeyes
program from denv
.
DENV_RUNNER=<your-runner> ./test/gui/run-gui-test
Make sure Network and Ports are Connected
My main reason for supporting this is to allow me to interact with a Jupyter Lab instance running from within the denv. The Jupyter Project has built some images with their software installed which can be used for testing.
mkdir net-test
cd net-test
denv init jupyter/datascience-notebook
denv jupyter lab --no-browser
The user should be able to access the localhost link displayed by jupyter. Note: Developers should know that these images have a very special user and entrypoint configuration specialized for jupyter lab which may cause extra complications.
The non-interactive tests do check for network connection within the container by attempting to connect a socket to a public Google DNS server. I do not expect this to be enough to guarantee network functionality especially for new runners that I am not familiar with. Any aid in more precisely testing external network connection as well as "localhost"-style connection would be an appreciated contribution.