diff --git a/setup.py b/setup.py index 88aa21e3..c60803cc 100644 --- a/setup.py +++ b/setup.py @@ -44,12 +44,14 @@ 'devices = rocker.extensions:Devices', 'dev_helpers = rocker.extensions:DevHelpers', 'env = rocker.extensions:Environment', + 'expose = rocker.extensions:Expose', 'git = rocker.git_extension:Git', 'home = rocker.extensions:HomeDir', 'volume = rocker.volume_extension:Volume', 'name = rocker.extensions:Name', 'network = rocker.extensions:Network', 'nvidia = rocker.nvidia_extension:Nvidia', + 'port = rocker.extensions:Port', 'privileged = rocker.extensions:Privileged', 'pulse = rocker.extensions:PulseAudio', 'ssh = rocker.ssh_extension:Ssh', diff --git a/src/rocker/extensions.py b/src/rocker/extensions.py index 9c376124..bdfcd4a2 100644 --- a/src/rocker/extensions.py +++ b/src/rocker/extensions.py @@ -139,6 +139,59 @@ def register_arguments(parser, defaults={}): default=defaults.get('network', None), help="What network configuration to use.") + +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 + def get_name(): + return 'port' + + def __init__(self): + self.name = Port.get_name() + + def get_preamble(self, cliargs): + return '' + + def get_docker_args(self, cliargs): + args = [''] + ports = cliargs.get('port', []) + for port in ports: + args.append(' -p {0}'.format(port)) + return ' '.join(args) + + @staticmethod + def register_arguments(parser, defaults={}): + parser.add_argument('--port', + default=defaults.get('port', None), + action='append', + help="Binds port from the container to host machine.") + + class PulseAudio(RockerExtension): @staticmethod def get_name(): diff --git a/test/test_extension.py b/test/test_extension.py index 34a387ff..0c6aa7b4 100644 --- a/test/test_extension.py +++ b/test/test_extension.py @@ -146,6 +146,71 @@ def test_network_extension(self): args = p.get_docker_args(mock_cliargs) self.assertTrue('--network host' in args) +class ExposeExtensionTest(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_expose_extension(self): + plugins = list_plugins() + expose_plugin = plugins['expose'] + self.assertEqual(expose_plugin.get_name(), 'expose') + + p = expose_plugin() + self.assertTrue(plugin_load_parser_correctly(expose_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.assertNotIn('--expose', args) + + mock_cliargs = {'expose': ['80', '8080']} + args = p.get_docker_args(mock_cliargs) + self.assertIn('--expose 80', args) + self.assertIn('--expose 8080', args) + +class PortExtensionTest(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_port_extension(self): + plugins = list_plugins() + port_plugin = plugins['port'] + self.assertEqual(port_plugin.get_name(), 'port') + + p = port_plugin() + self.assertTrue(plugin_load_parser_correctly(port_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.assertNotIn('-p', args) + + mock_cliargs = {'port': ['80:8080', '81:8081']} + args = p.get_docker_args(mock_cliargs) + self.assertIn('-p 80:8080', args) + self.assertIn('-p 81:8081', args) class NameExtensionTest(unittest.TestCase):