add service filter to volumes command

Signed-off-by: Leonardo Peregrino <55335068+leoperegrino@users.noreply.github.com>
This commit is contained in:
Leonardo Peregrino 2025-06-18 00:25:07 -03:00 committed by Nicolas De loof
parent 5430caa172
commit 3a7982fe45
3 changed files with 65 additions and 7 deletions

View File

@ -19,6 +19,7 @@ package compose
import ( import (
"context" "context"
"fmt" "fmt"
"slices"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/cli/command/formatter"
@ -39,13 +40,12 @@ func volumesCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
} }
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "volumes [OPTIONS]", Use: "volumes [OPTIONS] [SERVICE...]",
Short: "List volumes", Short: "List volumes",
RunE: Adapt(func(ctx context.Context, args []string) error { RunE: Adapt(func(ctx context.Context, args []string) error {
return runVol(ctx, dockerCli, backend, options) return runVol(ctx, dockerCli, backend, args, options)
}), }),
Args: cobra.NoArgs, ValidArgsFunction: completeServiceNames(dockerCli, p),
ValidArgsFunction: noCompletion(),
} }
cmd.Flags().BoolVarP(&options.Quiet, "quiet", "q", false, "Only display volume names") cmd.Flags().BoolVarP(&options.Quiet, "quiet", "q", false, "Only display volume names")
@ -54,13 +54,26 @@ func volumesCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
return cmd return cmd
} }
func runVol(ctx context.Context, dockerCli command.Cli, backend api.Service, options volumesOptions) error { func runVol(ctx context.Context, dockerCli command.Cli, backend api.Service, services []string, options volumesOptions) error {
project, _, err := options.projectOrName(ctx, dockerCli, []string{}...) project, _, err := options.projectOrName(ctx, dockerCli, services...)
if err != nil { if err != nil {
return err return err
} }
names := project.ServiceNames()
if len(services) == 0 {
services = names
}
for _, service := range services {
if !slices.Contains(names, service) {
return fmt.Errorf("no such service: %s", service)
}
}
volumes, err := backend.Volumes(ctx, project, api.VolumesOptions{ volumes, err := backend.Volumes(ctx, project, api.VolumesOptions{
Services: services,
}) })
if err != nil { if err != nil {
return err return err

View File

@ -104,6 +104,7 @@ type Service interface {
} }
type VolumesOptions struct { type VolumesOptions struct {
Services []string
} }
type VolumesSummary = *volume.Volume type VolumesSummary = *volume.Volume

View File

@ -18,7 +18,9 @@ package compose
import ( import (
"context" "context"
"slices"
"github.com/docker/docker/api/types/container"
"github.com/compose-spec/compose-go/v2/types" "github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/api"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
@ -29,6 +31,26 @@ func (s *composeService) Volumes( ctx context.Context, project *types.Project, o
projectName := project.Name projectName := project.Name
allContainers, err := s.apiClient().ContainerList(ctx, container.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)),
})
if err != nil {
return nil, err
}
var containers []container.Summary
if len(options.Services) > 0 {
// filter service containers
for _, c := range allContainers {
if slices.Contains(options.Services, c.Labels[api.ServiceLabel]) {
containers = append(containers, c)
}
}
} else {
containers = allContainers
}
volumesResponse, err := s.apiClient().VolumeList(ctx, volume.ListOptions{ volumesResponse, err := s.apiClient().VolumeList(ctx, volume.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)), Filters: filters.NewArgs(projectFilter(projectName)),
}) })
@ -38,5 +60,27 @@ func (s *composeService) Volumes( ctx context.Context, project *types.Project, o
projectVolumes := volumesResponse.Volumes projectVolumes := volumesResponse.Volumes
return projectVolumes, nil if len(options.Services) == 0 {
return projectVolumes, nil
}
var volumes []api.VolumesSummary
// create a name lookup of volumes used by containers
serviceVolumes := make(map[string]bool)
for _, container := range containers {
for _, mount := range container.Mounts {
serviceVolumes[mount.Name] = true
}
}
// append if volumes in this project are in serviceVolumes
for _, v := range projectVolumes {
if serviceVolumes[v.Name] {
volumes = append(volumes, v)
}
}
return volumes, nil
} }