github.com/jandre/docker@v1.7.0/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/nat"
    11  	"github.com/docker/docker/pkg/graphdb"
    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 value == "exited" {
    57  				all = true
    58  			}
    59  		}
    60  	}
    61  	names := map[string][]string{}
    62  	daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
    63  		names[e.ID()] = append(names[e.ID()], p)
    64  		return nil
    65  	}, 1)
    66  
    67  	var beforeCont, sinceCont *Container
    68  	if config.Before != "" {
    69  		beforeCont, err = daemon.Get(config.Before)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  	}
    74  
    75  	if config.Since != "" {
    76  		sinceCont, err = daemon.Get(config.Since)
    77  		if err != nil {
    78  			return nil, err
    79  		}
    80  	}
    81  
    82  	errLast := errors.New("last container")
    83  	writeCont := func(container *Container) error {
    84  		container.Lock()
    85  		defer container.Unlock()
    86  		if !container.Running && !all && n <= 0 && config.Since == "" && config.Before == "" {
    87  			return nil
    88  		}
    89  		if !psFilters.Match("name", container.Name) {
    90  			return nil
    91  		}
    92  
    93  		if !psFilters.Match("id", container.ID) {
    94  			return nil
    95  		}
    96  
    97  		if !psFilters.MatchKVList("label", container.Config.Labels) {
    98  			return nil
    99  		}
   100  
   101  		if config.Before != "" && !foundBefore {
   102  			if container.ID == beforeCont.ID {
   103  				foundBefore = true
   104  			}
   105  			return nil
   106  		}
   107  		if n > 0 && displayed == n {
   108  			return errLast
   109  		}
   110  		if config.Since != "" {
   111  			if container.ID == sinceCont.ID {
   112  				return errLast
   113  			}
   114  		}
   115  		if len(filtExited) > 0 {
   116  			shouldSkip := true
   117  			for _, code := range filtExited {
   118  				if code == container.ExitCode && !container.Running {
   119  					shouldSkip = false
   120  					break
   121  				}
   122  			}
   123  			if shouldSkip {
   124  				return nil
   125  			}
   126  		}
   127  
   128  		if !psFilters.Match("status", container.State.StateString()) {
   129  			return nil
   130  		}
   131  		displayed++
   132  		newC := &types.Container{
   133  			ID:    container.ID,
   134  			Names: names[container.ID],
   135  		}
   136  		newC.Image = container.Config.Image
   137  		if len(container.Args) > 0 {
   138  			args := []string{}
   139  			for _, arg := range container.Args {
   140  				if strings.Contains(arg, " ") {
   141  					args = append(args, fmt.Sprintf("'%s'", arg))
   142  				} else {
   143  					args = append(args, arg)
   144  				}
   145  			}
   146  			argsAsString := strings.Join(args, " ")
   147  
   148  			newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString)
   149  		} else {
   150  			newC.Command = fmt.Sprintf("%s", container.Path)
   151  		}
   152  		newC.Created = int(container.Created.Unix())
   153  		newC.Status = container.State.String()
   154  
   155  		newC.Ports = []types.Port{}
   156  		for port, bindings := range container.NetworkSettings.Ports {
   157  			p, _ := nat.ParsePort(port.Port())
   158  			if len(bindings) == 0 {
   159  				newC.Ports = append(newC.Ports, types.Port{
   160  					PrivatePort: p,
   161  					Type:        port.Proto(),
   162  				})
   163  				continue
   164  			}
   165  			for _, binding := range bindings {
   166  				h, _ := nat.ParsePort(binding.HostPort)
   167  				newC.Ports = append(newC.Ports, types.Port{
   168  					PrivatePort: p,
   169  					PublicPort:  h,
   170  					Type:        port.Proto(),
   171  					IP:          binding.HostIp,
   172  				})
   173  			}
   174  		}
   175  
   176  		if config.Size {
   177  			sizeRw, sizeRootFs := container.GetSize()
   178  			newC.SizeRw = int(sizeRw)
   179  			newC.SizeRootFs = int(sizeRootFs)
   180  		}
   181  		newC.Labels = container.Config.Labels
   182  		containers = append(containers, newC)
   183  		return nil
   184  	}
   185  
   186  	for _, container := range daemon.List() {
   187  		if err := writeCont(container); err != nil {
   188  			if err != errLast {
   189  				return nil, err
   190  			}
   191  			break
   192  		}
   193  	}
   194  	return containers, nil
   195  }