144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package artifact
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/containers/common/pkg/completion"
|
|
"github.com/containers/common/pkg/report"
|
|
"github.com/containers/image/v5/docker/reference"
|
|
"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"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
listCmd = &cobra.Command{
|
|
Use: "ls [options]",
|
|
Aliases: []string{"list"},
|
|
Short: "List OCI artifacts",
|
|
Long: "List OCI artifacts in local store",
|
|
RunE: list,
|
|
Args: validate.NoArgs,
|
|
ValidArgsFunction: completion.AutocompleteNone,
|
|
Example: `podman artifact ls`,
|
|
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
|
|
}
|
|
listFlag = listFlagType{}
|
|
)
|
|
|
|
type listFlagType struct {
|
|
format string
|
|
noHeading bool
|
|
noTrunc bool
|
|
}
|
|
|
|
type artifactListOutput struct {
|
|
Digest string
|
|
Repository string
|
|
Size string
|
|
Tag string
|
|
}
|
|
|
|
var (
|
|
defaultArtifactListOutputFormat = "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.Size}}\n{{end -}}"
|
|
)
|
|
|
|
func init() {
|
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
|
Command: listCmd,
|
|
Parent: artifactCmd,
|
|
})
|
|
flags := listCmd.Flags()
|
|
formatFlagName := "format"
|
|
flags.StringVar(&listFlag.format, formatFlagName, defaultArtifactListOutputFormat, "Format volume output using JSON or a Go template")
|
|
_ = listCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&artifactListOutput{}))
|
|
flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print column headings")
|
|
flags.BoolVar(&listFlag.noTrunc, "no-trunc", false, "Do not truncate output")
|
|
}
|
|
|
|
func list(cmd *cobra.Command, _ []string) error {
|
|
reports, err := registry.ImageEngine().ArtifactList(registry.Context(), entities.ArtifactListOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return outputTemplate(cmd, reports)
|
|
}
|
|
|
|
func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) error {
|
|
var err error
|
|
artifacts := make([]artifactListOutput, 0)
|
|
for _, lr := range lrs {
|
|
var (
|
|
tag string
|
|
)
|
|
artifactName, err := lr.Artifact.GetName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
repo, err := reference.Parse(artifactName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
named, ok := repo.(reference.Named)
|
|
if !ok {
|
|
return fmt.Errorf("%q is an invalid artifact name", artifactName)
|
|
}
|
|
if tagged, ok := named.(reference.Tagged); ok {
|
|
tag = tagged.Tag()
|
|
}
|
|
|
|
// Note: Right now we only support things that are single manifests
|
|
// We should certainly expand this support for things like arch, etc
|
|
// as we move on
|
|
artifactDigest, err := lr.Artifact.GetDigest()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
artifactHash := artifactDigest.Encoded()[0:12]
|
|
// If the user does not want truncated hashes
|
|
if listFlag.noTrunc {
|
|
artifactHash = artifactDigest.Encoded()
|
|
}
|
|
|
|
artifacts = append(artifacts, artifactListOutput{
|
|
Digest: artifactHash,
|
|
Repository: named.Name(),
|
|
Size: units.HumanSize(float64(lr.Artifact.TotalSizeBytes())),
|
|
Tag: tag,
|
|
})
|
|
}
|
|
|
|
headers := report.Headers(artifactListOutput{}, map[string]string{
|
|
"REPOSITORY": "REPOSITORY",
|
|
"Tag": "TAG",
|
|
"Size": "SIZE",
|
|
"Digest": "DIGEST",
|
|
})
|
|
|
|
rpt := report.New(os.Stdout, cmd.Name())
|
|
defer rpt.Flush()
|
|
|
|
switch {
|
|
case cmd.Flag("format").Changed:
|
|
rpt, err = rpt.Parse(report.OriginUser, listFlag.format)
|
|
default:
|
|
rpt, err = rpt.Parse(report.OriginPodman, listFlag.format)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rpt.RenderHeaders && !listFlag.noHeading {
|
|
if err := rpt.Execute(headers); err != nil {
|
|
return fmt.Errorf("failed to write report column headers: %w", err)
|
|
}
|
|
}
|
|
return rpt.Execute(artifacts)
|
|
}
|