From 21e312e402e44ff1b2431b8fdef3c3ae0212c6a6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Fri, 17 Nov 2017 17:43:12 -0600 Subject: [PATCH 1/6] Implement --filter flag for docker-compose config --services. Fix #1498 Signed-off-by: Svyatoslav Ilinskiy --- compose/cli/main.py | 61 ++++++++++++++++++- tests/acceptance/cli_test.py | 26 ++++++++ .../config-services-filter/docker-compose.yml | 6 ++ 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/config-services-filter/docker-compose.yml diff --git a/compose/cli/main.py b/compose/cli/main.py index c3e30919d..3e4121420 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -287,7 +287,7 @@ class TopLevelCommand(object): """ Validate and view the Compose file. - Usage: config [options] + Usage: config [options] [-f KEY=VAL...] Options: --resolve-image-digests Pin image tags to digests. @@ -295,6 +295,7 @@ class TopLevelCommand(object): anything. --services Print the service names, one per line. --volumes Print the volume names, one per line. + -f, --filter KEY=VAL Filter containers by a property (can be used multiple times) """ @@ -309,7 +310,15 @@ class TopLevelCommand(object): return if options['--services']: - print('\n'.join(service['name'] for service in compose_config.services)) + filters = build_filters(options.get('--filter')) + if filters: + if not self.project: + self.project = project_from_options('.', config_options) + services = filter_services(filters, self.project.services, self.project) + else: + services = [service['name'] for service in compose_config.services] + + print('\n'.join(services)) return if options['--volumes']: @@ -1312,3 +1321,51 @@ def build_exec_command(options, container_id, command): args += [container_id] args += command return args + + +def has_container_with_state(containers, state): + for container in containers: + states = { + 'running': container.is_running, + 'stopped': not container.is_running, + 'paused': container.is_paused, + } + if state not in states: + raise UserError("Invalid state: %s" % state) + if states[state]: + return True + return False + + +def filter_services(filters, services, project): + def should_include(service): + for f in filters: + if f == 'status': + containers = project.containers([service.name], stopped=True) + for status in filters[f]: + if not has_container_with_state(containers, status): + return False + elif f == 'option': + for option in filters[f]: + if option == 'image' or option == 'build': + if option not in service.options: + return False + else: + raise UserError("Invalid option: %s" % option) + else: + raise UserError("Invalid filter: %s" % f) + return True + + return [s.name for s in services if should_include(s)] + + +def build_filters(args): + filters = {} + for arg in args: + if '=' not in arg: + raise UserError("Arguments to --filter should be in form KEY=VAL") + key, val = arg.split('=', 1) + if key not in filters: + filters[key] = [] + filters[key].append(val) + return filters diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 8468dfbde..a4c19afc5 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -440,6 +440,32 @@ class CLITestCase(DockerClientTestCase): }, } + def test_config_services_filter_option(self): + self.base_dir = 'tests/fixtures/config-services-filter' + image = self.dispatch(['config', '--services', '--filter', 'option=image']) + build = self.dispatch(['config', '--services', '--filter', 'option=build']) + + self.assertIn('with_build', build.stdout) + self.assertNotIn('with_build', image.stdout) + self.assertIn('with_image', image.stdout) + self.assertNotIn('with_image', build.stdout) + + def test_config_services_filter_status(self): + self.base_dir = 'tests/fixtures/config-services-filter' + self.dispatch(['up', '-d']) + self.dispatch(['pause', 'with_image']) + paused = self.dispatch(['config', '--services', '--filter', 'status=paused']) + stopped = self.dispatch(['config', '--services', '--filter', 'status=stopped']) + running = self.dispatch(['config', '--services', '--filter', 'status=running', + '--filter', 'option=build']) + + self.assertNotIn('with_build', stopped.stdout) + self.assertNotIn('with_image', stopped.stdout) + self.assertNotIn('with_build', paused.stdout) + self.assertIn('with_image', paused.stdout) + self.assertIn('with_build', running.stdout) + self.assertNotIn('with_image', running.stdout) + def test_ps(self): self.project.get_service('simple').create_container() result = self.dispatch(['ps']) diff --git a/tests/fixtures/config-services-filter/docker-compose.yml b/tests/fixtures/config-services-filter/docker-compose.yml new file mode 100644 index 000000000..3d8609373 --- /dev/null +++ b/tests/fixtures/config-services-filter/docker-compose.yml @@ -0,0 +1,6 @@ +with_image: + image: busybox:latest + command: top +with_build: + build: ../build-ctx/ + command: top From 1414c1f1fa92db256c83083cb2107740957dff05 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Fri, 17 Nov 2017 17:43:51 -0600 Subject: [PATCH 2/6] Use docker-compose config --services in bash completion Signed-off-by: Svyatoslav Ilinskiy --- contrib/completion/bash/docker-compose | 32 +++++++------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/contrib/completion/bash/docker-compose b/contrib/completion/bash/docker-compose index 1fdb27705..5885e686b 100644 --- a/contrib/completion/bash/docker-compose +++ b/contrib/completion/bash/docker-compose @@ -64,48 +64,32 @@ __docker_compose_services_all() { COMPREPLY=( $(compgen -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) } -# All services that have an entry with the given key in their compose_file section -___docker_compose_services_with_key() { - # flatten sections under "services" to one line, then filter lines containing the key and return section name - __docker_compose_q config \ - | sed -n -e '/^services:/,/^[^ ]/p' \ - | sed -n 's/^ //p' \ - | awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' \ - | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' -} - # All services that are defined by a Dockerfile reference __docker_compose_services_from_build() { - COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key build)" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q config --services --filter "option=build")" -- "$cur") ) } # All services that are defined by an image __docker_compose_services_from_image() { - COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key image)" -- "$cur") ) -} - -# The services for which containers have been created, optionally filtered -# by a boolean expression passed in as argument. -__docker_compose_services_with() { - local containers names - containers="$(__docker_compose_q ps -q)" - names=$(docker 2>/dev/null inspect -f "{{if ${1:-true}}}{{range \$k, \$v := .Config.Labels}}{{if eq \$k \"com.docker.compose.service\"}}{{\$v}}{{end}}{{end}}{{end}}" $containers) - COMPREPLY=( $(compgen -W "$names" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q config --services --filter "option=image")" -- "$cur") ) } # The services for which at least one paused container exists __docker_compose_services_paused() { - __docker_compose_services_with '.State.Paused' + names=$(__docker_compose_q config --services --filter "status=paused") + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } # The services for which at least one running container exists __docker_compose_services_running() { - __docker_compose_services_with '.State.Running' + names=$(__docker_compose_q config --services --filter "status=running") + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } # The services for which at least one stopped container exists __docker_compose_services_stopped() { - __docker_compose_services_with 'not .State.Running' + names=$(__docker_compose_q config --services --filter "status=stopped") + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } From 5924c6366e7351299c3541279508a32fae3bbdfe Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Sat, 18 Nov 2017 17:46:55 -0600 Subject: [PATCH 3/6] Fix minor issue in docker-compose config documentation. Signed-off-by: Svyatoslav Ilinskiy --- compose/cli/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 3e4121420..5cec853db 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -295,7 +295,7 @@ class TopLevelCommand(object): anything. --services Print the service names, one per line. --volumes Print the volume names, one per line. - -f, --filter KEY=VAL Filter containers by a property (can be used multiple times) + -f, --filter KEY=VAL Filter services by a property (can be used multiple times) """ From be0b9026317eab47dc0c9a67a2d77105c7330c2a Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Sat, 2 Dec 2017 18:36:31 -0600 Subject: [PATCH 4/6] Add ability to list and filter services in `ps` Also, rename --filter "option=..." to --filter "key=..." Signed-off-by: Svyatoslav Ilinskiy --- compose/cli/main.py | 90 +++++++++---------- contrib/completion/bash/docker-compose | 10 +-- tests/acceptance/cli_test.py | 55 ++++++------ .../docker-compose.yml | 0 4 files changed, 79 insertions(+), 76 deletions(-) rename tests/fixtures/{config-services-filter => ps-services-filter}/docker-compose.yml (100%) diff --git a/compose/cli/main.py b/compose/cli/main.py index 5cec853db..37168f033 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -287,7 +287,7 @@ class TopLevelCommand(object): """ Validate and view the Compose file. - Usage: config [options] [-f KEY=VAL...] + Usage: config [options] Options: --resolve-image-digests Pin image tags to digests. @@ -295,7 +295,6 @@ class TopLevelCommand(object): anything. --services Print the service names, one per line. --volumes Print the volume names, one per line. - -f, --filter KEY=VAL Filter services by a property (can be used multiple times) """ @@ -310,15 +309,7 @@ class TopLevelCommand(object): return if options['--services']: - filters = build_filters(options.get('--filter')) - if filters: - if not self.project: - self.project = project_from_options('.', config_options) - services = filter_services(filters, self.project.services, self.project) - else: - services = [service['name'] for service in compose_config.services] - - print('\n'.join(services)) + print('\n'.join(service['name'] for service in compose_config.services)) return if options['--volumes']: @@ -608,38 +599,47 @@ class TopLevelCommand(object): """ List containers. - Usage: ps [options] [SERVICE...] + Usage: ps [options] [--filter KEY=VAL...] [SERVICE...] Options: - -q Only display IDs + -q Only display IDs + --services Display services + --filter KEY=VAL Filter services by a property (can be used multiple times) """ - containers = sorted( - self.project.containers(service_names=options['SERVICE'], stopped=True) + - self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only), - key=attrgetter('name')) - - if options['-q']: - for container in containers: - print(container.id) + if options['--services']: + filters = build_filters(options.get('--filter')) + services = self.project.services + if filters: + services = filter_services(filters, services, self.project) + print('\n'.join(service.name for service in services)) else: - headers = [ - 'Name', - 'Command', - 'State', - 'Ports', - ] - rows = [] - for container in containers: - command = container.human_readable_command - if len(command) > 30: - command = '%s ...' % command[:26] - rows.append([ - container.name, - command, - container.human_readable_state, - container.human_readable_ports, - ]) - print(Formatter().table(headers, rows)) + containers = sorted( + self.project.containers(service_names=options['SERVICE'], stopped=True) + + self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only), + key=attrgetter('name')) + + if options['-q']: + for container in containers: + print(container.id) + else: + headers = [ + 'Name', + 'Command', + 'State', + 'Ports', + ] + rows = [] + for container in containers: + command = container.human_readable_command + if len(command) > 30: + command = '%s ...' % command[:26] + rows.append([ + container.name, + command, + container.human_readable_state, + container.human_readable_ports, + ]) + print(Formatter().table(headers, rows)) def pull(self, options): """ @@ -1345,18 +1345,18 @@ def filter_services(filters, services, project): for status in filters[f]: if not has_container_with_state(containers, status): return False - elif f == 'option': - for option in filters[f]: - if option == 'image' or option == 'build': - if option not in service.options: + elif f == 'key': + for key in filters[f]: + if key == 'image' or key == 'build': + if key not in service.options: return False else: - raise UserError("Invalid option: %s" % option) + raise UserError("Invalid option: %s" % key) else: raise UserError("Invalid filter: %s" % f) return True - return [s.name for s in services if should_include(s)] + return filter(should_include, services) def build_filters(args): diff --git a/contrib/completion/bash/docker-compose b/contrib/completion/bash/docker-compose index 5885e686b..248ff9285 100644 --- a/contrib/completion/bash/docker-compose +++ b/contrib/completion/bash/docker-compose @@ -66,29 +66,29 @@ __docker_compose_services_all() { # All services that are defined by a Dockerfile reference __docker_compose_services_from_build() { - COMPREPLY=( $(compgen -W "$(__docker_compose_q config --services --filter "option=build")" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "key=build")" -- "$cur") ) } # All services that are defined by an image __docker_compose_services_from_image() { - COMPREPLY=( $(compgen -W "$(__docker_compose_q config --services --filter "option=image")" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "key=image")" -- "$cur") ) } # The services for which at least one paused container exists __docker_compose_services_paused() { - names=$(__docker_compose_q config --services --filter "status=paused") + names=$(__docker_compose_q ps --services --filter "status=paused") COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } # The services for which at least one running container exists __docker_compose_services_running() { - names=$(__docker_compose_q config --services --filter "status=running") + names=$(__docker_compose_q ps --services --filter "status=running") COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } # The services for which at least one stopped container exists __docker_compose_services_stopped() { - names=$(__docker_compose_q config --services --filter "status=stopped") + names=$(__docker_compose_q ps --services --filter "status=stopped") COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index a4c19afc5..d15d5c5fe 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -440,32 +440,6 @@ class CLITestCase(DockerClientTestCase): }, } - def test_config_services_filter_option(self): - self.base_dir = 'tests/fixtures/config-services-filter' - image = self.dispatch(['config', '--services', '--filter', 'option=image']) - build = self.dispatch(['config', '--services', '--filter', 'option=build']) - - self.assertIn('with_build', build.stdout) - self.assertNotIn('with_build', image.stdout) - self.assertIn('with_image', image.stdout) - self.assertNotIn('with_image', build.stdout) - - def test_config_services_filter_status(self): - self.base_dir = 'tests/fixtures/config-services-filter' - self.dispatch(['up', '-d']) - self.dispatch(['pause', 'with_image']) - paused = self.dispatch(['config', '--services', '--filter', 'status=paused']) - stopped = self.dispatch(['config', '--services', '--filter', 'status=stopped']) - running = self.dispatch(['config', '--services', '--filter', 'status=running', - '--filter', 'option=build']) - - self.assertNotIn('with_build', stopped.stdout) - self.assertNotIn('with_image', stopped.stdout) - self.assertNotIn('with_build', paused.stdout) - self.assertIn('with_image', paused.stdout) - self.assertIn('with_build', running.stdout) - self.assertNotIn('with_image', running.stdout) - def test_ps(self): self.project.get_service('simple').create_container() result = self.dispatch(['ps']) @@ -493,6 +467,35 @@ class CLITestCase(DockerClientTestCase): self.assertNotIn('multiplecomposefiles_another_1', result.stdout) self.assertIn('multiplecomposefiles_yetanother_1', result.stdout) + def test_ps_services_filter_option(self): + self.base_dir = 'tests/fixtures/ps-services-filter' + image = self.dispatch(['ps', '--services', '--filter', 'key=image']) + build = self.dispatch(['ps', '--services', '--filter', 'key=build']) + all_services = self.dispatch(['ps', '--services']) + + self.assertIn('with_build', all_services.stdout) + self.assertIn('with_image', all_services.stdout) + self.assertIn('with_build', build.stdout) + self.assertNotIn('with_build', image.stdout) + self.assertIn('with_image', image.stdout) + self.assertNotIn('with_image', build.stdout) + + def test_ps_services_filter_status(self): + self.base_dir = 'tests/fixtures/ps-services-filter' + self.dispatch(['up', '-d']) + self.dispatch(['pause', 'with_image']) + paused = self.dispatch(['ps', '--services', '--filter', 'status=paused']) + stopped = self.dispatch(['ps', '--services', '--filter', 'status=stopped']) + running = self.dispatch(['ps', '--services', '--filter', 'status=running', + '--filter', 'key=build']) + + self.assertNotIn('with_build', stopped.stdout) + self.assertNotIn('with_image', stopped.stdout) + self.assertNotIn('with_build', paused.stdout) + self.assertIn('with_image', paused.stdout) + self.assertIn('with_build', running.stdout) + self.assertNotIn('with_image', running.stdout) + def test_pull(self): result = self.dispatch(['pull']) assert sorted(result.stderr.split('\n'))[1:] == [ diff --git a/tests/fixtures/config-services-filter/docker-compose.yml b/tests/fixtures/ps-services-filter/docker-compose.yml similarity index 100% rename from tests/fixtures/config-services-filter/docker-compose.yml rename to tests/fixtures/ps-services-filter/docker-compose.yml From 253bed497db517807c6b69c4e68827038f727f6d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Sun, 7 Jan 2018 13:56:05 -0600 Subject: [PATCH 5/6] Allow only one `--filter` argument and simplify code Signed-off-by: Svyatoslav Ilinskiy --- compose/cli/main.py | 122 ++++++++++++++++++----------------- tests/acceptance/cli_test.py | 27 ++++---- 2 files changed, 75 insertions(+), 74 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 37168f033..3b6e25ccb 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -599,47 +599,51 @@ class TopLevelCommand(object): """ List containers. - Usage: ps [options] [--filter KEY=VAL...] [SERVICE...] + Usage: ps [options] [--filter KEY=VAL] [SERVICE...] Options: -q Only display IDs --services Display services - --filter KEY=VAL Filter services by a property (can be used multiple times) + --filter KEY=VAL Filter services by a property """ - if options['--services']: - filters = build_filters(options.get('--filter')) - services = self.project.services - if filters: - services = filter_services(filters, services, self.project) - print('\n'.join(service.name for service in services)) - else: - containers = sorted( - self.project.containers(service_names=options['SERVICE'], stopped=True) + - self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only), - key=attrgetter('name')) + if options['-q'] and options['--services']: + raise UserError('-q and --services cannot be combined') - if options['-q']: - for container in containers: - print(container.id) - else: - headers = [ - 'Name', - 'Command', - 'State', - 'Ports', - ] - rows = [] - for container in containers: - command = container.human_readable_command - if len(command) > 30: - command = '%s ...' % command[:26] - rows.append([ - container.name, - command, - container.human_readable_state, - container.human_readable_ports, - ]) - print(Formatter().table(headers, rows)) + if options['--services']: + filt = build_filter(options.get('--filter')) + services = self.project.services + if filt: + services = filter_services(filt, services, self.project) + print('\n'.join(service.name for service in services)) + return + + containers = sorted( + self.project.containers(service_names=options['SERVICE'], stopped=True) + + self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only), + key=attrgetter('name')) + + if options['-q']: + for container in containers: + print(container.id) + else: + headers = [ + 'Name', + 'Command', + 'State', + 'Ports', + ] + rows = [] + for container in containers: + command = container.human_readable_command + if len(command) > 30: + command = '%s ...' % command[:26] + rows.append([ + container.name, + command, + container.human_readable_state, + container.human_readable_ports, + ]) + print(Formatter().table(headers, rows)) def pull(self, options): """ @@ -1324,34 +1328,34 @@ def build_exec_command(options, container_id, command): def has_container_with_state(containers, state): + states = { + 'running': lambda c: c.is_running, + 'stopped': lambda c: not c.is_running, + 'paused': lambda c: c.is_paused, + 'restarting': lambda c: c.is_restarting, + } for container in containers: - states = { - 'running': container.is_running, - 'stopped': not container.is_running, - 'paused': container.is_paused, - } if state not in states: raise UserError("Invalid state: %s" % state) - if states[state]: + if states[state](container): return True - return False -def filter_services(filters, services, project): +def filter_services(filt, services, project): def should_include(service): - for f in filters: + for f in filt: if f == 'status': + state = filt[f] containers = project.containers([service.name], stopped=True) - for status in filters[f]: - if not has_container_with_state(containers, status): - return False + if not has_container_with_state(containers, state): + return False elif f == 'key': - for key in filters[f]: - if key == 'image' or key == 'build': - if key not in service.options: - return False - else: - raise UserError("Invalid option: %s" % key) + key = filt[f] + if key == 'image' or key == 'build': + if key not in service.options: + return False + else: + raise UserError("Invalid value for key filter: %s" % key) else: raise UserError("Invalid filter: %s" % f) return True @@ -1359,13 +1363,11 @@ def filter_services(filters, services, project): return filter(should_include, services) -def build_filters(args): - filters = {} - for arg in args: +def build_filter(arg): + filt = {} + if arg is not None: if '=' not in arg: raise UserError("Arguments to --filter should be in form KEY=VAL") key, val = arg.split('=', 1) - if key not in filters: - filters[key] = [] - filters[key].append(val) - return filters + filt[key] = val + return filt diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index d15d5c5fe..c6240419f 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -473,12 +473,12 @@ class CLITestCase(DockerClientTestCase): build = self.dispatch(['ps', '--services', '--filter', 'key=build']) all_services = self.dispatch(['ps', '--services']) - self.assertIn('with_build', all_services.stdout) - self.assertIn('with_image', all_services.stdout) - self.assertIn('with_build', build.stdout) - self.assertNotIn('with_build', image.stdout) - self.assertIn('with_image', image.stdout) - self.assertNotIn('with_image', build.stdout) + assert 'with_build' in all_services.stdout + assert 'with_image' in all_services.stdout + assert 'with_build' in build.stdout + assert 'with_build' not in image.stdout + assert 'with_image' in image.stdout + assert 'with_image' not in build.stdout def test_ps_services_filter_status(self): self.base_dir = 'tests/fixtures/ps-services-filter' @@ -486,15 +486,14 @@ class CLITestCase(DockerClientTestCase): self.dispatch(['pause', 'with_image']) paused = self.dispatch(['ps', '--services', '--filter', 'status=paused']) stopped = self.dispatch(['ps', '--services', '--filter', 'status=stopped']) - running = self.dispatch(['ps', '--services', '--filter', 'status=running', - '--filter', 'key=build']) + running = self.dispatch(['ps', '--services', '--filter', 'status=running']) - self.assertNotIn('with_build', stopped.stdout) - self.assertNotIn('with_image', stopped.stdout) - self.assertNotIn('with_build', paused.stdout) - self.assertIn('with_image', paused.stdout) - self.assertIn('with_build', running.stdout) - self.assertNotIn('with_image', running.stdout) + assert 'with_build' not in stopped.stdout + assert 'with_image' not in stopped.stdout + assert 'with_build' not in paused.stdout + assert 'with_image' in paused.stdout + assert 'with_build' in running.stdout + assert 'with_image' in running.stdout def test_pull(self): result = self.dispatch(['pull']) From a1f0c3ed7cb590789aa848a466f85f78f912282d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ilinskiy Date: Tue, 9 Jan 2018 10:57:06 -0600 Subject: [PATCH 6/6] Rename `ps --filter` option from `key` to `source`. Signed-off-by: Svyatoslav Ilinskiy --- compose/cli/main.py | 10 +++++----- contrib/completion/bash/docker-compose | 4 ++-- tests/acceptance/cli_test.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 3b6e25ccb..224e6263a 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -1349,13 +1349,13 @@ def filter_services(filt, services, project): containers = project.containers([service.name], stopped=True) if not has_container_with_state(containers, state): return False - elif f == 'key': - key = filt[f] - if key == 'image' or key == 'build': - if key not in service.options: + elif f == 'source': + source = filt[f] + if source == 'image' or source == 'build': + if source not in service.options: return False else: - raise UserError("Invalid value for key filter: %s" % key) + raise UserError("Invalid value for source filter: %s" % source) else: raise UserError("Invalid filter: %s" % f) return True diff --git a/contrib/completion/bash/docker-compose b/contrib/completion/bash/docker-compose index 248ff9285..bbc08e583 100644 --- a/contrib/completion/bash/docker-compose +++ b/contrib/completion/bash/docker-compose @@ -66,12 +66,12 @@ __docker_compose_services_all() { # All services that are defined by a Dockerfile reference __docker_compose_services_from_build() { - COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "key=build")" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "source=build")" -- "$cur") ) } # All services that are defined by an image __docker_compose_services_from_image() { - COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "key=image")" -- "$cur") ) + COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "source=image")" -- "$cur") ) } # The services for which at least one paused container exists diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index c6240419f..7622380a1 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -469,8 +469,8 @@ class CLITestCase(DockerClientTestCase): def test_ps_services_filter_option(self): self.base_dir = 'tests/fixtures/ps-services-filter' - image = self.dispatch(['ps', '--services', '--filter', 'key=image']) - build = self.dispatch(['ps', '--services', '--filter', 'key=build']) + image = self.dispatch(['ps', '--services', '--filter', 'source=image']) + build = self.dispatch(['ps', '--services', '--filter', 'source=build']) all_services = self.dispatch(['ps', '--services']) assert 'with_build' in all_services.stdout