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 }