def test_user_extension(self): plugins = list_plugins() user_plugin = plugins['user'] self.assertEqual(user_plugin.get_name(), 'user') p = user_plugin() self.assertTrue(plugin_load_parser_correctly(user_plugin)) env_subs = p.get_environment_subs() self.assertEqual(env_subs['gid'], os.getgid()) self.assertEqual(env_subs['uid'], os.getuid()) self.assertEqual(env_subs['name'], getpass.getuser()) self.assertEqual(env_subs['dir'], str(Path.home())) self.assertEqual(env_subs['gecos'], pwd.getpwuid(os.getuid()).pw_gecos) self.assertEqual(env_subs['shell'], pwd.getpwuid(os.getuid()).pw_shell) mock_cliargs = {} snippet = p.get_snippet(mock_cliargs).splitlines() uid_line = [l for l in snippet if '--uid' in l][0] self.assertTrue(str(os.getuid()) in uid_line) self.assertEqual(p.get_preamble(mock_cliargs), '') self.assertEqual(p.get_docker_args(mock_cliargs), '') self.assertTrue('mkhomedir_helper' in p.get_snippet(mock_cliargs)) home_active_cliargs = mock_cliargs home_active_cliargs['home'] = True self.assertFalse( 'mkhomedir_helper' in p.get_snippet(home_active_cliargs))
def test_git_extension(self): plugins = list_plugins() git_plugin = plugins['git'] self.assertEqual(git_plugin.get_name(), 'git') p = git_plugin() self.assertTrue(plugin_load_parser_correctly(git_plugin)) mock_cliargs = {} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) # self.assertFalse(args) system_gitconfig = '/etc/gitconfig' user_gitconfig = os.path.expanduser('~/.gitconfig') user_gitconfig_target = '/root/.gitconfig' if os.path.exists(system_gitconfig): # TODO(tfoote) This isn't exercised on most systems, it would need to be mocked self.assertIn('-v %s:%s' % (system_gitconfig, system_gitconfig), args) if os.path.exists(user_gitconfig): self.assertIn('-v %s:%s' % (user_gitconfig, user_gitconfig_target), args) # Test with user "enabled" mock_cliargs = {'user': True} user_args = p.get_docker_args(mock_cliargs) if os.path.exists(user_gitconfig): self.assertIn('-v %s:%s' % (user_gitconfig, user_gitconfig), user_args)
def test_pulse_extension(self): plugins = list_plugins() pulse_plugin = plugins['pulse'] self.assertEqual(pulse_plugin.get_name(), 'pulse') p = pulse_plugin() self.assertTrue(plugin_load_parser_correctly(pulse_plugin)) mock_cliargs = {} snippet = p.get_snippet(mock_cliargs) #first line self.assertIn('RUN mkdir -p /etc/pulse', snippet) self.assertIn('default-server = unix:/run/user/', snippet) #skipping user id that's system dependent self.assertIn('autospawn = no', snippet) self.assertIn('daemon-binary = /bin/true', snippet) #last line self.assertIn('> /etc/pulse/client.conf', snippet) self.assertEqual(p.get_preamble(mock_cliargs), '') docker_args = p.get_docker_args(mock_cliargs) self.assertIn('-v /run/user/', docker_args) self.assertIn('/pulse:/run/user/', docker_args) self.assertIn('/pulse --device /dev/snd ', docker_args) self.assertIn(' -e PULSE_SERVER=unix', docker_args) self.assertIn('/pulse/native -v', docker_args) self.assertIn('/pulse/native:', docker_args) self.assertIn('/pulse/native --group-add', docker_args)
def test_list_plugins(self): plugins_found = list_plugins() plugin_names = plugins_found.keys() self.assertTrue('nvidia' in plugin_names) self.assertTrue('pulse' in plugin_names) self.assertTrue('user' in plugin_names) self.assertTrue('home' in plugin_names)
def test_x11_xpdyinfo(self): plugins = list_plugins() desired_plugins = ['x11'] active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins] for tag in self.dockerfile_tags: dig = DockerImageGenerator(active_extensions, {}, tag) self.assertEqual(dig.build(), 0) self.assertEqual(dig.run(), 0)
def test_nvidia_glmark2(self): plugins = list_plugins() desired_plugins = ['x11', 'nvidia', 'user'] #TODO(Tfoote) encode the x11 dependency into the plugin and remove from test here active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins] for tag in self.dockerfile_tags: dig = DockerImageGenerator(active_extensions, {}, tag) self.assertEqual(dig.build(), 0) self.assertEqual(dig.run(), 0)
def test_return_code_multiple_extensions(self): plugins = list_plugins() desired_plugins = ['home', 'user'] active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins] dig = DockerImageGenerator(active_extensions, {}, 'ubuntu:bionic') self.assertEqual(dig.build(), 0) self.assertEqual(dig.run('true'), 0) self.assertEqual(dig.run('false'), 1)
def test_pulse_extension(self): plugins = list_plugins() dev_helper_plugin = plugins['dev_helpers'] self.assertEqual(dev_helper_plugin.get_name(), 'dev_helpers') p = dev_helper_plugin() self.assertTrue(plugin_load_parser_correctly(dev_helper_plugin)) mock_cliargs = {} self.assertEqual(p.get_snippet(mock_cliargs), EXPECTED_DEV_HELPERS_SNIPPET) self.assertEqual(p.get_preamble(mock_cliargs), '')
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')
def test_env_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': [['ENVVARNAME=envvar_value', 'ENV2=val2'], ['ENV3=val3']]} 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 run_drone_demo(command): plugins = list_plugins() base_image = 'tfoote/drone_demo' desired_plugins = ['nvidia', 'pulse', 'user', 'home', 'x11'] active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins] pull_image(base_image) dig = DockerImageGenerator(active_extensions, {}, base_image) if dig.build() != 0: print ("Failed to build") sys.exit(1) if dig.run(command) != 0: print ("Failed to run") sys.exit(1)
def test_home_extension(self): plugins = list_plugins() home_plugin = plugins['home'] self.assertEqual(home_plugin.get_name(), 'home') p = home_plugin() self.assertTrue(plugin_load_parser_correctly(home_plugin)) mock_cliargs = {} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertTrue('-v %s:%s' % (Path.home(), Path.home()) in args)
def test_privileged_extension(self): plugins = list_plugins() print(plugins) privileged_plugin = plugins['privileged'] self.assertEqual(privileged_plugin.get_name(), 'privileged') p = privileged_plugin() self.assertTrue(plugin_load_parser_correctly(privileged_plugin)) mock_cliargs = {'privileged': True} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertTrue('--privileged' in args)
def test_nvidia_extension_basic(self): plugins = list_plugins() nvidia_plugin = plugins['nvidia'] self.assertEqual(nvidia_plugin.get_name(), 'nvidia') self.assertTrue(plugin_load_parser_correctly(nvidia_plugin)) p = nvidia_plugin() mock_cliargs = {'base_image': 'ubuntu:xenial'} snippet = p.get_snippet(mock_cliargs) self.assertIn( 'COPY --from=glvnd /usr/local/lib/x86_64-linux-gnu /usr/local/lib/x86_64-linux-gnu', snippet) self.assertIn( 'COPY --from=glvnd /usr/local/lib/i386-linux-gnu /usr/local/lib/i386-linux-gnu', snippet) self.assertIn( 'ENV LD_LIBRARY_PATH /usr/local/lib/x86_64-linux-gnu:/usr/local/lib/i386-linux-gnu', snippet) self.assertIn('NVIDIA_VISIBLE_DEVICES', snippet) self.assertIn('NVIDIA_DRIVER_CAPABILITIES', snippet) mock_cliargs = {'base_image': 'ubuntu:bionic'} snippet = p.get_snippet(mock_cliargs) self.assertIn( 'RUN apt-get update && apt-get install -y --no-install-recommends', snippet) self.assertIn(' libglvnd0 ', snippet) self.assertIn(' libgles2 ', snippet) self.assertIn( 'COPY --from=glvnd /usr/share/glvnd/egl_vendor.d/10_nvidia.json /usr/share/glvnd/egl_vendor.d/10_nvidia.json', snippet) self.assertIn('NVIDIA_VISIBLE_DEVICES', snippet) self.assertIn('NVIDIA_DRIVER_CAPABILITIES', snippet) preamble = p.get_preamble(mock_cliargs) self.assertIn('FROM nvidia/opengl:1.0-glvnd-devel-', preamble) docker_args = p.get_docker_args(mock_cliargs) #TODO(tfoote) restore with #37 self.assertIn(' -e DISPLAY -e TERM', docker_args) #TODO(tfoote) restore with #37 self.assertIn(' -e QT_X11_NO_MITSHM=1', docker_args) #TODO(tfoote) restore with #37 self.assertIn(' -e XAUTHORITY=', docker_args) #TODO(tfoote) restore with #37 self.assertIn(' -v /tmp/.X11-unix:/tmp/.X11-unix ', docker_args) #TODO(tfoote) restore with #37 self.assertIn(' -v /etc/localtime:/etc/localtime:ro ', docker_args) if get_docker_version() >= Version("19.03"): self.assertIn(' --gpus all', docker_args) else: self.assertIn(' --runtime=nvidia', docker_args)
def test_x11_extension_basic(self): plugins = list_plugins() x11_plugin = plugins['x11'] self.assertEqual(x11_plugin.get_name(), 'x11') self.assertTrue(plugin_load_parser_correctly(x11_plugin)) p = x11_plugin() mock_cliargs = {'base_image': 'ubuntu:xenial'} docker_args = p.get_docker_args(mock_cliargs) self.assertIn(' -e DISPLAY -e TERM', docker_args) self.assertIn(' -e QT_X11_NO_MITSHM=1', docker_args) self.assertIn(' -e XAUTHORITY=', docker_args) self.assertIn(' -v /tmp/.X11-unix:/tmp/.X11-unix ', docker_args) self.assertIn(' -v /etc/localtime:/etc/localtime:ro ', docker_args)
def test_user_collisions(self): plugins = list_plugins() user_plugin = plugins['user'] self.assertEqual(user_plugin.get_name(), 'user') uid = os.getuid() + 1 COLLIDING_UID_DOCKERFILE = f"""FROM ubuntu:jammy RUN useradd test -u{uid} """ iof = StringIO(COLLIDING_UID_DOCKERFILE.encode()) image_id = docker_build( fileobj=iof, #output_callback=output_callback, nocache=True, forcerm=True, tag="rocker:" + f"user_extension_test_uid_collision") print(f'Image id is {image_id}') self.assertTrue( image_id, f"Image failed to build >>>{COLLIDING_UID_DOCKERFILE}<<<") # Test Colliding UID but not name build_args = { 'user': True, 'user_override_name': 'test2', 'user_preserve_home': True, # 'command': 'ls -l && touch /home/test2/home_directory_access_verification', 'command': 'touch /home/test2/testwrite', } dig = DockerImageGenerator([user_plugin()], build_args, image_id) exit_code = dig.build(**build_args) self.assertTrue(exit_code == 0, f"Build failed with exit code {exit_code}") run_exit_code = dig.run(**build_args) self.assertTrue(run_exit_code == 0, f"Run failed with exit code {run_exit_code}") # Test colliding UID and name build_args['user_override_name'] = 'test' build_args['command'] = 'touch /home/test/testwrite' dig = DockerImageGenerator([user_plugin()], build_args, image_id) exit_code = dig.build(**build_args) self.assertTrue(exit_code == 0, f"Build failed with exit code {exit_code}") run_exit_code = dig.run(**build_args) self.assertTrue(run_exit_code == 0, f"Run failed with exit code {run_exit_code}")
def test_network_extension(self): plugins = list_plugins() network_plugin = plugins['network'] self.assertEqual(network_plugin.get_name(), 'network') p = network_plugin() self.assertTrue(plugin_load_parser_correctly(network_plugin)) mock_cliargs = {'network': 'none'} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertTrue('--network none' in args) mock_cliargs = {'network': 'host'} args = p.get_docker_args(mock_cliargs) self.assertTrue('--network host' in args)
def test_name_extension(self): plugins = list_plugins() name_plugin = plugins['name'] self.assertEqual(name_plugin.get_name(), 'name') p = name_plugin() self.assertTrue(plugin_load_parser_correctly(name_plugin)) mock_cliargs = {'name': 'none'} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertTrue('--name none' in args) mock_cliargs = {'name': 'docker_name'} args = p.get_docker_args(mock_cliargs) self.assertTrue('--name docker_name' in args)
def test_git_extension(self): plugins = list_plugins() git_plugin = plugins['git'] self.assertEqual(git_plugin.get_name(), 'git') p = git_plugin() self.assertTrue(plugin_load_parser_correctly(git_plugin)) mock_cliargs = {} mock_config_file = tempfile.NamedTemporaryFile() mock_system_config_file = tempfile.NamedTemporaryFile() mock_cliargs['git_config_path'] = mock_config_file.name mock_cliargs['git_config_path_system'] = mock_system_config_file.name args = p.get_docker_args(mock_cliargs) system_gitconfig = mock_system_config_file.name system_gitconfig_target = '/etc/gitconfig' user_gitconfig = mock_config_file.name user_gitconfig_target = '/root/.gitconfig' self.assertIn('-v %s:%s' % (system_gitconfig, system_gitconfig_target), args) self.assertIn('-v %s:%s' % (user_gitconfig, user_gitconfig_target), args) # Test with user "enabled" mock_cliargs = {'user': True} mock_cliargs['git_config_path'] = mock_config_file.name user_args = p.get_docker_args(mock_cliargs) user_gitconfig_target = os.path.expanduser('~/.gitconfig') self.assertIn('-v %s:%s' % (user_gitconfig, user_gitconfig_target), user_args) # Test with overridden user mock_cliargs['user_override_name'] = 'testusername' user_args = p.get_docker_args(mock_cliargs) user_gitconfig_target = '/home/testusername/.gitconfig' self.assertIn('-v %s:%s' % (user_gitconfig, user_gitconfig_target), user_args) # Test non-extant files no generation mock_cliargs['git_config_path'] = '/path-does-not-exist' mock_cliargs['git_config_path_system'] = '/path-does-not-exist-either' user_args = p.get_docker_args(mock_cliargs) self.assertNotIn('-v', user_args)
def test_devices_extension(self): plugins = list_plugins() devices_plugin = plugins['devices'] self.assertEqual(devices_plugin.get_name(), 'devices') p = devices_plugin() self.assertTrue(plugin_load_parser_correctly(devices_plugin)) mock_cliargs = {'devices': ['/dev/random']} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertTrue('--device /dev/random' in args) # Check case for invalid device mock_cliargs = {'devices': ['/dev/does_not_exist']} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') args = p.get_docker_args(mock_cliargs) self.assertFalse('--device' in args)
def test_ssh_extension(self): plugins = list_plugins() ssh_plugin = plugins['ssh'] self.assertEqual(ssh_plugin.get_name(), 'ssh') p = ssh_plugin() self.assertTrue(plugin_load_parser_correctly(ssh_plugin)) mock_cliargs = {} self.assertEqual(p.get_snippet(mock_cliargs), '') self.assertEqual(p.get_preamble(mock_cliargs), '') # with SSH_AUTH_SOCK set os.environ['SSH_AUTH_SOCK'] = 'foo' args = p.get_docker_args(mock_cliargs) self.assertIn( '-e SSH_AUTH_SOCK -v ' + shlex.quote( '{SSH_AUTH_SOCK}:{SSH_AUTH_SOCK}'.format(**os.environ)), args) #without it set del os.environ['SSH_AUTH_SOCK'] args = p.get_docker_args(mock_cliargs) self.assertNotIn('SSH_AUTH_SOCK', args)
def test_nvidia_env_subs(self): plugins = list_plugins() nvidia_plugin = plugins['nvidia'] p = nvidia_plugin() # base image doesn't exist mock_cliargs = {'base_image': 'ros:does-not-exist'} with self.assertRaises(SystemExit) as cm: p.get_environment_subs(mock_cliargs) self.assertEqual(cm.exception.code, 1) # unsupported version mock_cliargs = {'base_image': 'ubuntu:17.04'} with self.assertRaises(SystemExit) as cm: p.get_environment_subs(mock_cliargs) self.assertEqual(cm.exception.code, 1) # unsupported os mock_cliargs = {'base_image': 'debian'} with self.assertRaises(SystemExit) as cm: p.get_environment_subs(mock_cliargs) self.assertEqual(cm.exception.code, 1)