2014-07-31 17:26:25 -04:00
|
|
|
package daemon
|
2014-07-29 22:04:39 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2014-06-02 15:08:39 -04:00
|
|
|
"strconv"
|
2014-07-29 22:04:39 -04:00
|
|
|
"strings"
|
|
|
|
|
2015-02-05 17:55:08 -05:00
|
|
|
"github.com/docker/docker/graph"
|
2014-07-29 22:04:39 -04:00
|
|
|
"github.com/docker/docker/pkg/graphdb"
|
2014-07-31 17:26:25 -04:00
|
|
|
|
|
|
|
"github.com/docker/docker/engine"
|
2015-02-05 17:55:08 -05:00
|
|
|
"github.com/docker/docker/pkg/parsers"
|
2014-06-02 15:08:39 -04:00
|
|
|
"github.com/docker/docker/pkg/parsers/filters"
|
2014-07-29 22:04:39 -04:00
|
|
|
)
|
|
|
|
|
2014-07-31 17:26:25 -04:00
|
|
|
// List returns an array of all containers registered in the daemon.
|
|
|
|
func (daemon *Daemon) List() []*Container {
|
|
|
|
return daemon.containers.List()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
2014-07-29 22:04:39 -04:00
|
|
|
var (
|
|
|
|
foundBefore bool
|
|
|
|
displayed int
|
|
|
|
all = job.GetenvBool("all")
|
|
|
|
since = job.Getenv("since")
|
|
|
|
before = job.Getenv("before")
|
|
|
|
n = job.GetenvInt("limit")
|
|
|
|
size = job.GetenvBool("size")
|
2014-06-02 15:08:39 -04:00
|
|
|
psFilters filters.Args
|
|
|
|
filt_exited []int
|
2014-07-29 22:04:39 -04:00
|
|
|
)
|
|
|
|
outs := engine.NewTable("Created", 0)
|
|
|
|
|
2014-06-02 15:08:39 -04:00
|
|
|
psFilters, err := filters.FromParam(job.Getenv("filters"))
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
if i, ok := psFilters["exited"]; ok {
|
|
|
|
for _, value := range i {
|
|
|
|
code, err := strconv.Atoi(value)
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
filt_exited = append(filt_exited, code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-08 18:14:04 -05:00
|
|
|
if i, ok := psFilters["status"]; ok {
|
|
|
|
for _, value := range i {
|
|
|
|
if value == "exited" {
|
|
|
|
all = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-29 22:04:39 -04:00
|
|
|
names := map[string][]string{}
|
2014-07-31 17:26:25 -04:00
|
|
|
daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
|
2014-07-29 22:04:39 -04:00
|
|
|
names[e.ID()] = append(names[e.ID()], p)
|
|
|
|
return nil
|
2015-01-14 18:26:42 -05:00
|
|
|
}, 1)
|
2014-07-29 22:04:39 -04:00
|
|
|
|
2014-07-31 17:26:25 -04:00
|
|
|
var beforeCont, sinceCont *Container
|
2014-07-29 22:04:39 -04:00
|
|
|
if before != "" {
|
2014-12-16 18:06:35 -05:00
|
|
|
beforeCont, err = daemon.Get(before)
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
2014-07-29 22:04:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if since != "" {
|
2014-12-16 18:06:35 -05:00
|
|
|
sinceCont, err = daemon.Get(since)
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
2014-07-29 22:04:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
errLast := errors.New("last container")
|
2014-07-31 17:26:25 -04:00
|
|
|
writeCont := func(container *Container) error {
|
2014-07-29 22:04:39 -04:00
|
|
|
container.Lock()
|
|
|
|
defer container.Unlock()
|
2014-08-31 11:20:35 -04:00
|
|
|
if !container.Running && !all && n <= 0 && since == "" && before == "" {
|
2014-07-29 22:04:39 -04:00
|
|
|
return nil
|
|
|
|
}
|
2014-10-13 02:12:44 -04:00
|
|
|
if !psFilters.Match("name", container.Name) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if !psFilters.Match("id", container.ID) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-07-29 22:04:39 -04:00
|
|
|
if before != "" && !foundBefore {
|
|
|
|
if container.ID == beforeCont.ID {
|
|
|
|
foundBefore = true
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if n > 0 && displayed == n {
|
|
|
|
return errLast
|
|
|
|
}
|
|
|
|
if since != "" {
|
|
|
|
if container.ID == sinceCont.ID {
|
|
|
|
return errLast
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 17:51:47 -05:00
|
|
|
if len(filt_exited) > 0 {
|
2014-06-02 15:08:39 -04:00
|
|
|
should_skip := true
|
|
|
|
for _, code := range filt_exited {
|
2015-01-08 17:51:47 -05:00
|
|
|
if code == container.ExitCode && !container.Running {
|
2014-06-02 15:08:39 -04:00
|
|
|
should_skip = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if should_skip {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2014-10-13 02:12:44 -04:00
|
|
|
|
|
|
|
if !psFilters.Match("status", container.State.StateString()) {
|
|
|
|
return nil
|
2014-09-26 19:25:50 -04:00
|
|
|
}
|
2014-07-29 22:04:39 -04:00
|
|
|
displayed++
|
|
|
|
out := &engine.Env{}
|
2014-12-11 07:56:21 -05:00
|
|
|
out.SetJson("Id", container.ID)
|
2014-07-29 22:04:39 -04:00
|
|
|
out.SetList("Names", names[container.ID])
|
2015-02-05 17:55:08 -05:00
|
|
|
img := container.Config.Image
|
|
|
|
_, tag := parsers.ParseRepositoryTag(container.Config.Image)
|
|
|
|
if tag == "" {
|
|
|
|
img = img + ":" + graph.DEFAULTTAG
|
|
|
|
}
|
|
|
|
out.SetJson("Image", img)
|
2014-07-29 22:04:39 -04:00
|
|
|
if len(container.Args) > 0 {
|
|
|
|
args := []string{}
|
|
|
|
for _, arg := range container.Args {
|
|
|
|
if strings.Contains(arg, " ") {
|
|
|
|
args = append(args, fmt.Sprintf("'%s'", arg))
|
|
|
|
} else {
|
|
|
|
args = append(args, arg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
argsAsString := strings.Join(args, " ")
|
|
|
|
|
|
|
|
out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString))
|
|
|
|
} else {
|
|
|
|
out.Set("Command", fmt.Sprintf("\"%s\"", container.Path))
|
|
|
|
}
|
|
|
|
out.SetInt64("Created", container.Created.Unix())
|
|
|
|
out.Set("Status", container.State.String())
|
|
|
|
str, err := container.NetworkSettings.PortMappingAPI().ToListString()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
out.Set("Ports", str)
|
|
|
|
if size {
|
|
|
|
sizeRw, sizeRootFs := container.GetSize()
|
|
|
|
out.SetInt64("SizeRw", sizeRw)
|
|
|
|
out.SetInt64("SizeRootFs", sizeRootFs)
|
|
|
|
}
|
|
|
|
outs.Add(out)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-07-31 17:26:25 -04:00
|
|
|
for _, container := range daemon.List() {
|
2014-07-29 22:04:39 -04:00
|
|
|
if err := writeCont(container); err != nil {
|
|
|
|
if err != errLast {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
outs.ReverseSort()
|
|
|
|
if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
return engine.StatusOK
|
|
|
|
}
|