daemon/list.go
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
 }