From 658803edf885f490168e223d07b2b1a2cbd22aae Mon Sep 17 00:00:00 2001 From: Simon van der Veldt Date: Mon, 22 Feb 2016 21:05:59 +0100 Subject: [PATCH 1/2] Add -w or --workdir to compose run to override workdir from commandline Signed-off-by: Simon van der Veldt --- compose/cli/main.py | 4 ++++ docs/reference/run.md | 1 + tests/acceptance/cli_test.py | 18 ++++++++++++++++++ tests/fixtures/run-workdir/docker-compose.yml | 4 ++++ tests/unit/cli_test.py | 3 +++ 5 files changed, 30 insertions(+) create mode 100644 tests/fixtures/run-workdir/docker-compose.yml diff --git a/compose/cli/main.py b/compose/cli/main.py index 6636216828c..146b77b4cc4 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -527,6 +527,7 @@ def run(self, options): to the host. -T Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY. + -w, --workdir="" Working directory inside the container """ service = self.project.get_service(options['SERVICE']) detach = options['-d'] @@ -576,6 +577,9 @@ def run(self, options): if options['--name']: container_options['name'] = options['--name'] + if options['--workdir']: + container_options['working_dir'] = options['--workdir'] + run_one_off_container(container_options, self.project, service, options) def scale(self, options): diff --git a/docs/reference/run.md b/docs/reference/run.md index 21890c60a92..863544246d2 100644 --- a/docs/reference/run.md +++ b/docs/reference/run.md @@ -26,6 +26,7 @@ Options: -p, --publish=[] Publish a container's port(s) to the host --service-ports Run command with the service's ports enabled and mapped to the host. -T Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY. +-w, --workdir="" Working directory inside the container ``` Runs a one-time command against a service. For example, the following command starts the `web` service and runs `bash` as its command. diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 825b97bed07..a712de8a6c0 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -1025,6 +1025,24 @@ def test_run_with_custom_name(self): container, = service.containers(stopped=True, one_off=True) self.assertEqual(container.name, name) + def test_run_service_with_workdir_overridden(self): + self.base_dir = 'tests/fixtures/run-workdir' + name = 'service' + workdir = '/var' + self.dispatch(['run', '--workdir={workdir}'.format(workdir=workdir), name]) + service = self.project.get_service(name) + container = service.containers(stopped=True, one_off=True)[0] + self.assertEqual(workdir, container.get('Config.WorkingDir')) + + def test_run_service_with_workdir_overridden_short_form(self): + self.base_dir = 'tests/fixtures/run-workdir' + name = 'service' + workdir = '/var' + self.dispatch(['run', '-w', workdir, name]) + service = self.project.get_service(name) + container = service.containers(stopped=True, one_off=True)[0] + self.assertEqual(workdir, container.get('Config.WorkingDir')) + @v2_only() def test_run_interactive_connects_to_network(self): self.base_dir = 'tests/fixtures/networks' diff --git a/tests/fixtures/run-workdir/docker-compose.yml b/tests/fixtures/run-workdir/docker-compose.yml new file mode 100644 index 00000000000..dc3ea86a0fd --- /dev/null +++ b/tests/fixtures/run-workdir/docker-compose.yml @@ -0,0 +1,4 @@ +service: + image: busybox:latest + working_dir: /etc + command: /bin/true diff --git a/tests/unit/cli_test.py b/tests/unit/cli_test.py index 1d7c13e7e93..e0ada460d64 100644 --- a/tests/unit/cli_test.py +++ b/tests/unit/cli_test.py @@ -102,6 +102,7 @@ def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_ '--publish': [], '--rm': None, '--name': None, + '--workdir': None, }) _, _, call_kwargs = mock_run_operation.mock_calls[0] @@ -135,6 +136,7 @@ def test_run_service_with_restart_always(self): '--publish': [], '--rm': None, '--name': None, + '--workdir': None, }) self.assertEquals( @@ -156,6 +158,7 @@ def test_run_service_with_restart_always(self): '--publish': [], '--rm': True, '--name': None, + '--workdir': None, }) self.assertFalse( From 52b791a2647af6e7ace5b2b1ea480fbec16dc08d Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Fri, 26 Feb 2016 14:24:02 -0800 Subject: [PATCH 2/2] Split off build_container_options() to reduce the complexity of run Signed-off-by: Daniel Nephin --- compose/cli/main.py | 75 ++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 146b77b4cc4..486fb151659 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -538,48 +538,18 @@ def run(self, options): "Please pass the -d flag when using `docker-compose run`." ) - if options['COMMAND']: - command = [options['COMMAND']] + options['ARGS'] - else: - command = service.options.get('command') - - container_options = { - 'command': command, - 'tty': not (detach or options['-T'] or not sys.stdin.isatty()), - 'stdin_open': not detach, - 'detach': detach, - } - - if options['-e']: - container_options['environment'] = parse_environment(options['-e']) - - if options['--entrypoint']: - container_options['entrypoint'] = options.get('--entrypoint') - - if options['--rm']: - container_options['restart'] = None - - if options['--user']: - container_options['user'] = options.get('--user') - - if not options['--service-ports']: - container_options['ports'] = [] - - if options['--publish']: - container_options['ports'] = options.get('--publish') - if options['--publish'] and options['--service-ports']: raise UserError( 'Service port mapping and manual port mapping ' 'can not be used togather' ) - if options['--name']: - container_options['name'] = options['--name'] - - if options['--workdir']: - container_options['working_dir'] = options['--workdir'] + if options['COMMAND']: + command = [options['COMMAND']] + options['ARGS'] + else: + command = service.options.get('command') + container_options = build_container_options(options, detach, command) run_one_off_container(container_options, self.project, service, options) def scale(self, options): @@ -780,6 +750,41 @@ def build_action_from_opts(options): return BuildAction.none +def build_container_options(options, detach, command): + container_options = { + 'command': command, + 'tty': not (detach or options['-T'] or not sys.stdin.isatty()), + 'stdin_open': not detach, + 'detach': detach, + } + + if options['-e']: + container_options['environment'] = parse_environment(options['-e']) + + if options['--entrypoint']: + container_options['entrypoint'] = options.get('--entrypoint') + + if options['--rm']: + container_options['restart'] = None + + if options['--user']: + container_options['user'] = options.get('--user') + + if not options['--service-ports']: + container_options['ports'] = [] + + if options['--publish']: + container_options['ports'] = options.get('--publish') + + if options['--name']: + container_options['name'] = options['--name'] + + if options['--workdir']: + container_options['working_dir'] = options['--workdir'] + + return container_options + + def run_one_off_container(container_options, project, service, options): if not options['--no-deps']: deps = service.get_dependency_names()