From 64c18c71c77818796c173d4f2c8122a530278236 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Fri, 30 Aug 2024 14:57:58 +0200 Subject: [PATCH 1/6] Add IPC support to RockerExtension - Introduced a new IPC class that extends RockerExtension to handle IPC namespace options. - Implemented `get_name` to return the 'ipc' identifier. - Added `get_docker_args` method to generate Docker IPC arguments based on CLI input. - Included a `get_preamble` method that returns an empty string as no preamble is needed. This commit enables the use of IPC-related Docker arguments in Rocker configurations. --- README.md | 2 +- setup.py | 1 + src/rocker/extensions.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1941818..9e9bb74 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can get full details on the extensions from the main `rocker --help` command - pulse -- Mount pulse audio into the container - ssh -- Pass through ssh access to the container. -As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, and `privileged`. +As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, `ipc`, and `privileged`. ### Externally maintained extensions diff --git a/setup.py b/setup.py index 35c0594..3de76b5 100644 --- a/setup.py +++ b/setup.py @@ -56,6 +56,7 @@ 'hostname = rocker.extensions:Hostname', 'name = rocker.extensions:Name', 'network = rocker.extensions:Network', + 'ipc = rocker.extensions:IPC', 'nvidia = rocker.nvidia_extension:Nvidia', 'port = rocker.extensions:Port', 'privileged = rocker.extensions:Privileged', diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index bf5e773..1366538 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -162,6 +162,26 @@ def register_arguments(parser, defaults={}): default=defaults.get('network', None), help="What network configuration to use.") +class IPC(RockerExtension): + @staticmethod + def get_name(): + return 'ipc' + def __init__(self): + self.name = IPC.get_name() + + def get_preamble(self, cliargs): + return '' + + def get_docker_args(self, cliargs): + args = '' + ipc = cliargs.get('ipc', None) + args += ' --ipc %s ' % ipc + return args + + @staticmethod + def register_arguments(parser, defaults={}): + parser.add_argument('--ipc', default=defaults.get('ipc', 'private'), + help='IPC namespace to use.') class Expose(RockerExtension): @staticmethod From 3ba3a36223567a4f398d16b6c3c0eaef73e73b66 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Fri, 30 Aug 2024 21:34:13 +0200 Subject: [PATCH 2/6] Revert "Merge pull request #1 from sachinkum0009/improvement/added-ipc-flag" This reverts commit 27cbd5884ca2c85f88aad3384c4c888ee02a9130, reversing changes made to 73ab0d61fbcd583b89441b92640561550b634b2b. --- README.md | 2 +- setup.py | 1 - src/rocker/extensions.py | 20 -------------------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/README.md b/README.md index faea049..bef60f6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can get full details on the extensions from the main `rocker --help` command - pulse -- Mount pulse audio into the container - ssh -- Pass through ssh access to the container. -As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, `ipc`, and `privileged`. +As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, and `privileged`. ### Externally maintained extensions diff --git a/setup.py b/setup.py index 5c074ef..5ba172e 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,6 @@ 'hostname = rocker.extensions:Hostname', 'name = rocker.extensions:Name', 'network = rocker.extensions:Network', - 'ipc = rocker.extensions:IPC', 'nvidia = rocker.nvidia_extension:Nvidia', 'port = rocker.extensions:Port', 'privileged = rocker.extensions:Privileged', diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index 1366538..bf5e773 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -162,26 +162,6 @@ def register_arguments(parser, defaults={}): default=defaults.get('network', None), help="What network configuration to use.") -class IPC(RockerExtension): - @staticmethod - def get_name(): - return 'ipc' - def __init__(self): - self.name = IPC.get_name() - - def get_preamble(self, cliargs): - return '' - - def get_docker_args(self, cliargs): - args = '' - ipc = cliargs.get('ipc', None) - args += ' --ipc %s ' % ipc - return args - - @staticmethod - def register_arguments(parser, defaults={}): - parser.add_argument('--ipc', default=defaults.get('ipc', 'private'), - help='IPC namespace to use.') class Expose(RockerExtension): @staticmethod From ec683df896d2bdd3f4d40915605d2cfdd64725d0 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Fri, 30 Aug 2024 14:57:58 +0200 Subject: [PATCH 3/6] Add IPC support to RockerExtension - Introduced a new IPC class that extends RockerExtension to handle IPC namespace options. - Implemented `get_name` to return the 'ipc' identifier. - Added `get_docker_args` method to generate Docker IPC arguments based on CLI input. - Included a `get_preamble` method that returns an empty string as no preamble is needed. This commit enables the use of IPC-related Docker arguments in Rocker configurations. --- README.md | 2 +- setup.py | 1 + src/rocker/extensions.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bef60f6..faea049 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can get full details on the extensions from the main `rocker --help` command - pulse -- Mount pulse audio into the container - ssh -- Pass through ssh access to the container. -As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, and `privileged`. +As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, `ipc`, and `privileged`. ### Externally maintained extensions diff --git a/setup.py b/setup.py index 5ba172e..5c074ef 100644 --- a/setup.py +++ b/setup.py @@ -56,6 +56,7 @@ 'hostname = rocker.extensions:Hostname', 'name = rocker.extensions:Name', 'network = rocker.extensions:Network', + 'ipc = rocker.extensions:IPC', 'nvidia = rocker.nvidia_extension:Nvidia', 'port = rocker.extensions:Port', 'privileged = rocker.extensions:Privileged', diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index bf5e773..1366538 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -162,6 +162,26 @@ def register_arguments(parser, defaults={}): default=defaults.get('network', None), help="What network configuration to use.") +class IPC(RockerExtension): + @staticmethod + def get_name(): + return 'ipc' + def __init__(self): + self.name = IPC.get_name() + + def get_preamble(self, cliargs): + return '' + + def get_docker_args(self, cliargs): + args = '' + ipc = cliargs.get('ipc', None) + args += ' --ipc %s ' % ipc + return args + + @staticmethod + def register_arguments(parser, defaults={}): + parser.add_argument('--ipc', default=defaults.get('ipc', 'private'), + help='IPC namespace to use.') class Expose(RockerExtension): @staticmethod From daef32aede4a8c7b1fb8e193b61c065b68bfdc50 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Mon, 2 Sep 2024 12:52:08 +0200 Subject: [PATCH 4/6] adding a full link for the options documentation Co-authored-by: Tully Foote --- src/rocker/extensions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index 1366538..c111068 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -181,7 +181,7 @@ def get_docker_args(self, cliargs): @staticmethod def register_arguments(parser, defaults={}): parser.add_argument('--ipc', default=defaults.get('ipc', 'private'), - help='IPC namespace to use.') + help='IPC namespace to use. To share ipc with the host use host. More details can be found at https://docs.docker.com/reference/cli/docker/container/run/#ipc') class Expose(RockerExtension): @staticmethod From b23bf60d26d5e987350bd74ca67dc23f6b8cfc44 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Mon, 2 Sep 2024 13:53:28 +0200 Subject: [PATCH 5/6] alphabetical order for ease of maintenance and readability. --- setup.py | 2 +- src/rocker/extensions.py | 95 +++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/setup.py b/setup.py index 5c074ef..4d66983 100644 --- a/setup.py +++ b/setup.py @@ -54,9 +54,9 @@ 'group_add = rocker.extensions:GroupAdd', 'home = rocker.extensions:HomeDir', 'hostname = rocker.extensions:Hostname', + 'ipc = rocker.extensions:Ipc', 'name = rocker.extensions:Name', 'network = rocker.extensions:Network', - 'ipc = rocker.extensions:IPC', 'nvidia = rocker.nvidia_extension:Nvidia', 'port = rocker.extensions:Port', 'privileged = rocker.extensions:Privileged', diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index c111068..6d66ec6 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -91,6 +91,32 @@ def register_arguments(parser, defaults={}): help="add development tools emacs and byobu to your environment") +class Expose(RockerExtension): + @staticmethod + def get_name(): + return 'expose' + + def __init__(self): + self.name = Expose.get_name() + + def get_preamble(self, cliargs): + return '' + + def get_docker_args(self, cliargs): + args = [''] + ports = cliargs.get('expose', []) + for port in ports: + args.append(' --expose {0}'.format(port)) + return ' '.join(args) + + @staticmethod + def register_arguments(parser, defaults={}): + parser.add_argument('--expose', + default=defaults.get('expose', None), + action='append', + help="Exposes a port from the container to host machine.") + + class Hostname(RockerExtension): @staticmethod def get_name(): @@ -114,6 +140,29 @@ def register_arguments(parser, defaults={}): parser.add_argument('--hostname', default=defaults.get('hostname', ''), help='Hostname of the container.') + +class Ipc(RockerExtension): + @staticmethod + def get_name(): + return 'ipc' + def __init__(self): + self.name = Ipc.get_name() + + def get_preamble(self, cliargs): + return '' + + def get_docker_args(self, cliargs): + args = '' + ipc = cliargs.get('ipc', None) + args += ' --ipc %s ' % ipc + return args + + @staticmethod + def register_arguments(parser, defaults={}): + parser.add_argument('--ipc', default=defaults.get('ipc', None), + help='IPC namespace to use. To share ipc with the host use host. More details can be found at https://docs.docker.com/reference/cli/docker/container/run/#ipc') + + class Name(RockerExtension): @staticmethod def get_name(): @@ -162,52 +211,6 @@ def register_arguments(parser, defaults={}): default=defaults.get('network', None), help="What network configuration to use.") -class IPC(RockerExtension): - @staticmethod - def get_name(): - return 'ipc' - def __init__(self): - self.name = IPC.get_name() - - def get_preamble(self, cliargs): - return '' - - def get_docker_args(self, cliargs): - args = '' - ipc = cliargs.get('ipc', None) - args += ' --ipc %s ' % ipc - return args - - @staticmethod - def register_arguments(parser, defaults={}): - parser.add_argument('--ipc', default=defaults.get('ipc', 'private'), - help='IPC namespace to use. To share ipc with the host use host. More details can be found at https://docs.docker.com/reference/cli/docker/container/run/#ipc') - -class Expose(RockerExtension): - @staticmethod - def get_name(): - return 'expose' - - def __init__(self): - self.name = Expose.get_name() - - def get_preamble(self, cliargs): - return '' - - def get_docker_args(self, cliargs): - args = [''] - ports = cliargs.get('expose', []) - for port in ports: - args.append(' --expose {0}'.format(port)) - return ' '.join(args) - - @staticmethod - def register_arguments(parser, defaults={}): - parser.add_argument('--expose', - default=defaults.get('expose', None), - action='append', - help="Exposes a port from the container to host machine.") - class Port(RockerExtension): @staticmethod From 5aad3d8ac5b960d67de13012a3f7911cd16b8d29 Mon Sep 17 00:00:00 2001 From: Sachin Kumar Date: Mon, 2 Sep 2024 13:56:44 +0200 Subject: [PATCH 6/6] :zap: basic test for ipc for high coverage --- test/test_extension.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/test_extension.py b/test/test_extension.py index 446c692..57eab1e 100644 --- a/test/test_extension.py +++ b/test/test_extension.py @@ -114,6 +114,40 @@ def test_home_extension(self): args = p.get_docker_args(mock_cliargs) self.assertTrue('-v %s:%s' % (Path.home(), Path.home()) in args) + +class IpcExtensionTest(unittest.TestCase): + + def setUp(self): + # Work around interference between empy Interpreter + # stdout proxy and test runner. empy installs a proxy on stdout + # to be able to capture the information. + # And the test runner creates a new stdout object for each test. + # This breaks empy as it assumes that the proxy has persistent + # between instances of the Interpreter class + # empy will error with the exception + # "em.Error: interpreter stdout proxy lost" + em.Interpreter._wasProxyInstalled = False + + @pytest.mark.docker + def test_ipc_extension(self): + plugins = list_plugins() + ipc_plugin = plugins['ipc'] + self.assertEqual(ipc_plugin.get_name(), 'ipc') + + p = ipc_plugin() + self.assertTrue(plugin_load_parser_correctly(ipc_plugin)) + + mock_cliargs = {'ipc': 'none'} + self.assertEqual(p.get_snippet(mock_cliargs), '') + self.assertEqual(p.get_preamble(mock_cliargs), '') + args = p.get_docker_args(mock_cliargs) + self.assertTrue('--ipc none' in args) + + mock_cliargs = {'ipc': 'host'} + args = p.get_docker_args(mock_cliargs) + self.assertTrue('--ipc host' in args) + + class NetworkExtensionTest(unittest.TestCase): def setUp(self):