github.com/torfuzx/docker@v1.8.1/daemon/list.go (about)

     1  package daemon
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/pkg/graphdb"
    11  	"github.com/docker/docker/pkg/nat"
    12  	"github.com/docker/docker/pkg/parsers/filters"
    13  )
    14  
    15  // List returns an array of all containers registered in the daemon.
    16  func (daemon *Daemon) List() []*Container {
    17  	return daemon.containers.List()
    18  }
    19  
    20  type ContainersConfig struct {
    21  	All     bool
    22  	Since   string
    23  	Before  string
    24  	Limit   int
    25  	Size    bool
    26  	Filters string
    27  }
    28  
    29  func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) {
    30  	var (
    31  		foundBefore bool
    32  		displayed   int
    33  		all         = config.All
    34  		n           = config.Limit
    35  		psFilters   filters.Args
    36  		filtExited  []int
    37  	)
    38  	containers := []*types.Container{}
    39  
    40  	psFilters, err := filters.FromParam(config.Filters)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	if i, ok := psFilters["exited"]; ok {
    45  		for _, value := range i {
    46  			code, err := strconv.Atoi(value)
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  			filtExited = append(filtExited, code)
    51  		}
    52  	}
    53  
    54  	if i, ok := psFilters["status"]; ok {
    55  		for _, value := range i {
    56  			if !isValidStateString(value) {
    57  				return nil, errors.New("Unrecognised filter value for status")
    58  			}
    59  			if value == "exited" || value == "created" {
    60  				all = true
    61  			}
    62  		}
    63  	}
    64  	names := map[string][]string{}
    65  	daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
    66  		names[e.ID()] = append(names[e.ID()], p)
    67  		return nil
    68  	}, 1)
    69  
    70  	var beforeCont, sinceCont *Container
    71  	if config.Before != "" {
    72  		beforeCont, err = daemon.Get(config.Before)
    73  		if err != nil {
    74  			return nil, err
    75  		}
    76  	}
    77  
    78  	if config.Since != "" {
    79  		sinceCont, err = daemon.Get(config.Since)
    80  		if err != nil {
    81  			return nil, err
    82  		}
    83  	}
    84  
    85  	errLast := errors.New("last container")
    86  	writeCont := func(container *Container) error {
    87  		container.Lock()
    88  		defer container.Unlock()
    89  		if !container.Running && !all && n <= 0 && config.Since == "" && config.Before == "" {
    90  			return nil
    91  		}
    92  		if !psFilters.Match("name", container.Name) {
    93  			return nil
    94  		}
    95  
    96  		if !psFilters.Match("id", container.ID) {
    97  			return nil
    98  		}
    99  
   100  		if !psFilters.MatchKVList("label", container.Config.Labels) {
   101  			return nil
   102  		}
   103  
   104  		if config.Before != "" && !foundBefore {
   105  			if container.ID == beforeCont.ID {
   106  				foundBefore = true
   107  			}
   108  			return nil
   109  		}
   110  		if n > 0 && displayed == n {
   111  			return errLast
   112  		}
   113  		if config.Since != "" {
   114  			if container.ID == sinceCont.ID {
   115  				return errLast
   116  			}
   117  		}
   118  		if len(filtExited) > 0 {
   119  			shouldSkip := true
   120  			for _, code := range filtExited {
   121  				if code == container.ExitCode && !container.Running {
   122  					shouldSkip = false
   123  					break
   124  				}
   125  			}
   126  			if shouldSkip {
   127  				return nil
   128  			}
   129  		}
   130  
   131  		if !psFilters.Match("status", container.State.StateString()) {
   132  			return nil
   133  		}
   134  		displayed++
   135  		newC := &types.Container{
   136  			ID:    container.ID,
   137  			Names: names[container.ID],
   138  		}
   139  		newC.Image = container.Config.Image
   140  		if len(container.Args) > 0 {
   141  			args := []string{}
   142  			for _, arg := range container.Args {
   143  				if strings.Contains(arg, " ") {
   144  					args = append(args, fmt.Sprintf("'%s'", arg))
   145  				} else {
   146  					args = append(args, arg)
   147  				}
   148  			}
   149  			argsAsString := strings.Join(args, " ")
   150  
   151  			newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString)
   152  		} else {
   153  			newC.Command = fmt.Sprintf("%s", container.Path)
   154  		}
   155  		newC.Created = int(container.Created.Unix())
   156  		newC.Status = container.State.String()
   157  		newC.HostConfig.NetworkMode = string(container.HostConfig().NetworkMode)
   158  
   159  		newC.Ports = []types.Port{}
   160  		for port, bindings := range container.NetworkSettings.Ports {
   161  			p, err := nat.ParsePort(port.Port())
   162  			if err != nil {
   163  				return err
   164  			}
   165  			if len(bindings) == 0 {
   166  				newC.Ports = append(newC.Ports, types.Port{
   167  					PrivatePort: p,
   168  					Type:        port.Proto(),
   169  				})
   170  				continue
   171  			}
   172  			for _, binding := range bindings {
   173  				h, err := nat.ParsePort(binding.HostPort)
   174  				if err != nil {
   175  					return err
   176  				}
   177  				newC.Ports = append(newC.Ports, types.Port{
   178  					PrivatePort: p,
   179  					PublicPort:  h,
   180  					Type:        port.Proto(),
   181  					IP:          binding.HostIP,
   182  				})
   183  			}
   184  		}
   185  
   186  		if config.Size {
   187  			sizeRw, sizeRootFs := container.GetSize()
   188  			newC.SizeRw = int(sizeRw)
   189  			newC.SizeRootFs = int(sizeRootFs)
   190  		}
   191  		newC.Labels = container.Config.Labels
   192  		containers = append(containers, newC)
   193  		return nil
   194  	}
   195  
   196  	for _, container := range daemon.List() {
   197  		if err := writeCont(container); err != nil {
   198  			if err != errLast {
   199  				return nil, err
   200  			}
   201  			break
   202  		}
   203  	}
   204  	return containers, nil
   205  }