2018-08-31 18:14:36 -04:00
|
|
|
package formatter
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/pkg/stringid"
|
|
|
|
"github.com/docker/go-units"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultBuildCacheTableFormat = "table {{.ID}}\t{{.Type}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}\t{{.Description}}"
|
|
|
|
|
|
|
|
cacheIDHeader = "CACHE ID"
|
2018-09-13 13:47:40 -04:00
|
|
|
cacheTypeHeader = "CACHE TYPE"
|
2018-08-31 18:14:36 -04:00
|
|
|
parentHeader = "PARENT"
|
|
|
|
lastUsedSinceHeader = "LAST USED"
|
|
|
|
usageCountHeader = "USAGE"
|
|
|
|
inUseHeader = "IN USE"
|
|
|
|
sharedHeader = "SHARED"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewBuildCacheFormat returns a Format for rendering using a Context
|
|
|
|
func NewBuildCacheFormat(source string, quiet bool) Format {
|
|
|
|
switch source {
|
|
|
|
case TableFormatKey:
|
|
|
|
if quiet {
|
2018-10-23 11:05:44 -04:00
|
|
|
return DefaultQuietFormat
|
2018-08-31 18:14:36 -04:00
|
|
|
}
|
|
|
|
return Format(defaultBuildCacheTableFormat)
|
|
|
|
case RawFormatKey:
|
|
|
|
if quiet {
|
|
|
|
return `build_cache_id: {{.ID}}`
|
|
|
|
}
|
|
|
|
format := `build_cache_id: {{.ID}}
|
|
|
|
parent_id: {{.Parent}}
|
2018-09-13 13:47:40 -04:00
|
|
|
build_cache_type: {{.CacheType}}
|
2018-08-31 18:14:36 -04:00
|
|
|
description: {{.Description}}
|
2018-09-13 13:47:40 -04:00
|
|
|
created_at: {{.CreatedAt}}
|
|
|
|
created_since: {{.CreatedSince}}
|
|
|
|
last_used_at: {{.LastUsedAt}}
|
|
|
|
last_used_since: {{.LastUsedSince}}
|
2018-08-31 18:14:36 -04:00
|
|
|
usage_count: {{.UsageCount}}
|
|
|
|
in_use: {{.InUse}}
|
|
|
|
shared: {{.Shared}}
|
|
|
|
`
|
|
|
|
return Format(format)
|
|
|
|
}
|
|
|
|
return Format(source)
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildCacheSort(buildCache []*types.BuildCache) {
|
|
|
|
sort.Slice(buildCache, func(i, j int) bool {
|
|
|
|
lui, luj := buildCache[i].LastUsedAt, buildCache[j].LastUsedAt
|
|
|
|
switch {
|
|
|
|
case lui == nil && luj == nil:
|
|
|
|
return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0
|
|
|
|
case lui == nil:
|
|
|
|
return true
|
|
|
|
case luj == nil:
|
|
|
|
return false
|
|
|
|
case lui.Equal(*luj):
|
|
|
|
return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0
|
|
|
|
default:
|
|
|
|
return lui.Before(*luj)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// BuildCacheWrite renders the context for a list of containers
|
|
|
|
func BuildCacheWrite(ctx Context, buildCaches []*types.BuildCache) error {
|
2018-10-23 11:05:44 -04:00
|
|
|
render := func(format func(subContext SubContext) error) error {
|
2018-08-31 18:14:36 -04:00
|
|
|
buildCacheSort(buildCaches)
|
|
|
|
for _, bc := range buildCaches {
|
|
|
|
err := format(&buildCacheContext{trunc: ctx.Trunc, v: bc})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ctx.Write(newBuildCacheContext(), render)
|
|
|
|
}
|
|
|
|
|
|
|
|
type buildCacheContext struct {
|
|
|
|
HeaderContext
|
|
|
|
trunc bool
|
|
|
|
v *types.BuildCache
|
|
|
|
}
|
|
|
|
|
|
|
|
func newBuildCacheContext() *buildCacheContext {
|
|
|
|
buildCacheCtx := buildCacheContext{}
|
2018-10-23 11:05:44 -04:00
|
|
|
buildCacheCtx.Header = SubHeaderContext{
|
2018-08-31 18:14:36 -04:00
|
|
|
"ID": cacheIDHeader,
|
|
|
|
"Parent": parentHeader,
|
2018-09-13 13:47:40 -04:00
|
|
|
"CacheType": cacheTypeHeader,
|
2018-10-23 11:05:44 -04:00
|
|
|
"Size": SizeHeader,
|
|
|
|
"CreatedSince": CreatedSinceHeader,
|
2018-08-31 18:14:36 -04:00
|
|
|
"LastUsedSince": lastUsedSinceHeader,
|
|
|
|
"UsageCount": usageCountHeader,
|
|
|
|
"InUse": inUseHeader,
|
|
|
|
"Shared": sharedHeader,
|
2018-10-23 11:05:44 -04:00
|
|
|
"Description": DescriptionHeader,
|
2018-08-31 18:14:36 -04:00
|
|
|
}
|
|
|
|
return &buildCacheCtx
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) MarshalJSON() ([]byte, error) {
|
2018-10-23 11:05:44 -04:00
|
|
|
return MarshalJSON(c)
|
2018-08-31 18:14:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) ID() string {
|
|
|
|
id := c.v.ID
|
|
|
|
if c.trunc {
|
|
|
|
id = stringid.TruncateID(c.v.ID)
|
|
|
|
}
|
|
|
|
if c.v.InUse {
|
|
|
|
return id + "*"
|
|
|
|
}
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) Parent() string {
|
|
|
|
if c.trunc {
|
|
|
|
return stringid.TruncateID(c.v.Parent)
|
|
|
|
}
|
|
|
|
return c.v.Parent
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:47:40 -04:00
|
|
|
func (c *buildCacheContext) CacheType() string {
|
2018-08-31 18:14:36 -04:00
|
|
|
return c.v.Type
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) Description() string {
|
|
|
|
return c.v.Description
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) Size() string {
|
|
|
|
return units.HumanSizeWithPrecision(float64(c.v.Size), 3)
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:47:40 -04:00
|
|
|
func (c *buildCacheContext) CreatedAt() string {
|
|
|
|
return c.v.CreatedAt.String()
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:14:36 -04:00
|
|
|
func (c *buildCacheContext) CreatedSince() string {
|
|
|
|
return units.HumanDuration(time.Now().UTC().Sub(c.v.CreatedAt)) + " ago"
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:47:40 -04:00
|
|
|
func (c *buildCacheContext) LastUsedAt() string {
|
|
|
|
if c.v.LastUsedAt == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return c.v.LastUsedAt.String()
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:14:36 -04:00
|
|
|
func (c *buildCacheContext) LastUsedSince() string {
|
|
|
|
if c.v.LastUsedAt == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return units.HumanDuration(time.Now().UTC().Sub(*c.v.LastUsedAt)) + " ago"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) UsageCount() string {
|
|
|
|
return fmt.Sprintf("%d", c.v.UsageCount)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) InUse() string {
|
|
|
|
return fmt.Sprintf("%t", c.v.InUse)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *buildCacheContext) Shared() string {
|
|
|
|
return fmt.Sprintf("%t", c.v.Shared)
|
|
|
|
}
|