Added top to docker-compose to display running processes.

This commit allows `docker-compose` to access `top` for containers
much like running `docker top` directly on a given container.

This commit includes:

* `docker-compose` CLI changes to expose `top`
* Completions for `bash` and `zsh`
* Required testing for the new `top` command

Signed-off-by: Peter Urda <peter.urda@gmail.com>
This commit is contained in:
Peter Urda 2016-10-14 00:44:52 -07:00
parent 1f39b33357
commit a67500ee57
No known key found for this signature in database
GPG Key ID: 240BD54D194E3161
5 changed files with 72 additions and 0 deletions

View File

@ -215,6 +215,7 @@ class TopLevelCommand(object):
scale Set number of containers for a service scale Set number of containers for a service
start Start services start Start services
stop Stop services stop Stop services
top Display the running processes
unpause Unpause services unpause Unpause services
up Create and start containers up Create and start containers
version Show the Docker-Compose version information version Show the Docker-Compose version information
@ -800,6 +801,33 @@ class TopLevelCommand(object):
containers = self.project.restart(service_names=options['SERVICE'], timeout=timeout) containers = self.project.restart(service_names=options['SERVICE'], timeout=timeout)
exit_if(not containers, 'No containers to restart', 1) exit_if(not containers, 'No containers to restart', 1)
def top(self, options):
"""
Display the running processes
Usage: top [SERVICE...]
"""
containers = sorted(
self.project.containers(service_names=options['SERVICE'], stopped=False) +
self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only),
key=attrgetter('name')
)
for idx, container in enumerate(containers):
if idx > 0:
print()
top_data = self.project.client.top(container.name)
headers = top_data.get("Titles")
rows = []
for process in top_data.get("Processes", []):
rows.append(process)
print(container.name)
print(Formatter().table(headers, rows))
def unpause(self, options): def unpause(self, options):
""" """
Unpause services. Unpause services.

View File

@ -434,6 +434,18 @@ _docker_compose_stop() {
} }
_docker_compose_top() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
;;
*)
__docker_compose_services_running
;;
esac
}
_docker_compose_unpause() { _docker_compose_unpause() {
case "$cur" in case "$cur" in
-*) -*)
@ -499,6 +511,7 @@ _docker_compose() {
scale scale
start start
stop stop
top
unpause unpause
up up
version version

View File

@ -341,6 +341,11 @@ __docker-compose_subcommand() {
$opts_timeout \ $opts_timeout \
'*:running services:__docker-compose_runningservices' && ret=0 '*:running services:__docker-compose_runningservices' && ret=0
;; ;;
(top)
_arguments \
$opts_help \
'*:running services:__docker-compose_runningservices' && ret=0
;;
(unpause) (unpause)
_arguments \ _arguments \
$opts_help \ $opts_help \

View File

@ -1907,3 +1907,23 @@ class CLITestCase(DockerClientTestCase):
"BAZ=2", "BAZ=2",
]) ])
self.assertTrue(expected_env <= set(web.get('Config.Env'))) self.assertTrue(expected_env <= set(web.get('Config.Env')))
def test_top_services_not_running(self):
self.base_dir = 'tests/fixtures/top'
result = self.dispatch(['top'])
assert len(result.stdout) == 0
def test_top_services_running(self):
self.base_dir = 'tests/fixtures/top'
self.dispatch(['up', '-d'])
result = self.dispatch(['top'])
self.assertIn('top_service_a', result.stdout)
self.assertIn('top_service_b', result.stdout)
self.assertNotIn('top_not_a_service', result.stdout)
def test_top_processes_running(self):
self.base_dir = 'tests/fixtures/top'
self.dispatch(['up', '-d'])
result = self.dispatch(['top'])
assert result.stdout.count("top") == 4

6
tests/fixtures/top/docker-compose.yml vendored Normal file
View File

@ -0,0 +1,6 @@
service_a:
image: busybox:latest
command: top
service_b:
image: busybox:latest
command: top