1package formatter 2 3import ( 4 "fmt" 5 "sort" 6 "strings" 7 "time" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/pkg/stringid" 11 "github.com/docker/go-units" 12) 13 14const ( 15 defaultBuildCacheTableFormat = "table {{.ID}}\t{{.Type}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}\t{{.Description}}" 16 17 cacheIDHeader = "CACHE ID" 18 cacheTypeHeader = "CACHE TYPE" 19 parentHeader = "PARENT" 20 lastUsedSinceHeader = "LAST USED" 21 usageCountHeader = "USAGE" 22 inUseHeader = "IN USE" 23 sharedHeader = "SHARED" 24) 25 26// NewBuildCacheFormat returns a Format for rendering using a Context 27func NewBuildCacheFormat(source string, quiet bool) Format { 28 switch source { 29 case TableFormatKey: 30 if quiet { 31 return defaultQuietFormat 32 } 33 return Format(defaultBuildCacheTableFormat) 34 case RawFormatKey: 35 if quiet { 36 return `build_cache_id: {{.ID}}` 37 } 38 format := `build_cache_id: {{.ID}} 39parent_id: {{.Parent}} 40build_cache_type: {{.CacheType}} 41description: {{.Description}} 42created_at: {{.CreatedAt}} 43created_since: {{.CreatedSince}} 44last_used_at: {{.LastUsedAt}} 45last_used_since: {{.LastUsedSince}} 46usage_count: {{.UsageCount}} 47in_use: {{.InUse}} 48shared: {{.Shared}} 49` 50 return Format(format) 51 } 52 return Format(source) 53} 54 55func buildCacheSort(buildCache []*types.BuildCache) { 56 sort.Slice(buildCache, func(i, j int) bool { 57 lui, luj := buildCache[i].LastUsedAt, buildCache[j].LastUsedAt 58 switch { 59 case lui == nil && luj == nil: 60 return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0 61 case lui == nil: 62 return true 63 case luj == nil: 64 return false 65 case lui.Equal(*luj): 66 return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0 67 default: 68 return lui.Before(*luj) 69 } 70 }) 71} 72 73// BuildCacheWrite renders the context for a list of containers 74func BuildCacheWrite(ctx Context, buildCaches []*types.BuildCache) error { 75 render := func(format func(subContext subContext) error) error { 76 buildCacheSort(buildCaches) 77 for _, bc := range buildCaches { 78 err := format(&buildCacheContext{trunc: ctx.Trunc, v: bc}) 79 if err != nil { 80 return err 81 } 82 } 83 return nil 84 } 85 return ctx.Write(newBuildCacheContext(), render) 86} 87 88type buildCacheHeaderContext map[string]string 89 90type buildCacheContext struct { 91 HeaderContext 92 trunc bool 93 v *types.BuildCache 94} 95 96func newBuildCacheContext() *buildCacheContext { 97 buildCacheCtx := buildCacheContext{} 98 buildCacheCtx.header = buildCacheHeaderContext{ 99 "ID": cacheIDHeader, 100 "Parent": parentHeader, 101 "CacheType": cacheTypeHeader, 102 "Size": sizeHeader, 103 "CreatedSince": createdSinceHeader, 104 "LastUsedSince": lastUsedSinceHeader, 105 "UsageCount": usageCountHeader, 106 "InUse": inUseHeader, 107 "Shared": sharedHeader, 108 "Description": descriptionHeader, 109 } 110 return &buildCacheCtx 111} 112 113func (c *buildCacheContext) MarshalJSON() ([]byte, error) { 114 return marshalJSON(c) 115} 116 117func (c *buildCacheContext) ID() string { 118 id := c.v.ID 119 if c.trunc { 120 id = stringid.TruncateID(c.v.ID) 121 } 122 if c.v.InUse { 123 return id + "*" 124 } 125 return id 126} 127 128func (c *buildCacheContext) Parent() string { 129 if c.trunc { 130 return stringid.TruncateID(c.v.Parent) 131 } 132 return c.v.Parent 133} 134 135func (c *buildCacheContext) CacheType() string { 136 return c.v.Type 137} 138 139func (c *buildCacheContext) Description() string { 140 return c.v.Description 141} 142 143func (c *buildCacheContext) Size() string { 144 return units.HumanSizeWithPrecision(float64(c.v.Size), 3) 145} 146 147func (c *buildCacheContext) CreatedAt() string { 148 return c.v.CreatedAt.String() 149} 150 151func (c *buildCacheContext) CreatedSince() string { 152 return units.HumanDuration(time.Now().UTC().Sub(c.v.CreatedAt)) + " ago" 153} 154 155func (c *buildCacheContext) LastUsedAt() string { 156 if c.v.LastUsedAt == nil { 157 return "" 158 } 159 return c.v.LastUsedAt.String() 160} 161 162func (c *buildCacheContext) LastUsedSince() string { 163 if c.v.LastUsedAt == nil { 164 return "" 165 } 166 return units.HumanDuration(time.Now().UTC().Sub(*c.v.LastUsedAt)) + " ago" 167} 168 169func (c *buildCacheContext) UsageCount() string { 170 return fmt.Sprintf("%d", c.v.UsageCount) 171} 172 173func (c *buildCacheContext) InUse() string { 174 return fmt.Sprintf("%t", c.v.InUse) 175} 176 177func (c *buildCacheContext) Shared() string { 178 return fmt.Sprintf("%t", c.v.Shared) 179} 180