mirror of https://github.com/docker/compose.git
Add ability to list and filter services in `ps`
Also, rename --filter "option=..." to --filter "key=..." Signed-off-by: Svyatoslav Ilinskiy <ilinskiy.sv@gmail.com>
This commit is contained in:
parent
5924c6366e
commit
be0b902631
|
@ -287,7 +287,7 @@ class TopLevelCommand(object):
|
||||||
"""
|
"""
|
||||||
Validate and view the Compose file.
|
Validate and view the Compose file.
|
||||||
|
|
||||||
Usage: config [options] [-f KEY=VAL...]
|
Usage: config [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--resolve-image-digests Pin image tags to digests.
|
--resolve-image-digests Pin image tags to digests.
|
||||||
|
@ -295,7 +295,6 @@ class TopLevelCommand(object):
|
||||||
anything.
|
anything.
|
||||||
--services Print the service names, one per line.
|
--services Print the service names, one per line.
|
||||||
--volumes Print the volume 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
|
return
|
||||||
|
|
||||||
if options['--services']:
|
if options['--services']:
|
||||||
filters = build_filters(options.get('--filter'))
|
print('\n'.join(service['name'] for service in compose_config.services))
|
||||||
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
|
return
|
||||||
|
|
||||||
if options['--volumes']:
|
if options['--volumes']:
|
||||||
|
@ -608,11 +599,20 @@ class TopLevelCommand(object):
|
||||||
"""
|
"""
|
||||||
List containers.
|
List containers.
|
||||||
|
|
||||||
Usage: ps [options] [SERVICE...]
|
Usage: ps [options] [--filter KEY=VAL...] [SERVICE...]
|
||||||
|
|
||||||
Options:
|
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)
|
||||||
"""
|
"""
|
||||||
|
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(
|
containers = sorted(
|
||||||
self.project.containers(service_names=options['SERVICE'], stopped=True) +
|
self.project.containers(service_names=options['SERVICE'], stopped=True) +
|
||||||
self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only),
|
self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only),
|
||||||
|
@ -1345,18 +1345,18 @@ def filter_services(filters, services, project):
|
||||||
for status in filters[f]:
|
for status in filters[f]:
|
||||||
if not has_container_with_state(containers, status):
|
if not has_container_with_state(containers, status):
|
||||||
return False
|
return False
|
||||||
elif f == 'option':
|
elif f == 'key':
|
||||||
for option in filters[f]:
|
for key in filters[f]:
|
||||||
if option == 'image' or option == 'build':
|
if key == 'image' or key == 'build':
|
||||||
if option not in service.options:
|
if key not in service.options:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
raise UserError("Invalid option: %s" % option)
|
raise UserError("Invalid option: %s" % key)
|
||||||
else:
|
else:
|
||||||
raise UserError("Invalid filter: %s" % f)
|
raise UserError("Invalid filter: %s" % f)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return [s.name for s in services if should_include(s)]
|
return filter(should_include, services)
|
||||||
|
|
||||||
|
|
||||||
def build_filters(args):
|
def build_filters(args):
|
||||||
|
|
|
@ -66,29 +66,29 @@ __docker_compose_services_all() {
|
||||||
|
|
||||||
# All services that are defined by a Dockerfile reference
|
# All services that are defined by a Dockerfile reference
|
||||||
__docker_compose_services_from_build() {
|
__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
|
# All services that are defined by an image
|
||||||
__docker_compose_services_from_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
|
# The services for which at least one paused container exists
|
||||||
__docker_compose_services_paused() {
|
__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") )
|
COMPREPLY=( $(compgen -W "$names" -- "$cur") )
|
||||||
}
|
}
|
||||||
|
|
||||||
# The services for which at least one running container exists
|
# The services for which at least one running container exists
|
||||||
__docker_compose_services_running() {
|
__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") )
|
COMPREPLY=( $(compgen -W "$names" -- "$cur") )
|
||||||
}
|
}
|
||||||
|
|
||||||
# The services for which at least one stopped container exists
|
# The services for which at least one stopped container exists
|
||||||
__docker_compose_services_stopped() {
|
__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") )
|
COMPREPLY=( $(compgen -W "$names" -- "$cur") )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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):
|
def test_ps(self):
|
||||||
self.project.get_service('simple').create_container()
|
self.project.get_service('simple').create_container()
|
||||||
result = self.dispatch(['ps'])
|
result = self.dispatch(['ps'])
|
||||||
|
@ -493,6 +467,35 @@ class CLITestCase(DockerClientTestCase):
|
||||||
self.assertNotIn('multiplecomposefiles_another_1', result.stdout)
|
self.assertNotIn('multiplecomposefiles_another_1', result.stdout)
|
||||||
self.assertIn('multiplecomposefiles_yetanother_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):
|
def test_pull(self):
|
||||||
result = self.dispatch(['pull'])
|
result = self.dispatch(['pull'])
|
||||||
assert sorted(result.stderr.split('\n'))[1:] == [
|
assert sorted(result.stderr.split('\n'))[1:] == [
|
||||||
|
|
Loading…
Reference in New Issue