From caa0cbbc4b174d92a061c6ac4b591dc704988647 Mon Sep 17 00:00:00 2001
From: Nicolas De Loof <nicolas.deloof@gmail.com>
Date: Thu, 23 Nov 2023 11:53:19 +0100
Subject: [PATCH] Introduce ps --orphans so user can include/exclude services
 not declared by project

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
---
 cmd/compose/ps.go                     | 15 +++++++++++----
 docs/reference/compose_ps.md          |  1 +
 docs/reference/docker_compose_ps.yaml | 10 ++++++++++
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/cmd/compose/ps.go b/cmd/compose/ps.go
index eed22aee7..8b3f3d34d 100644
--- a/cmd/compose/ps.go
+++ b/cmd/compose/ps.go
@@ -42,6 +42,7 @@ type psOptions struct {
 	Filter   string
 	Status   []string
 	noTrunc  bool
+	Orphans  bool
 }
 
 func (p *psOptions) parseFilter() error {
@@ -84,6 +85,7 @@ func psCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
 	flags.StringArrayVar(&opts.Status, "status", []string{}, "Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]")
 	flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
 	flags.BoolVar(&opts.Services, "services", false, "Display services")
+	flags.BoolVar(&opts.Orphans, "orphans", true, "Include orphaned services (not declared by project)")
 	flags.BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
 	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
 	return psCmd
@@ -95,12 +97,17 @@ func runPs(ctx context.Context, dockerCli command.Cli, backend api.Service, serv
 		return err
 	}
 
-	if project != nil && len(services) > 0 {
+	if project != nil {
 		names := project.ServiceNames()
-		for _, service := range services {
-			if !utils.StringContains(names, service) {
-				return fmt.Errorf("no such service: %s", service)
+		if len(services) > 0 {
+			for _, service := range services {
+				if !utils.StringContains(names, service) {
+					return fmt.Errorf("no such service: %s", service)
+				}
 			}
+		} else if !opts.Orphans {
+			// until user asks to list orphaned services, we only include those declared in project
+			services = names
 		}
 	}
 
diff --git a/docs/reference/compose_ps.md b/docs/reference/compose_ps.md
index b73cae5d7..81ef25509 100644
--- a/docs/reference/compose_ps.md
+++ b/docs/reference/compose_ps.md
@@ -12,6 +12,7 @@ List containers
 | [`--filter`](#filter) | `string`      |         | Filter services by a property (supported filters: status).                                                                                                                                                                                                                                                                                                                                                                           |
 | [`--format`](#format) | `string`      | `table` | Format output using a custom template:<br>'table':            Print output in table format with column headers (default)<br>'table TEMPLATE':   Print output in table format using the given Go template<br>'json':             Print in JSON format<br>'TEMPLATE':         Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
 | `--no-trunc`          |               |         | Don't truncate output                                                                                                                                                                                                                                                                                                                                                                                                                |
+| `--orphans`           |               |         | Include orphaned services (not declared by project)                                                                                                                                                                                                                                                                                                                                                                                  |
 | `-q`, `--quiet`       |               |         | Only display IDs                                                                                                                                                                                                                                                                                                                                                                                                                     |
 | `--services`          |               |         | Display services                                                                                                                                                                                                                                                                                                                                                                                                                     |
 | [`--status`](#status) | `stringArray` |         | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited]                                                                                                                                                                                                                                                                                                                        |
diff --git a/docs/reference/docker_compose_ps.yaml b/docs/reference/docker_compose_ps.yaml
index 9e6bb072e..78842a999 100644
--- a/docs/reference/docker_compose_ps.yaml
+++ b/docs/reference/docker_compose_ps.yaml
@@ -70,6 +70,16 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
+    - option: orphans
+      value_type: bool
+      default_value: "true"
+      description: Include orphaned services (not declared by project)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
     - option: quiet
       shorthand: q
       value_type: bool