artifact: added CREATED column to artifact ls

Fixes: #27314

Signed-off-by: Volodymyr Pankin <volopank@gmail.com>
This commit is contained in:
Volodymyr Pankin
2025-10-19 18:53:07 +02:00
parent f2a559a8fe
commit 538229da90
3 changed files with 35 additions and 9 deletions

View File

@@ -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",
})

View File

@@ -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

View File

@@ -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() {