Skip to content

Commit a2eec9a

Browse files
rhatdanCursor AI
andcommitted
Add CREATED column to podman artifact ls output
This change adds a CREATED column to the podman artifact ls command output, displaying the artifact creation time in human-readable format (e.g., "3 weeks ago"), similar to podman image ls. The creation time is extracted from the org.opencontainers.image.created annotation stored in the artifact manifest and formatted using units.HumanDuration. Changes: - Add Created field to artifactListOutput struct - Parse and format creation time from manifest annotations - Update default output format to include CREATED column - Update documentation with Created placeholder - Add test to verify Created column is displayed Fixes #27314 Co-authored-by: Cursor AI <[email protected]> Signed-off-by: Daniel J Walsh <[email protected]>
1 parent b3ec5cf commit a2eec9a

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

cmd/podman/artifact/list.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package artifact
33
import (
44
"fmt"
55
"os"
6+
"time"
67

78
"github.com/containers/podman/v5/cmd/podman/common"
89
"github.com/containers/podman/v5/cmd/podman/registry"
910
"github.com/containers/podman/v5/cmd/podman/validate"
1011
"github.com/containers/podman/v5/pkg/domain/entities"
1112
"github.com/docker/go-units"
13+
imgspec "github.com/opencontainers/image-spec/specs-go/v1"
1214
"github.com/spf13/cobra"
1315
"go.podman.io/common/pkg/completion"
1416
"go.podman.io/common/pkg/report"
@@ -36,6 +38,7 @@ type listFlagType struct {
3638
}
3739

3840
type artifactListOutput struct {
41+
Created string
3942
Digest string
4043
Repository string
4144
Size string
@@ -44,7 +47,7 @@ type artifactListOutput struct {
4447
}
4548

4649
var (
47-
defaultArtifactListOutputFormat = "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.Size}}\n{{end -}}"
50+
defaultArtifactListOutputFormat = "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.Created}}\t{{.Size}}\n{{end -}}"
4851
)
4952

5053
func init() {
@@ -106,7 +109,18 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro
106109
artifactHash = artifactDigest.Encoded()
107110
}
108111

112+
// Get the created time from the manifest annotations
113+
created := "<unknown>"
114+
if lr.Artifact.Manifest != nil && lr.Artifact.Manifest.Annotations != nil {
115+
if createdStr, ok := lr.Artifact.Manifest.Annotations[imgspec.AnnotationCreated]; ok {
116+
if createdTime, err := time.Parse(time.RFC3339Nano, createdStr); err == nil {
117+
created = units.HumanDuration(time.Since(createdTime)) + " ago"
118+
}
119+
}
120+
}
121+
109122
artifacts = append(artifacts, artifactListOutput{
123+
Created: created,
110124
Digest: artifactHash,
111125
Repository: named.Name(),
112126
Size: units.HumanSize(float64(lr.Artifact.TotalSizeBytes())),
@@ -116,10 +130,11 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro
116130
}
117131

118132
headers := report.Headers(artifactListOutput{}, map[string]string{
119-
"REPOSITORY": "REPOSITORY",
120-
"Tag": "TAG",
121-
"Size": "SIZE",
133+
"Created": "CREATED",
122134
"Digest": "DIGEST",
135+
"Repository": "REPOSITORY",
136+
"Size": "SIZE",
137+
"Tag": "TAG",
123138
})
124139

125140
rpt := report.New(os.Stdout, cmd.Name())

docs/source/markdown/podman-artifact-ls.1.md.in

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Print results with a Go template.
1818

1919
| **Placeholder** | **Description** |
2020
|-----------------|------------------------------------------------|
21+
| .Created | Artifact creation time in human readable units |
2122
| .Digest | The computed digest of the artifact's manifest |
2223
| .Repository | Repository name of the artifact |
2324
| .Size | Size artifact in human readable units |
@@ -33,24 +34,24 @@ Print results with a Go template.
3334
List artifacts in the local store
3435
```
3536
$ podman artifact ls
36-
REPOSITORY TAG DIGEST SIZE
37-
quay.io/artifact/foobar1 latest ab609fad386d 2.097GB
38-
quay.io/artifact/foobar2 special cd734b558ceb 12.58MB
37+
REPOSITORY TAG DIGEST CREATED SIZE
38+
quay.io/artifact/foobar1 latest ab609fad386d 3 weeks ago 2.097GB
39+
quay.io/artifact/foobar2 special cd734b558ceb 2 days ago 12.58MB
3940
```
4041

4142
List artifacts in the local store without truncating the digest
4243
```
4344
$ podman artifact ls --no-trunc
44-
REPOSITORY TAG DIGEST SIZE
45-
quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB
46-
quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB
45+
REPOSITORY TAG DIGEST CREATED SIZE
46+
quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 3 weeks ago 2.097GB
47+
quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 2 days ago 12.58MB
4748
```
4849

4950
List artifacts in the local store without the title header
5051
```
5152
$ podman artifact ls --noheading
52-
quay.io/artifact/foobar1 latest ab609fad386d 2.097GB
53-
quay.io/artifact/foobar2 special cd734b558ceb 12.58MB
53+
quay.io/artifact/foobar1 latest ab609fad386d 3 weeks ago 2.097GB
54+
quay.io/artifact/foobar2 special cd734b558ceb 2 days ago 12.58MB
5455
```
5556

5657
List artifact digests and size using a --format

test/e2e/artifact_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ var _ = Describe("Podman artifact", func() {
7878
// Verify if the virtual size values are present in the output
7979
Expect(virtualSizes).To(ContainElement("4192"))
8080
Expect(virtualSizes).To(ContainElement("10240"))
81+
82+
// Check if .Created is reported and is not "<unknown>"
83+
createdFormatSession := podmanTest.PodmanExitCleanly("artifact", "ls", "--format", "{{.Created}}")
84+
createdTimes := createdFormatSession.OutputToStringArray()
85+
86+
// Should list 2 lines (without the header)
87+
Expect(createdTimes).To(HaveLen(2))
88+
89+
// Verify the created times are not "<unknown>" and end with " ago"
90+
for _, created := range createdTimes {
91+
Expect(created).ToNot(Equal("<unknown>"))
92+
Expect(created).To(HaveSuffix(" ago"))
93+
}
8194
})
8295

8396
It("podman artifact simple add", func() {

0 commit comments

Comments
 (0)