diff --git a/cmd/podman/artifact/list.go b/cmd/podman/artifact/list.go index dbb7cc2aad..86e5164e73 100644 --- a/cmd/podman/artifact/list.go +++ b/cmd/podman/artifact/list.go @@ -3,12 +3,14 @@ package artifact import ( "fmt" "os" + "time" "github.com/containers/podman/v5/cmd/podman/common" "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/docker/go-units" + imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/cobra" "go.podman.io/common/pkg/completion" "go.podman.io/common/pkg/report" @@ -40,11 +42,12 @@ type artifactListOutput struct { Repository string Size string Tag string + Created string VirtualSize string } var ( - defaultArtifactListOutputFormat = "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.Size}}\n{{end -}}" + defaultArtifactListOutputFormat = "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.Created}}\t{{.Size}}\n{{end -}}" ) func init() { @@ -106,11 +109,22 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro artifactHash = artifactDigest.Encoded() } + var created string + createdAnnotation, ok := lr.Manifest.Annotations[imgspecv1.AnnotationCreated] + if ok { + createdTime, err := time.Parse(time.RFC3339Nano, createdAnnotation) + if err != nil { + return err + } + created = units.HumanDuration(time.Since(createdTime)) + " ago" + } + artifacts = append(artifacts, artifactListOutput{ Digest: artifactHash, Repository: named.Name(), Size: units.HumanSize(float64(lr.Artifact.TotalSizeBytes())), Tag: tag, + Created: created, VirtualSize: fmt.Sprintf("%d", lr.Artifact.TotalSizeBytes()), }) } @@ -118,6 +132,7 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro headers := report.Headers(artifactListOutput{}, map[string]string{ "REPOSITORY": "REPOSITORY", "Tag": "TAG", + "Created": "CREATED", "Size": "SIZE", "Digest": "DIGEST", }) diff --git a/docs/source/markdown/podman-artifact-ls.1.md.in b/docs/source/markdown/podman-artifact-ls.1.md.in index a2590d7334..d2b6203639 100644 --- a/docs/source/markdown/podman-artifact-ls.1.md.in +++ b/docs/source/markdown/podman-artifact-ls.1.md.in @@ -18,6 +18,7 @@ Print results with a Go template. | **Placeholder** | **Description** | |-----------------|------------------------------------------------| +| .Created | Elapsed time since the artifact was created | | .Digest | The computed digest of the artifact's manifest | | .Repository | Repository name of the artifact | | .Size | Size artifact in human readable units | @@ -33,24 +34,24 @@ Print results with a Go template. List artifacts in the local store ``` $ podman artifact ls -REPOSITORY TAG DIGEST SIZE -quay.io/artifact/foobar1 latest ab609fad386d 2.097GB -quay.io/artifact/foobar2 special cd734b558ceb 12.58MB +REPOSITORY TAG DIGEST CREATED SIZE +quay.io/artifact/foobar1 latest ab609fad386d 6 hours ago 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb 53 seconds ago 12.58MB ``` List artifacts in the local store without truncating the digest ``` $ podman artifact ls --no-trunc -REPOSITORY TAG DIGEST SIZE -quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB -quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB +REPOSITORY TAG DIGEST CREATED SIZE +quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 6 hours ago 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 53 seconds ago 12.58MB ``` List artifacts in the local store without the title header ``` $ podman artifact ls --noheading -quay.io/artifact/foobar1 latest ab609fad386d 2.097GB -quay.io/artifact/foobar2 special cd734b558ceb 12.58MB +quay.io/artifact/foobar1 latest ab609fad386d 6 hours ago 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb 53 seconds ago 12.58MB ``` List artifact digests and size using a --format diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index cf59e3f3c5..fd640aca11 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -78,6 +78,16 @@ var _ = Describe("Podman artifact", func() { // Verify if the virtual size values are present in the output Expect(virtualSizes).To(ContainElement("4192")) Expect(virtualSizes).To(ContainElement("10240")) + + // Check if .Created is reported correctly + createdFormatSession := podmanTest.PodmanExitCleanly("artifact", "ls", "--format", "{{.Created}}") + created := createdFormatSession.OutputToStringArray() + + Expect(created).To(HaveLen(2)) + + // Assuming the test runs less than a minute + humanReadableDurationRegexp := `^(Less than a second|1 second|\d+ seconds) ago$` + Expect(created).To(ContainElements(MatchRegexp(humanReadableDurationRegexp), MatchRegexp(humanReadableDurationRegexp))) }) It("podman artifact simple add", func() {