diff --git a/compose/cli/main.py b/compose/cli/main.py index 079ea160a..3777d518a 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -179,7 +179,7 @@ class TopLevelCommand(object): """Define and run multi-container applications with Docker. Usage: - docker-compose [-f ...] [options] [COMMAND] [ARGS...] + docker-compose [-f ...] [options] [--] [COMMAND] [ARGS...] docker-compose -h|--help Options: @@ -256,7 +256,7 @@ class TopLevelCommand(object): e.g. `composetest_db`. If you change a service's `Dockerfile` or the contents of its build directory, you can run `docker-compose build` to rebuild it. - Usage: build [options] [--build-arg key=val...] [SERVICE...] + Usage: build [options] [--build-arg key=val...] [--] [SERVICE...] Options: --build-arg key=val Set build-time variables for services. @@ -422,7 +422,7 @@ class TopLevelCommand(object): """ Receive real time events from containers. - Usage: events [options] [SERVICE...] + Usage: events [options] [--] [SERVICE...] Options: --json Output events as a stream of json objects @@ -447,7 +447,7 @@ class TopLevelCommand(object): """ Execute a command in a running container - Usage: exec [options] [-e KEY=VAL...] SERVICE COMMAND [ARGS...] + Usage: exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...] Options: -d, --detach Detached mode: Run command in the background. @@ -535,7 +535,7 @@ class TopLevelCommand(object): def images(self, options): """ List images used by the created containers. - Usage: images [options] [SERVICE...] + Usage: images [options] [--] [SERVICE...] Options: -q, --quiet Only display IDs @@ -590,7 +590,7 @@ class TopLevelCommand(object): """ Force stop service containers. - Usage: kill [options] [SERVICE...] + Usage: kill [options] [--] [SERVICE...] Options: -s SIGNAL SIGNAL to send to the container. @@ -604,7 +604,7 @@ class TopLevelCommand(object): """ View output from containers. - Usage: logs [options] [SERVICE...] + Usage: logs [options] [--] [SERVICE...] Options: --no-color Produce monochrome output. @@ -647,7 +647,7 @@ class TopLevelCommand(object): """ Print the public port for a port binding. - Usage: port [options] SERVICE PRIVATE_PORT + Usage: port [options] [--] SERVICE PRIVATE_PORT Options: --protocol=proto tcp or udp [default: tcp] @@ -668,7 +668,7 @@ class TopLevelCommand(object): """ List containers. - Usage: ps [options] [SERVICE...] + Usage: ps [options] [--] [SERVICE...] Options: -q, --quiet Only display IDs @@ -724,7 +724,7 @@ class TopLevelCommand(object): """ Pulls images for services defined in a Compose file, but does not start the containers. - Usage: pull [options] [SERVICE...] + Usage: pull [options] [--] [SERVICE...] Options: --ignore-pull-failures Pull what it can and ignores images with pull failures. @@ -747,7 +747,7 @@ class TopLevelCommand(object): """ Pushes images for services. - Usage: push [options] [SERVICE...] + Usage: push [options] [--] [SERVICE...] Options: --ignore-push-failures Push what it can and ignores images with push failures. @@ -766,7 +766,7 @@ class TopLevelCommand(object): Any data which is not in a volume will be lost. - Usage: rm [options] [SERVICE...] + Usage: rm [options] [--] [SERVICE...] Options: -f, --force Don't ask to confirm removal @@ -814,7 +814,7 @@ class TopLevelCommand(object): `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`. Usage: - run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] + run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] [--] SERVICE [COMMAND] [ARGS...] Options: @@ -904,7 +904,7 @@ class TopLevelCommand(object): They can be started again with `docker-compose start`. - Usage: stop [options] [SERVICE...] + Usage: stop [options] [--] [SERVICE...] Options: -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. @@ -917,7 +917,7 @@ class TopLevelCommand(object): """ Restart running containers. - Usage: restart [options] [SERVICE...] + Usage: restart [options] [--] [SERVICE...] Options: -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. @@ -982,7 +982,7 @@ class TopLevelCommand(object): If you want to force Compose to stop and recreate all containers, use the `--force-recreate` flag. - Usage: up [options] [--scale SERVICE=NUM...] [SERVICE...] + Usage: up [options] [--scale SERVICE=NUM...] [--] [SERVICE...] Options: -d, --detach Detached mode: Run containers in the background, diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 180c3824f..df4e72aec 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -187,7 +187,7 @@ class CLITestCase(DockerClientTestCase): def test_help(self): self.base_dir = 'tests/fixtures/no-composefile' result = self.dispatch(['help', 'up'], returncode=0) - assert 'Usage: up [options] [--scale SERVICE=NUM...] [SERVICE...]' in result.stdout + assert 'Usage: up [options] [--scale SERVICE=NUM...] [--] [SERVICE...]' in result.stdout # Prevent tearDown from trying to create a project self.base_dir = None @@ -2862,3 +2862,129 @@ services: assert re.search(r'foo1.+test[ \t]+dev', result.stdout) is not None assert re.search(r'foo2.+test[ \t]+prod', result.stdout) is not None assert re.search(r'foo3.+test[ \t]+latest', result.stdout) is not None + + def test_build_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + result = self.dispatch(['build', '--pull', '--', '--test-service']) + + assert BUILD_PULL_TEXT in result.stdout + + def test_events_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + events_proc = start_process(self.base_dir, ['events', '--json', '--', '--test-service']) + self.dispatch(['up', '-d', '--', '--test-service']) + wait_on_condition(ContainerCountCondition(self.project, 1)) + + os.kill(events_proc.pid, signal.SIGINT) + result = wait_on_process(events_proc, returncode=1) + lines = [json.loads(line) for line in result.stdout.rstrip().split('\n')] + assert Counter(e['action'] for e in lines) == {'create': 1, 'start': 1} + + def test_exec_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + assert len(self.project.containers()) == 1 + + stdout, stderr = self.dispatch(['exec', '-T', '--', '--test-service', 'ls', '-1d', '/']) + + assert stderr == "" + assert stdout == "/\n" + + def test_images_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + result = self.dispatch(['images', '--', '--test-service']) + + assert "busybox" in result.stdout + + def test_kill_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + service = self.project.get_service('--test-service') + + assert len(service.containers()) == 1 + assert service.containers()[0].is_running + + self.dispatch(['kill', '--', '--test-service']) + + assert len(service.containers(stopped=True)) == 1 + assert not service.containers(stopped=True)[0].is_running + + def test_logs_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--log-service']) + result = self.dispatch(['logs', '--', '--log-service']) + + assert 'hello' in result.stdout + assert 'exited with' not in result.stdout + + def test_port_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + result = self.dispatch(['port', '--', '--test-service', '80']) + + assert result.stdout.strip() == "0.0.0.0:8080" + + def test_ps_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + + result = self.dispatch(['ps', '--', '--test-service']) + + assert 'flag-as-service-name_--test-service_1' in result.stdout + + def test_pull_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + result = self.dispatch(['pull', '--', '--test-service']) + + assert 'Pulling --test-service' in result.stderr + assert 'failed' not in result.stderr + + def test_rm_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '--no-start', '--', '--test-service']) + service = self.project.get_service('--test-service') + assert len(service.containers(stopped=True)) == 1 + + self.dispatch(['rm', '--force', '--', '--test-service']) + assert len(service.containers(stopped=True)) == 0 + + def test_run_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + result = self.dispatch(['run', '--no-deps', '--', '--test-service', 'echo', '-hello']) + + assert 'hello' in result.stdout + assert len(self.project.containers()) == 0 + + def test_stop_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + service = self.project.get_service('--test-service') + assert len(service.containers()) == 1 + assert service.containers()[0].is_running + + self.dispatch(['stop', '-t', '1', '--', '--test-service']) + + assert len(service.containers(stopped=True)) == 1 + assert not service.containers(stopped=True)[0].is_running + + def test_restart_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service']) + service = self.project.get_service('--test-service') + assert len(service.containers()) == 1 + assert service.containers()[0].is_running + + self.dispatch(['restart', '-t', '1', '--', '--test-service']) + + assert len(service.containers()) == 1 + assert service.containers()[0].is_running + + def test_up_with_stop_process_flag(self): + self.base_dir = 'tests/fixtures/flag-as-service-name' + self.dispatch(['up', '-d', '--', '--test-service', '--log-service']) + + service = self.project.get_service('--test-service') + another = self.project.get_service('--log-service') + assert len(service.containers()) == 1 + assert len(another.containers()) == 1 diff --git a/tests/fixtures/flag-as-service-name/Dockerfile b/tests/fixtures/flag-as-service-name/Dockerfile new file mode 100644 index 000000000..098ff3eb1 --- /dev/null +++ b/tests/fixtures/flag-as-service-name/Dockerfile @@ -0,0 +1,3 @@ +FROM busybox:1.27.2 +LABEL com.docker.compose.test_image=true +CMD echo "success" diff --git a/tests/fixtures/flag-as-service-name/docker-compose.yml b/tests/fixtures/flag-as-service-name/docker-compose.yml new file mode 100644 index 000000000..5b519a63e --- /dev/null +++ b/tests/fixtures/flag-as-service-name/docker-compose.yml @@ -0,0 +1,12 @@ +version: "2" +services: + --test-service: + image: busybox:1.27.0.2 + build: . + command: top + ports: + - "8080:80" + + --log-service: + image: busybox:1.31.0-uclibc + command: sh -c "echo hello && tail -f /dev/null"