mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Filter containers by status.
A continuation of #7616. Adds `docker ps --filter=status=(restarting|running|paused|stopped)` option. Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jess@docker.com> (github: jfrazelle)
This commit is contained in:
		
							parent
							
								
									8128339bc8
								
							
						
					
					
						commit
						ea09f03682
					
				
					 5 changed files with 78 additions and 8 deletions
				
			
		| 
						 | 
					@ -1485,7 +1485,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
 | 
				
			||||||
	last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
 | 
						last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flFilter := opts.NewListOpts(nil)
 | 
						flFilter := opts.NewListOpts(nil)
 | 
				
			||||||
	cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>")
 | 
						cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>\nstatus=(restarting|running|paused|exited)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := cmd.Parse(args); err != nil {
 | 
						if err := cmd.Parse(args); err != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
 | 
				
			||||||
		size        = job.GetenvBool("size")
 | 
							size        = job.GetenvBool("size")
 | 
				
			||||||
		psFilters   filters.Args
 | 
							psFilters   filters.Args
 | 
				
			||||||
		filt_exited []int
 | 
							filt_exited []int
 | 
				
			||||||
 | 
							filt_status []string
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	outs := engine.NewTable("Created", 0)
 | 
						outs := engine.NewTable("Created", 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,8 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filt_status, _ = psFilters["status"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	names := map[string][]string{}
 | 
						names := map[string][]string{}
 | 
				
			||||||
	daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
 | 
						daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
 | 
				
			||||||
		names[e.ID()] = append(names[e.ID()], p)
 | 
							names[e.ID()] = append(names[e.ID()], p)
 | 
				
			||||||
| 
						 | 
					@ -99,6 +102,11 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
 | 
				
			||||||
				return nil
 | 
									return nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							for _, status := range filt_status {
 | 
				
			||||||
 | 
								if container.State.StateString() != strings.ToLower(status) {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		displayed++
 | 
							displayed++
 | 
				
			||||||
		out := &engine.Env{}
 | 
							out := &engine.Env{}
 | 
				
			||||||
		out.Set("Id", container.ID)
 | 
							out.Set("Id", container.ID)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,20 @@ func (s *State) String() string {
 | 
				
			||||||
	return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
 | 
						return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StateString returns a single string to describe state
 | 
				
			||||||
 | 
					func (s *State) StateString() string {
 | 
				
			||||||
 | 
						if s.Running {
 | 
				
			||||||
 | 
							if s.Paused {
 | 
				
			||||||
 | 
								return "paused"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if s.Restarting {
 | 
				
			||||||
 | 
								return "restarting"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return "running"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "exited"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func wait(waitChan <-chan struct{}, timeout time.Duration) error {
 | 
					func wait(waitChan <-chan struct{}, timeout time.Duration) error {
 | 
				
			||||||
	if timeout < 0 {
 | 
						if timeout < 0 {
 | 
				
			||||||
		<-waitChan
 | 
							<-waitChan
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,14 +241,15 @@ as the root. Wildcards are allowed but the search is not recursive.
 | 
				
			||||||
    temp?
 | 
					    temp?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The first line above `*/temp*`, would ignore all files with names starting with
 | 
					The first line above `*/temp*`, would ignore all files with names starting with
 | 
				
			||||||
`temp` from any subdirectory below the root directory, for example file named 
 | 
					`temp` from any subdirectory below the root directory. For example, a file named
 | 
				
			||||||
`/somedir/temporary.txt` will be ignored. The second line `*/*/temp*`, will  
 | 
					`/somedir/temporary.txt` would be ignored. The second line `*/*/temp*`, will
 | 
				
			||||||
ignore files starting with name `temp` from any subdirectory that is two levels
 | 
					ignore files starting with name `temp` from any subdirectory that is two levels
 | 
				
			||||||
below the root directory, for example a file `/somedir/subdir/temporary.txt` is 
 | 
					below the root directory. For example, the file `/somedir/subdir/temporary.txt`
 | 
				
			||||||
ignored in this case. The last line in the above example `temp?`, will ignore 
 | 
					would get ignored in this case. The last line in the above example `temp?`
 | 
				
			||||||
the files that match the pattern from the root directory, for example files 
 | 
					will ignore the files that match the pattern from the root directory.
 | 
				
			||||||
`tempa`, `tempb` are ignored from the root directory. Currently  there is no
 | 
					For example, the files `tempa`, `tempb` are ignored from the root directory.
 | 
				
			||||||
support for regular expressions, formats like `[^temp*]` are ignored.
 | 
					Currently there is no support for regular expressions. Formats
 | 
				
			||||||
 | 
					like `[^temp*]` are ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See also:
 | 
					See also:
 | 
				
			||||||
| 
						 | 
					@ -943,6 +944,7 @@ further details.
 | 
				
			||||||
      --before=""           Show only container created before Id or Name, include non-running ones.
 | 
					      --before=""           Show only container created before Id or Name, include non-running ones.
 | 
				
			||||||
      -f, --filter=[]       Provide filter values. Valid filters:
 | 
					      -f, --filter=[]       Provide filter values. Valid filters:
 | 
				
			||||||
                              exited=<int> - containers with exit code of <int>
 | 
					                              exited=<int> - containers with exit code of <int>
 | 
				
			||||||
 | 
					                              status=(restarting|running|paused|exited)
 | 
				
			||||||
      -l, --latest=false    Show only the latest created container, include non-running ones.
 | 
					      -l, --latest=false    Show only the latest created container, include non-running ones.
 | 
				
			||||||
      -n=-1                 Show n last created containers, include non-running ones.
 | 
					      -n=-1                 Show n last created containers, include non-running ones.
 | 
				
			||||||
      --no-trunc=false      Don't truncate output
 | 
					      --no-trunc=false      Don't truncate output
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -235,4 +235,50 @@ func TestPsListContainersSize(t *testing.T) {
 | 
				
			||||||
	if foundSize != expectedSize {
 | 
						if foundSize != expectedSize {
 | 
				
			||||||
		t.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
 | 
							t.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deleteAllContainers()
 | 
				
			||||||
 | 
						logDone("ps - test ps size")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPsListContainersFilterStatus(t *testing.T) {
 | 
				
			||||||
 | 
						// FIXME: this should test paused, but it makes things hang and its wonky
 | 
				
			||||||
 | 
						// this is because paused containers can't be controlled by signals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// start exited container
 | 
				
			||||||
 | 
						runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
 | 
				
			||||||
 | 
						out, _, err := runCommandWithOutput(runCmd)
 | 
				
			||||||
 | 
						errorOut(err, t, out)
 | 
				
			||||||
 | 
						firstID := stripTrailingCharacters(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// make sure the exited cintainer is not running
 | 
				
			||||||
 | 
						runCmd = exec.Command(dockerBinary, "wait", firstID)
 | 
				
			||||||
 | 
						out, _, err = runCommandWithOutput(runCmd)
 | 
				
			||||||
 | 
						errorOut(err, t, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// start running container
 | 
				
			||||||
 | 
						runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 360")
 | 
				
			||||||
 | 
						out, _, err = runCommandWithOutput(runCmd)
 | 
				
			||||||
 | 
						errorOut(err, t, out)
 | 
				
			||||||
 | 
						secondID := stripTrailingCharacters(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// filter containers by exited
 | 
				
			||||||
 | 
						runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=exited")
 | 
				
			||||||
 | 
						out, _, err = runCommandWithOutput(runCmd)
 | 
				
			||||||
 | 
						errorOut(err, t, out)
 | 
				
			||||||
 | 
						containerOut := strings.TrimSpace(out)
 | 
				
			||||||
 | 
						if containerOut != firstID[:12] {
 | 
				
			||||||
 | 
							t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=running")
 | 
				
			||||||
 | 
						out, _, err = runCommandWithOutput(runCmd)
 | 
				
			||||||
 | 
						errorOut(err, t, out)
 | 
				
			||||||
 | 
						containerOut = strings.TrimSpace(out)
 | 
				
			||||||
 | 
						if containerOut != secondID[:12] {
 | 
				
			||||||
 | 
							t.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deleteAllContainers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logDone("ps - test ps filter status")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue