mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
chore(images): filter images by name with wildcard pattern using Docker filter
This commit is contained in:
+7
-37
@@ -29,7 +29,7 @@ func NewListCommand() *cobra.Command {
|
||||
opts := listOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ls [IMAGE]",
|
||||
Use: "ls [REPO:[TAG]]",
|
||||
Aliases: []string{"list"},
|
||||
Short: "List images on machines in the cluster.",
|
||||
Long: "List images on machines in the cluster. By default, on all machines. Optionally filter by image name.",
|
||||
@@ -45,8 +45,8 @@ func NewListCommand() *cobra.Command {
|
||||
# List images filtered by name (with any tag) on all machines.
|
||||
uc image ls myapp
|
||||
|
||||
# List images filtered by name and tag on specific machine.
|
||||
uc image ls myapp:1.2.3 -m machine1`,
|
||||
# List images filtered by name pattern on specific machine.
|
||||
uc image ls "myapp:1.*" -m machine1`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) > 0 {
|
||||
@@ -102,7 +102,10 @@ func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
|
||||
|
||||
machines := cli.ExpandCommaSeparatedValues(opts.machines)
|
||||
|
||||
clusterImages, err := clusterClient.ListImages(ctx, api.ImageFilter{Machines: machines})
|
||||
clusterImages, err := clusterClient.ListImages(ctx, api.ImageFilter{
|
||||
Machines: machines,
|
||||
Name: opts.nameFilter,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("list images: %w", err)
|
||||
}
|
||||
@@ -156,8 +159,6 @@ func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
rows = filterImagesByName(rows, opts.nameFilter)
|
||||
|
||||
if len(rows) == 0 {
|
||||
if opts.nameFilter != "" {
|
||||
fmt.Printf("No images matching '%s' found.\n", opts.nameFilter)
|
||||
@@ -181,37 +182,6 @@ func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// filterImagesByName filters the image rows by image name. It matches any tag of the image if only the name
|
||||
// is provided. For example, if filter is "nginx", it matches "nginx", "nginx:latest", "nginx:1.25", etc.
|
||||
// If filter is "nginx:latest", it matches only "nginx:latest".
|
||||
func filterImagesByName(rows []imageRow, nameFilter string) []imageRow {
|
||||
if nameFilter == "" {
|
||||
return rows
|
||||
}
|
||||
|
||||
var filteredRows []imageRow
|
||||
for _, row := range rows {
|
||||
if row.name == "<none>" {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(nameFilter, ":") {
|
||||
// Exact match if filter contains a tag.
|
||||
if row.name == nameFilter {
|
||||
filteredRows = append(filteredRows, row)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Match by name prefix if filter does not contain a tag.
|
||||
if strings.HasPrefix(row.name, nameFilter) &&
|
||||
len(row.name) > len(nameFilter) && row.name[len(nameFilter)] == ':' {
|
||||
filteredRows = append(filteredRows, row)
|
||||
}
|
||||
}
|
||||
return filteredRows
|
||||
}
|
||||
|
||||
// imagePlatforms returns a list of platforms supported by the image and a boolean indicating if it's multi-platform.
|
||||
func imagePlatforms(img image.Summary) ([]string, bool) {
|
||||
var formattedPlatforms []string
|
||||
|
||||
@@ -28,6 +28,9 @@ type ImageFilter struct {
|
||||
// Machines filters images to those present on the specified machines (names or IDs).
|
||||
// If empty, it matches images on all machines.
|
||||
Machines []string
|
||||
// Name filters images by name (with or without tag). Accepts a wildcard pattern.
|
||||
// If empty, it matches all image names.
|
||||
Name string
|
||||
}
|
||||
|
||||
// MachineRemoteImage represents an image in a remote registry fetched by a particular machine.
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
@@ -52,6 +53,12 @@ func (cli *Client) ListImages(ctx context.Context, filter api.ImageFilter) ([]ap
|
||||
}
|
||||
|
||||
opts := image.ListOptions{Manifests: true}
|
||||
if filter.Name != "" {
|
||||
opts.Filters = filters.NewArgs(
|
||||
filters.Arg("reference", filter.Name),
|
||||
)
|
||||
}
|
||||
|
||||
optsBytes, err := json.Marshal(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal options: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user