github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/api/client/formatter/custom.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/pkg/stringid" 11 "github.com/docker/docker/pkg/stringutils" 12 "github.com/docker/engine-api/types" 13 "github.com/docker/go-units" 14 ) 15 16 const ( 17 tableKey = "table" 18 19 containerIDHeader = "CONTAINER ID" 20 imageHeader = "IMAGE" 21 namesHeader = "NAMES" 22 commandHeader = "COMMAND" 23 createdSinceHeader = "CREATED" 24 createdAtHeader = "CREATED AT" 25 runningForHeader = "CREATED" 26 statusHeader = "STATUS" 27 portsHeader = "PORTS" 28 sizeHeader = "SIZE" 29 labelsHeader = "LABELS" 30 imageIDHeader = "IMAGE ID" 31 repositoryHeader = "REPOSITORY" 32 tagHeader = "TAG" 33 digestHeader = "DIGEST" 34 mountsHeader = "MOUNTS" 35 ) 36 37 type containerContext struct { 38 baseSubContext 39 trunc bool 40 c types.Container 41 } 42 43 func (c *containerContext) ID() string { 44 c.addHeader(containerIDHeader) 45 if c.trunc { 46 return stringid.TruncateID(c.c.ID) 47 } 48 return c.c.ID 49 } 50 51 func (c *containerContext) Names() string { 52 c.addHeader(namesHeader) 53 names := stripNamePrefix(c.c.Names) 54 if c.trunc { 55 for _, name := range names { 56 if len(strings.Split(name, "/")) == 1 { 57 names = []string{name} 58 break 59 } 60 } 61 } 62 return strings.Join(names, ",") 63 } 64 65 func (c *containerContext) Image() string { 66 c.addHeader(imageHeader) 67 if c.c.Image == "" { 68 return "<no image>" 69 } 70 if c.trunc { 71 if trunc := stringid.TruncateID(c.c.ImageID); trunc == stringid.TruncateID(c.c.Image) { 72 return trunc 73 } 74 } 75 return c.c.Image 76 } 77 78 func (c *containerContext) Command() string { 79 c.addHeader(commandHeader) 80 command := c.c.Command 81 if c.trunc { 82 command = stringutils.Truncate(command, 20) 83 } 84 return strconv.Quote(command) 85 } 86 87 func (c *containerContext) CreatedAt() string { 88 c.addHeader(createdAtHeader) 89 return time.Unix(int64(c.c.Created), 0).String() 90 } 91 92 func (c *containerContext) RunningFor() string { 93 c.addHeader(runningForHeader) 94 createdAt := time.Unix(int64(c.c.Created), 0) 95 return units.HumanDuration(time.Now().UTC().Sub(createdAt)) 96 } 97 98 func (c *containerContext) Ports() string { 99 c.addHeader(portsHeader) 100 return api.DisplayablePorts(c.c.Ports) 101 } 102 103 func (c *containerContext) Status() string { 104 c.addHeader(statusHeader) 105 return c.c.Status 106 } 107 108 func (c *containerContext) Size() string { 109 c.addHeader(sizeHeader) 110 srw := units.HumanSize(float64(c.c.SizeRw)) 111 sv := units.HumanSize(float64(c.c.SizeRootFs)) 112 113 sf := srw 114 if c.c.SizeRootFs > 0 { 115 sf = fmt.Sprintf("%s (virtual %s)", srw, sv) 116 } 117 return sf 118 } 119 120 func (c *containerContext) Labels() string { 121 c.addHeader(labelsHeader) 122 if c.c.Labels == nil { 123 return "" 124 } 125 126 var joinLabels []string 127 for k, v := range c.c.Labels { 128 joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) 129 } 130 return strings.Join(joinLabels, ",") 131 } 132 133 func (c *containerContext) Label(name string) string { 134 n := strings.Split(name, ".") 135 r := strings.NewReplacer("-", " ", "_", " ") 136 h := r.Replace(n[len(n)-1]) 137 138 c.addHeader(h) 139 140 if c.c.Labels == nil { 141 return "" 142 } 143 return c.c.Labels[name] 144 } 145 146 func (c *containerContext) Mounts() string { 147 c.addHeader(mountsHeader) 148 149 var name string 150 var mounts []string 151 for _, m := range c.c.Mounts { 152 if m.Name == "" { 153 name = m.Source 154 } else { 155 name = m.Name 156 } 157 if c.trunc { 158 name = stringutils.Truncate(name, 15) 159 } 160 mounts = append(mounts, name) 161 } 162 return strings.Join(mounts, ",") 163 } 164 165 type imageContext struct { 166 baseSubContext 167 trunc bool 168 i types.Image 169 repo string 170 tag string 171 digest string 172 } 173 174 func (c *imageContext) ID() string { 175 c.addHeader(imageIDHeader) 176 if c.trunc { 177 return stringid.TruncateID(c.i.ID) 178 } 179 return c.i.ID 180 } 181 182 func (c *imageContext) Repository() string { 183 c.addHeader(repositoryHeader) 184 return c.repo 185 } 186 187 func (c *imageContext) Tag() string { 188 c.addHeader(tagHeader) 189 return c.tag 190 } 191 192 func (c *imageContext) Digest() string { 193 c.addHeader(digestHeader) 194 return c.digest 195 } 196 197 func (c *imageContext) CreatedSince() string { 198 c.addHeader(createdSinceHeader) 199 createdAt := time.Unix(int64(c.i.Created), 0) 200 return units.HumanDuration(time.Now().UTC().Sub(createdAt)) 201 } 202 203 func (c *imageContext) CreatedAt() string { 204 c.addHeader(createdAtHeader) 205 return time.Unix(int64(c.i.Created), 0).String() 206 } 207 208 func (c *imageContext) Size() string { 209 c.addHeader(sizeHeader) 210 return units.HumanSize(float64(c.i.Size)) 211 } 212 213 type subContext interface { 214 fullHeader() string 215 addHeader(header string) 216 } 217 218 type baseSubContext struct { 219 header []string 220 } 221 222 func (c *baseSubContext) fullHeader() string { 223 if c.header == nil { 224 return "" 225 } 226 return strings.Join(c.header, "\t") 227 } 228 229 func (c *baseSubContext) addHeader(header string) { 230 if c.header == nil { 231 c.header = []string{} 232 } 233 c.header = append(c.header, strings.ToUpper(header)) 234 } 235 236 func stripNamePrefix(ss []string) []string { 237 sss := make([]string, len(ss)) 238 for i, s := range ss { 239 sss[i] = s[1:] 240 } 241 242 return sss 243 }