diff --git a/.gitignore b/.gitignore index 9bba9d4a..df2600f6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ deb_dist *.pyc .coverage build +rocker_venv \ No newline at end of file diff --git a/src/rocker/cli.py b/src/rocker/cli.py index d6f68311..a1d0641d 100755 --- a/src/rocker/cli.py +++ b/src/rocker/cli.py @@ -35,6 +35,7 @@ def main(): parser.add_argument('command', nargs='*', default='') parser.add_argument('--noexecute', action='store_true', help='Deprecated') parser.add_argument('--nocache', action='store_true') + parser.add_argument('--nocleanup', action='store_true', help='do not remove the docker container when stopped') parser.add_argument('--pull', action='store_true') parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + get_rocker_version()) diff --git a/src/rocker/core.py b/src/rocker/core.py index 71d919ce..ac5ae979 100755 --- a/src/rocker/core.py +++ b/src/rocker/core.py @@ -239,6 +239,36 @@ def build(self, **kwargs): print("Docker build failed\n", ex) return 1 + def get_operating_mode(self, args): + operating_mode = args.get('mode') + # Default to non-interactive if unset + if operating_mode not in OPERATION_MODES: + operating_mode = OPERATIONS_NON_INTERACTIVE + if operating_mode == OPERATIONS_INTERACTIVE and not os.isatty(sys.__stdin__.fileno()): + operating_mode = OPERATIONS_NON_INTERACTIVE + print("No tty detected for stdin forcing non-interactive") + return operating_mode + + + def generate_docker_cmd(self, command='', **kwargs): + docker_args = '' + + for e in self.active_extensions: + docker_args += e.get_docker_args(self.cliargs) + + image = self.image_id + cmd = "docker run" + if(not kwargs.get('nocleanup')): + # remove container only if --nocleanup is not present + cmd += " --rm" + + operating_mode = self.get_operating_mode(kwargs) + if operating_mode != OPERATIONS_NON_INTERACTIVE: + # only disable for OPERATIONS_NON_INTERACTIVE + cmd += " -it" + cmd += "%(docker_args)s %(image)s %(command)s" % locals() + return cmd + def run(self, command='', **kwargs): if not self.built: print("Cannot run if build has not passed.") @@ -250,28 +280,11 @@ def run(self, command='', **kwargs): except subprocess.CalledProcessError as ex: print("ERROR! Failed to precondition for extension [%s] with error: %s\ndeactivating" % (e.get_name(), ex)) return 1 - docker_args = '' - for e in self.active_extensions: - docker_args += e.get_docker_args(self.cliargs) + cmd = self.generate_docker_cmd(command, **kwargs) + operating_mode = self.get_operating_mode(kwargs) - image = self.image_id - operating_mode = kwargs.get('mode') - # Default to non-interactive if unset - if operating_mode not in OPERATION_MODES: - operating_mode = OPERATIONS_NON_INTERACTIVE - if operating_mode == OPERATIONS_INTERACTIVE and not os.isatty(sys.__stdin__.fileno()): - operating_mode = OPERATIONS_NON_INTERACTIVE - print("No tty detected for stdin forcing non-interactive") - cmd="docker run" - if operating_mode != OPERATIONS_NON_INTERACTIVE: - # only disable for OPERATIONS_NON_INTERACTIVE - cmd += " -it" - cmd += " \ - --rm \ - %(docker_args)s \ - %(image)s %(command)s" % locals() -# $DOCKER_OPTS \ + # $DOCKER_OPTS \ if operating_mode == OPERATIONS_DRY_RUN: print("Run this command: \n\n\n") print(cmd) diff --git a/test/test_core.py b/test/test_core.py index d874ec61..914d8437 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -120,4 +120,30 @@ def test_extension_manager(self): active_extensions = active_extensions = extension_manager.get_active_extensions({'user': True, 'ssh': True, 'extension_blacklist': ['ssh']}) self.assertEqual(len(active_extensions), 1) - self.assertEqual(active_extensions[0].get_name(), 'user') \ No newline at end of file + self.assertEqual(active_extensions[0].get_name(), 'user') + + def test_docker_cmd_interactive(self): + dig = DockerImageGenerator([], {}, 'ubuntu:bionic') + + self.assertNotIn('-it', dig.generate_docker_cmd(mode='')) + self.assertIn('-it', dig.generate_docker_cmd(mode='dry-run')) + + # TODO(tfoote) mock this appropriately + # google actions tests don't have a tty, local tests do + import os, sys + if os.isatty(sys.__stdin__.fileno()): + self.assertIn('-it', dig.generate_docker_cmd(mode='interactive')) + else: + self.assertNotIn('-it', dig.generate_docker_cmd(mode='interactive')) + + self.assertNotIn('-it', dig.generate_docker_cmd(mode='non-interactive')) + + + def test_docker_cmd_nocleanup(self): + dig = DockerImageGenerator([], {}, 'ubuntu:bionic') + + self.assertIn('--rm', dig.generate_docker_cmd()) + self.assertIn('--rm', dig.generate_docker_cmd(mode='dry-run')) + self.assertIn('--rm', dig.generate_docker_cmd(nocleanup='')) + + self.assertNotIn('--rm', dig.generate_docker_cmd(nocleanup='true')) \ No newline at end of file