d0370076 |
package daemon |
74fdadc8 |
import (
"errors"
"fmt" |
84146719 |
"strconv" |
74fdadc8 |
"strings"
|
065648a8 |
"github.com/docker/docker/api/types" |
74fdadc8 |
"github.com/docker/docker/pkg/graphdb" |
9c2374d1 |
"github.com/docker/docker/pkg/nat" |
84146719 |
"github.com/docker/docker/pkg/parsers/filters" |
74fdadc8 |
)
|
d0370076 |
// List returns an array of all containers registered in the daemon.
func (daemon *Daemon) List() []*Container {
return daemon.containers.List()
}
|
1bfa80bd |
type ContainersConfig struct {
All bool
Since string
Before string
Limit int
Size bool
Filters string
} |
065648a8 |
|
1bfa80bd |
func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) { |
74fdadc8 |
var (
foundBefore bool
displayed int |
1bfa80bd |
all = config.All
n = config.Limit |
84146719 |
psFilters filters.Args |
ae907e7a |
filtExited []int |
74fdadc8 |
) |
1bfa80bd |
containers := []*types.Container{} |
74fdadc8 |
|
1bfa80bd |
psFilters, err := filters.FromParam(config.Filters) |
84146719 |
if err != nil { |
1bfa80bd |
return nil, err |
84146719 |
}
if i, ok := psFilters["exited"]; ok {
for _, value := range i {
code, err := strconv.Atoi(value)
if err != nil { |
1bfa80bd |
return nil, err |
84146719 |
} |
ae907e7a |
filtExited = append(filtExited, code) |
84146719 |
}
}
|
2639e073 |
if i, ok := psFilters["status"]; ok {
for _, value := range i { |
7bf26d44 |
if !isValidStateString(value) {
return nil, errors.New("Unrecognised filter value for status")
} |
dc697b1c |
if value == "exited" || value == "created" { |
2639e073 |
all = true
}
}
} |
74fdadc8 |
names := map[string][]string{} |
d0370076 |
daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error { |
74fdadc8 |
names[e.ID()] = append(names[e.ID()], p)
return nil |
10c3d9f8 |
}, 1) |
74fdadc8 |
|
d0370076 |
var beforeCont, sinceCont *Container |
1bfa80bd |
if config.Before != "" {
beforeCont, err = daemon.Get(config.Before) |
d25a6537 |
if err != nil { |
1bfa80bd |
return nil, err |
74fdadc8 |
}
}
|
1bfa80bd |
if config.Since != "" {
sinceCont, err = daemon.Get(config.Since) |
d25a6537 |
if err != nil { |
1bfa80bd |
return nil, err |
74fdadc8 |
}
}
errLast := errors.New("last container") |
d0370076 |
writeCont := func(container *Container) error { |
74fdadc8 |
container.Lock()
defer container.Unlock() |
1bfa80bd |
if !container.Running && !all && n <= 0 && config.Since == "" && config.Before == "" { |
74fdadc8 |
return nil
} |
16346253 |
if !psFilters.Match("name", container.Name) {
return nil
}
if !psFilters.Match("id", container.ID) {
return nil
}
|
abb5e9a0 |
if !psFilters.MatchKVList("label", container.Config.Labels) {
return nil
}
|
1bfa80bd |
if config.Before != "" && !foundBefore { |
74fdadc8 |
if container.ID == beforeCont.ID {
foundBefore = true
}
return nil
}
if n > 0 && displayed == n {
return errLast
} |
1bfa80bd |
if config.Since != "" { |
74fdadc8 |
if container.ID == sinceCont.ID {
return errLast
}
} |
ae907e7a |
if len(filtExited) > 0 {
shouldSkip := true
for _, code := range filtExited { |
81f84023 |
if code == container.ExitCode && !container.Running { |
ae907e7a |
shouldSkip = false |
84146719 |
break
}
} |
ae907e7a |
if shouldSkip { |
84146719 |
return nil
}
} |
16346253 |
if !psFilters.Match("status", container.State.StateString()) {
return nil |
ea09f036 |
} |
74fdadc8 |
displayed++ |
1bfa80bd |
newC := &types.Container{ |
065648a8 |
ID: container.ID,
Names: names[container.ID],
} |
645c020f |
newC.Image = container.Config.Image |
74fdadc8 |
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, " ")
|
065648a8 |
newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString) |
74fdadc8 |
} else { |
065648a8 |
newC.Command = fmt.Sprintf("%s", container.Path)
} |
b261ce5f |
newC.Created = int(container.Created.Unix()) |
065648a8 |
newC.Status = container.State.String() |
8a9ed097 |
newC.HostConfig.NetworkMode = string(container.HostConfig().NetworkMode) |
065648a8 |
newC.Ports = []types.Port{}
for port, bindings := range container.NetworkSettings.Ports { |
12b6083c |
p, err := nat.ParsePort(port.Port())
if err != nil {
return err
} |
065648a8 |
if len(bindings) == 0 {
newC.Ports = append(newC.Ports, types.Port{
PrivatePort: p,
Type: port.Proto(),
})
continue
}
for _, binding := range bindings { |
12b6083c |
h, err := nat.ParsePort(binding.HostPort)
if err != nil {
return err
} |
065648a8 |
newC.Ports = append(newC.Ports, types.Port{
PrivatePort: p,
PublicPort: h,
Type: port.Proto(), |
15d01d6e |
IP: binding.HostIP, |
065648a8 |
})
} |
74fdadc8 |
} |
065648a8 |
|
1bfa80bd |
if config.Size { |
74fdadc8 |
sizeRw, sizeRootFs := container.GetSize() |
065648a8 |
newC.SizeRw = int(sizeRw)
newC.SizeRootFs = int(sizeRootFs) |
74fdadc8 |
} |
065648a8 |
newC.Labels = container.Config.Labels
containers = append(containers, newC) |
74fdadc8 |
return nil
}
|
d0370076 |
for _, container := range daemon.List() { |
74fdadc8 |
if err := writeCont(container); err != nil {
if err != errLast { |
1bfa80bd |
return nil, err |
74fdadc8 |
}
break
}
} |
1bfa80bd |
return containers, nil |
74fdadc8 |
} |