Explorar o código

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 <[email protected]>
Peter Urda %!s(int64=9) %!d(string=hai) anos
pai
achega
a67500ee57

+ 28 - 0
compose/cli/main.py

@@ -215,6 +215,7 @@ class TopLevelCommand(object):
       scale              Set number of containers for a service
       start              Start services
       stop               Stop services
+      top                Display the running processes
       unpause            Unpause services
       up                 Create and start containers
       version            Show the Docker-Compose version information
@@ -800,6 +801,33 @@ class TopLevelCommand(object):
         containers = self.project.restart(service_names=options['SERVICE'], timeout=timeout)
         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):
         """
         Unpause services.

+ 13 - 0
contrib/completion/bash/docker-compose

@@ -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() {
 	case "$cur" in
 		-*)
@@ -499,6 +511,7 @@ _docker_compose() {
 		scale
 		start
 		stop
+		top
 		unpause
 		up
 		version

+ 5 - 0
contrib/completion/zsh/_docker-compose

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

+ 20 - 0
tests/acceptance/cli_test.py

@@ -1907,3 +1907,23 @@ class CLITestCase(DockerClientTestCase):
             "BAZ=2",
         ])
         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 - 0
tests/fixtures/top/docker-compose.yml

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