github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/cli/command/formatter/container.go (about)

     1  package formatter
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/docker/docker/api"
    10  	"github.com/docker/docker/api/types"
    11  	"github.com/docker/docker/pkg/stringid"
    12  	"github.com/docker/docker/pkg/stringutils"
    13  	units "github.com/docker/go-units"
    14  )
    15  
    16  const (
    17  	defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}} ago\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
    18  
    19  	containerIDHeader = "CONTAINER ID"
    20  	namesHeader       = "NAMES"
    21  	commandHeader     = "COMMAND"
    22  	runningForHeader  = "CREATED"
    23  	statusHeader      = "STATUS"
    24  	portsHeader       = "PORTS"
    25  	mountsHeader      = "MOUNTS"
    26  	localVolumes      = "LOCAL VOLUMES"
    27  )
    28  
    29  // NewContainerFormat returns a Format for rendering using a Context
    30  func NewContainerFormat(source string, quiet bool, size bool) Format {
    31  	switch source {
    32  	case TableFormatKey:
    33  		if quiet {
    34  			return defaultQuietFormat
    35  		}
    36  		format := defaultContainerTableFormat
    37  		if size {
    38  			format += `\t{{.Size}}`
    39  		}
    40  		return Format(format)
    41  	case RawFormatKey:
    42  		if quiet {
    43  			return `container_id: {{.ID}}`
    44  		}
    45  		format := `container_id: {{.ID}}
    46  image: {{.Image}}
    47  command: {{.Command}}
    48  created_at: {{.CreatedAt}}
    49  status: {{- pad .Status 1 0}}
    50  names: {{.Names}}
    51  labels: {{- pad .Labels 1 0}}
    52  ports: {{- pad .Ports 1 0}}
    53  `
    54  		if size {
    55  			format += `size: {{.Size}}\n`
    56  		}
    57  		return Format(format)
    58  	}
    59  	return Format(source)
    60  }
    61  
    62  // ContainerWrite renders the context for a list of containers
    63  func ContainerWrite(ctx Context, containers []types.Container) error {
    64  	render := func(format func(subContext subContext) error) error {
    65  		for _, container := range containers {
    66  			err := format(&containerContext{trunc: ctx.Trunc, c: container})
    67  			if err != nil {
    68  				return err
    69  			}
    70  		}
    71  		return nil
    72  	}
    73  	return ctx.Write(&containerContext{}, render)
    74  }
    75  
    76  type containerContext struct {
    77  	HeaderContext
    78  	trunc bool
    79  	c     types.Container
    80  }
    81  
    82  func (c *containerContext) ID() string {
    83  	c.AddHeader(containerIDHeader)
    84  	if c.trunc {
    85  		return stringid.TruncateID(c.c.ID)
    86  	}
    87  	return c.c.ID
    88  }
    89  
    90  func (c *containerContext) Names() string {
    91  	c.AddHeader(namesHeader)
    92  	names := stripNamePrefix(c.c.Names)
    93  	if c.trunc {
    94  		for _, name := range names {
    95  			if len(strings.Split(name, "/")) == 1 {
    96  				names = []string{name}
    97  				break
    98  			}
    99  		}
   100  	}
   101  	return strings.Join(names, ",")
   102  }
   103  
   104  func (c *containerContext) Image() string {
   105  	c.AddHeader(imageHeader)
   106  	if c.c.Image == "" {
   107  		return "<no image>"
   108  	}
   109  	if c.trunc {
   110  		if trunc := stringid.TruncateID(c.c.ImageID); trunc == stringid.TruncateID(c.c.Image) {
   111  			return trunc
   112  		}
   113  	}
   114  	return c.c.Image
   115  }
   116  
   117  func (c *containerContext) Command() string {
   118  	c.AddHeader(commandHeader)
   119  	command := c.c.Command
   120  	if c.trunc {
   121  		command = stringutils.Ellipsis(command, 20)
   122  	}
   123  	return strconv.Quote(command)
   124  }
   125  
   126  func (c *containerContext) CreatedAt() string {
   127  	c.AddHeader(createdAtHeader)
   128  	return time.Unix(int64(c.c.Created), 0).String()
   129  }
   130  
   131  func (c *containerContext) RunningFor() string {
   132  	c.AddHeader(runningForHeader)
   133  	createdAt := time.Unix(int64(c.c.Created), 0)
   134  	return units.HumanDuration(time.Now().UTC().Sub(createdAt))
   135  }
   136  
   137  func (c *containerContext) Ports() string {
   138  	c.AddHeader(portsHeader)
   139  	return api.DisplayablePorts(c.c.Ports)
   140  }
   141  
   142  func (c *containerContext) Status() string {
   143  	c.AddHeader(statusHeader)
   144  	return c.c.Status
   145  }
   146  
   147  func (c *containerContext) Size() string {
   148  	c.AddHeader(sizeHeader)
   149  	srw := units.HumanSizeWithPrecision(float64(c.c.SizeRw), 3)
   150  	sv := units.HumanSizeWithPrecision(float64(c.c.SizeRootFs), 3)
   151  
   152  	sf := srw
   153  	if c.c.SizeRootFs > 0 {
   154  		sf = fmt.Sprintf("%s (virtual %s)", srw, sv)
   155  	}
   156  	return sf
   157  }
   158  
   159  func (c *containerContext) Labels() string {
   160  	c.AddHeader(labelsHeader)
   161  	if c.c.Labels == nil {
   162  		return ""
   163  	}
   164  
   165  	var joinLabels []string
   166  	for k, v := range c.c.Labels {
   167  		joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v))
   168  	}
   169  	return strings.Join(joinLabels, ",")
   170  }
   171  
   172  func (c *containerContext) Label(name string) string {
   173  	n := strings.Split(name, ".")
   174  	r := strings.NewReplacer("-", " ", "_", " ")
   175  	h := r.Replace(n[len(n)-1])
   176  
   177  	c.AddHeader(h)
   178  
   179  	if c.c.Labels == nil {
   180  		return ""
   181  	}
   182  	return c.c.Labels[name]
   183  }
   184  
   185  func (c *containerContext) Mounts() string {
   186  	c.AddHeader(mountsHeader)
   187  
   188  	var name string
   189  	var mounts []string
   190  	for _, m := range c.c.Mounts {
   191  		if m.Name == "" {
   192  			name = m.Source
   193  		} else {
   194  			name = m.Name
   195  		}
   196  		if c.trunc {
   197  			name = stringutils.Ellipsis(name, 15)
   198  		}
   199  		mounts = append(mounts, name)
   200  	}
   201  	return strings.Join(mounts, ",")
   202  }
   203  
   204  func (c *containerContext) LocalVolumes() string {
   205  	c.AddHeader(localVolumes)
   206  
   207  	count := 0
   208  	for _, m := range c.c.Mounts {
   209  		if m.Driver == "local" {
   210  			count++
   211  		}
   212  	}
   213  
   214  	return fmt.Sprintf("%d", count)
   215  }