Repository: osrf/rocker

Issue:
Ubuntu 20.04 support for `--nvidia`
Currently testing some stuff with ROS2 Foxy on Ubutu 20.04. Looks like `--nvidia` isn't supported yet:
```
WARNING distro version 20.04 not in supported list by Nvidia supported versions ['16.04', '18.04']
```

Related: https://gitlab.com/nvidia/container-images/opengl/-/issues/7

Comments:

Patch:
diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py
index a7894af..9d32843 100644
--- a/src/rocker/extensions.py
+++ b/src/rocker/extensions.py
@@ -215,9 +215,15 @@ class Environment(RockerExtension):
     def get_docker_args(self, cli_args):
         args = ['']
 
-        envs = [ x for sublist in cli_args['env'] for x in sublist]
-        for env in envs:
-            args.append('-e {0}'.format(quote(env)))
+        if cli_args.get('env'):
+            envs = [ x for sublist in cli_args['env'] for x in sublist]
+            for env in envs:
+                args.append('-e {0}'.format(quote(env)))
+
+        if cli_args.get('env_file'):
+            env_files = [ x for sublist in cli_args['env_file'] for x in sublist]
+            for env_file in env_files:
+                args.append('--env-file {0}'.format(quote(env_file)))
 
         return ' '.join(args)
 
@@ -229,3 +235,13 @@ class Environment(RockerExtension):
             nargs='+',
             action='append',
             help='set environment variables')
+        parser.add_argument('--env-file',
+            type=str,
+            nargs=1,
+            action='append',
+            help='set environment variable via env-file')
+
+    @classmethod
+    def check_args_for_activation(cls, cli_args):
+        """ Returns true if the arguments indicate that this extension should be activated otherwise false."""
+        return True if cli_args.get('env') or cli_args.get('env_file') else False
diff --git a/src/rocker/nvidia_extension.py b/src/rocker/nvidia_extension.py
index 32c31ff..e27a707 100644
--- a/src/rocker/nvidia_extension.py
+++ b/src/rocker/nvidia_extension.py
@@ -82,8 +82,8 @@ class Nvidia(RockerExtension):
     def __init__(self):
         self._env_subs = None
         self.name = Nvidia.get_name()
-        self.supported_distros = ['Ubuntu']
-        self.supported_versions = ['16.04', '18.04']
+        self.supported_distros = ['Ubuntu', 'Debian GNU/Linux']
+        self.supported_versions = ['16.04', '18.04', '20.04', '10']
 
 
     def get_environment_subs(self, cliargs={}):
@@ -105,7 +105,7 @@ class Nvidia(RockerExtension):
             sys.exit(1)
         self._env_subs['image_distro_version'] = ver
         if self._env_subs['image_distro_version'] not in self.supported_versions:
-            print("WARNING distro version %s not in supported list by Nvidia supported versions" % self._env_subs['image_distro_version'], self.supported_versions)
+            print("WARNING distro %s version %s not in supported list by Nvidia supported versions" % (dist, ver), self.supported_versions)
             sys.exit(1)
             # TODO(tfoote) add a standard mechanism for checking preconditions and disabling plugins
 
diff --git a/src/rocker/templates/nvidia_preamble.Dockerfile.em b/src/rocker/templates/nvidia_preamble.Dockerfile.em
index f6fb0af..1bab533 100644
--- a/src/rocker/templates/nvidia_preamble.Dockerfile.em
+++ b/src/rocker/templates/nvidia_preamble.Dockerfile.em
@@ -1,2 +1,3 @@
 # Ubuntu 16.04 with nvidia-docker2 beta opengl support
-FROM nvidia/opengl:1.0-glvnd-devel-@(image_distro_id.lower())@(image_distro_version) as glvnd
+@{suffix = '16.04' if image_distro_version == '16.04' else '18.04'}@
+FROM nvidia/opengl:1.0-glvnd-devel-ubuntu@(suffix) as glvnd
diff --git a/src/rocker/templates/nvidia_snippet.Dockerfile.em b/src/rocker/templates/nvidia_snippet.Dockerfile.em
index 1cda845..69e9a09 100644
--- a/src/rocker/templates/nvidia_snippet.Dockerfile.em
+++ b/src/rocker/templates/nvidia_snippet.Dockerfile.em
@@ -10,7 +10,7 @@ RUN ( echo '/usr/local/lib/x86_64-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf &&
 ENV LD_LIBRARY_PATH /usr/local/lib/x86_64-linux-gnu:/usr/local/lib/i386-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
 
 COPY --from=glvnd /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json
-@[else if image_distro_version == '18.04']@
+@[else]@
 RUN apt-get update && apt-get install -y --no-install-recommends \
     libglvnd0 \
     libgl1 \


Test patch:
diff --git a/test/test_extension.py b/test/test_extension.py
index 5000c32..9d61593 100644
--- a/test/test_extension.py
+++ b/test/test_extension.py
@@ -289,3 +289,17 @@ class EnvExtensionTest(unittest.TestCase):
         self.assertEqual(p.get_snippet(mock_cliargs), '')
         self.assertEqual(p.get_preamble(mock_cliargs), '')
         self.assertEqual(p.get_docker_args(mock_cliargs), ' -e ENVVARNAME=envvar_value -e ENV2=val2 -e ENV3=val3')
+
+    def test_env_file_extension(self):
+        plugins = list_plugins()
+        env_plugin = plugins['env']
+        self.assertEqual(env_plugin.get_name(), 'env')
+
+        p = env_plugin()
+        self.assertTrue(plugin_load_parser_correctly(env_plugin))
+        
+        mock_cliargs = {'env_file': [['foo'], ['bar']]}
+
+        self.assertEqual(p.get_snippet(mock_cliargs), '')
+        self.assertEqual(p.get_preamble(mock_cliargs), '')
+        self.assertEqual(p.get_docker_args(mock_cliargs), ' --env-file foo --env-file bar')
diff --git a/test/test_nvidia.py b/test/test_nvidia.py
index b183fe6..01bf2d4 100644
--- a/test/test_nvidia.py
+++ b/test/test_nvidia.py
@@ -36,9 +36,9 @@ class X11Test(unittest.TestCase):
     def setUpClass(self):
         client = get_docker_client()
         self.dockerfile_tags = []
-        for distro_version in ['xenial', 'bionic']:
+        for distro, distro_version in [('ubuntu', 'xenial'), ('ubuntu', 'bionic'), ('ubuntu', 'focal'), ('debian', 'buster')]:
             dockerfile = """
-FROM ubuntu:%(distro_version)s
+FROM %(distro)s:%(distro_version)s
 
 RUN apt-get update && apt-get install x11-utils -y && apt-get clean
 
@@ -204,7 +204,7 @@ CMD glmark2 --validate
         self.assertEqual(cm.exception.code, 1)
 
         # unsupported os
-        mock_cliargs = {'base_image': 'debian'}
+        mock_cliargs = {'base_image': 'fedora'}
         with self.assertRaises(SystemExit) as cm:
             p.get_environment_subs(mock_cliargs)
         self.assertEqual(cm.exception.code, 1)