diff --git a/cli/command/formatter/image.go b/cli/command/formatter/image.go index 91893e8f97..384b35dc19 100644 --- a/cli/command/formatter/image.go +++ b/cli/command/formatter/image.go @@ -11,8 +11,8 @@ import ( ) const ( - defaultImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}" - defaultImageTableFormatWithDigest = "table {{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}" + defaultImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{if .CreatedSince }}{{.CreatedSince}}{{else}}N/A{{end}}\t{{.Size}}" + defaultImageTableFormatWithDigest = "table {{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.ID}}\t{{if .CreatedSince }}{{.CreatedSince}}{{else}}N/A{{end}}\t{{.Size}}" imageIDHeader = "IMAGE ID" repositoryHeader = "REPOSITORY" @@ -235,6 +235,11 @@ func (c *imageContext) Digest() string { func (c *imageContext) CreatedSince() string { createdAt := time.Unix(c.i.Created, 0) + + if createdAt.IsZero() { + return "" + } + return units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago" } diff --git a/cli/command/formatter/image_test.go b/cli/command/formatter/image_test.go index 7efad0a758..55a91a9e2b 100644 --- a/cli/command/formatter/image_test.go +++ b/cli/command/formatter/image_test.go @@ -16,6 +16,7 @@ import ( func TestImageContext(t *testing.T) { imageID := stringid.GenerateRandomID() unix := time.Now().Unix() + zeroTime := int64(-62135596800) var ctx imageContext cases := []struct { @@ -76,6 +77,11 @@ func TestImageContext(t *testing.T) { i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}, }, "15kB", ctx.UniqueSize, }, + { + imageContext{ + i: types.ImageSummary{Created: zeroTime}, + }, "", ctx.CreatedSince, + }, } for _, c := range cases { @@ -91,7 +97,9 @@ func TestImageContext(t *testing.T) { func TestImageContextWrite(t *testing.T) { unixTime := time.Now().AddDate(0, 0, -1).Unix() + zeroTime := int64(-62135596800) expectedTime := time.Unix(unixTime, 0).String() + expectedZeroTime := time.Unix(zeroTime, 0).String() cases := []struct { context ImageContext @@ -125,7 +133,7 @@ func TestImageContextWrite(t *testing.T) { }, `REPOSITORY TAG IMAGE ID CREATED SIZE image tag1 imageID1 24 hours ago 0B -image tag2 imageID2 24 hours ago 0B +image tag2 imageID2 N/A 0B imageID3 24 hours ago 0B `, }, @@ -183,7 +191,7 @@ image }, `REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE image tag1 sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0B -image tag2 imageID2 24 hours ago 0B +image tag2 imageID2 N/A 0B imageID3 24 hours ago 0B `, }, @@ -221,7 +229,7 @@ image_id: imageID3 created_at: %s virtual_size: 0B -`, expectedTime, expectedTime, expectedTime), +`, expectedTime, expectedZeroTime, expectedTime), }, { ImageContext{ @@ -251,7 +259,7 @@ image_id: imageID3 created_at: %s virtual_size: 0B -`, expectedTime, expectedTime, expectedTime), +`, expectedTime, expectedZeroTime, expectedTime), }, { ImageContext{ @@ -287,7 +295,7 @@ image_id: imageID3 for _, testcase := range cases { images := []types.ImageSummary{ {ID: "imageID1", RepoTags: []string{"image:tag1"}, RepoDigests: []string{"image@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf"}, Created: unixTime}, - {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: unixTime}, + {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: zeroTime}, {ID: "imageID3", RepoTags: []string{":"}, RepoDigests: []string{"@"}, Created: unixTime}, } out := bytes.NewBufferString("")