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