From 96ab027a3c9eaf02faae9f4c8bd822f8471fbc2a Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 23 Oct 2025 09:22:03 -0400 Subject: [PATCH] Add CreatedAt format option to podman artifact ls This change adds a .CreatedAt format option to the podman artifact ls command to match the behavior of podman images --format CreatedAt. The .Created field continues to display human-readable elapsed time (e.g., '6 hours ago'), while the new .CreatedAt field displays the full timestamp (e.g., '2025-10-23 12:34:56 +0000 UTC'). Changes: - Refactored artifactListOutput struct to store time.Time value - Added CreatedAt() method returning full timestamp string - Added Created() method for human-readable duration - Updated documentation to include .CreatedAt field - Added e2e test for .CreatedAt format option Generated-with: Cursor AI Signed-off-by: Daniel J Walsh --- cmd/podman/artifact/list.go | 47 +++++++++++++------ .../markdown/podman-artifact-ls.1.md.in | 1 + test/e2e/artifact_test.go | 10 ++++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/cmd/podman/artifact/list.go b/cmd/podman/artifact/list.go index 86e5164e73..805354d2f7 100644 --- a/cmd/podman/artifact/list.go +++ b/cmd/podman/artifact/list.go @@ -38,12 +38,29 @@ type listFlagType struct { } type artifactListOutput struct { - Digest string - Repository string - Size string - Tag string - Created string - VirtualSize string + Digest string + Repository string + Size string + Tag string + created time.Time + VirtualSize string + virtualBytes int64 +} + +// Created returns human-readable elapsed time since artifact was created +func (a artifactListOutput) Created() string { + if a.created.IsZero() { + return "" + } + return units.HumanDuration(time.Since(a.created)) + " ago" +} + +// CreatedAt returns the full timestamp string of when the artifact was created +func (a artifactListOutput) CreatedAt() string { + if a.created.IsZero() { + return "" + } + return a.created.String() } var ( @@ -109,23 +126,23 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro artifactHash = artifactDigest.Encoded() } - var created string + var createdTime time.Time createdAnnotation, ok := lr.Manifest.Annotations[imgspecv1.AnnotationCreated] if ok { - createdTime, err := time.Parse(time.RFC3339Nano, createdAnnotation) + 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()), + Digest: artifactHash, + Repository: named.Name(), + Size: units.HumanSize(float64(lr.Artifact.TotalSizeBytes())), + Tag: tag, + created: createdTime, + VirtualSize: fmt.Sprintf("%d", lr.Artifact.TotalSizeBytes()), + virtualBytes: lr.Artifact.TotalSizeBytes(), }) } diff --git a/docs/source/markdown/podman-artifact-ls.1.md.in b/docs/source/markdown/podman-artifact-ls.1.md.in index d2b6203639..81cedd5783 100644 --- a/docs/source/markdown/podman-artifact-ls.1.md.in +++ b/docs/source/markdown/podman-artifact-ls.1.md.in @@ -19,6 +19,7 @@ Print results with a Go template. | **Placeholder** | **Description** | |-----------------|------------------------------------------------| | .Created | Elapsed time since the artifact was created | +| .CreatedAt | Full timestamp of when 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 | diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index 37683be3a2..f5b0e4ac69 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -88,6 +88,16 @@ var _ = Describe("Podman artifact", func() { // 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))) + + // Check if .CreatedAt is reported correctly + createdAtFormatSession := podmanTest.PodmanExitCleanly("artifact", "ls", "--format", "{{.CreatedAt}}") + createdAt := createdAtFormatSession.OutputToStringArray() + + Expect(createdAt).To(HaveLen(2)) + + // Verify the timestamp format looks like "2025-10-23 12:34:56.789 +0000 UTC" + timestampRegexp := `^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)? \+\d{4} UTC$` + Expect(createdAt).To(ContainElements(MatchRegexp(timestampRegexp), MatchRegexp(timestampRegexp))) }) It("podman artifact simple add", func() {