volume ls command can run without a project

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2025-09-09 16:24:05 +02:00 committed by Nicolas De loof
parent 385b3f5c96
commit a473341058
5 changed files with 15 additions and 35 deletions

View File

@ -55,24 +55,21 @@ func volumesCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
}
func runVol(ctx context.Context, dockerCli command.Cli, backend api.Service, services []string, options volumesOptions) error {
project, _, err := options.projectOrName(ctx, dockerCli, services...)
project, name, err := options.projectOrName(ctx, dockerCli, services...)
if err != nil {
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)
if project != nil {
names := project.ServiceNames()
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, name, api.VolumesOptions{
Services: services,
})
if err != nil {

View File

@ -101,7 +101,7 @@ type Service interface {
// Generate generates a Compose Project from existing containers
Generate(ctx context.Context, options GenerateOptions) (*types.Project, error)
// Volumes executes the equivalent to a `docker volume ls`
Volumes(ctx context.Context, project *types.Project, options VolumesOptions) ([]VolumesSummary, error)
Volumes(ctx context.Context, project string, options VolumesOptions) ([]VolumesSummary, error)
}
type VolumesOptions struct {

View File

@ -20,18 +20,15 @@ import (
"context"
"slices"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/volume"
)
func (s *composeService) Volumes(ctx context.Context, project *types.Project, options api.VolumesOptions) ([]api.VolumesSummary, error) {
projectName := project.Name
func (s *composeService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) {
allContainers, err := s.apiClient().ContainerList(ctx, container.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)),
Filters: filters.NewArgs(projectFilter(project)),
})
if err != nil {
return nil, err
@ -51,7 +48,7 @@ func (s *composeService) Volumes(ctx context.Context, project *types.Project, op
}
volumesResponse, err := s.apiClient().VolumeList(ctx, volume.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)),
Filters: filters.NewArgs(projectFilter(project)),
})
if err != nil {
return nil, err

View File

@ -20,7 +20,6 @@ import (
"context"
"testing"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
@ -59,7 +58,6 @@ func TestVolumes(t *testing.T) {
}
ctx := context.Background()
project := &types.Project{Name: testProject}
args := filters.NewArgs(projectFilter(testProject))
listOpts := container.ListOptions{Filters: args}
volumeListArgs := filters.NewArgs(projectFilter(testProject))
@ -75,14 +73,14 @@ func TestVolumes(t *testing.T) {
// Test without service filter - should return all project volumes
volumeOptions := api.VolumesOptions{}
volumes, err := tested.Volumes(ctx, project, volumeOptions)
volumes, err := tested.Volumes(ctx, testProject, volumeOptions)
expected := []api.VolumesSummary{vol1, vol2, vol3}
assert.NilError(t, err)
assert.DeepEqual(t, volumes, expected)
// Test with service filter - should only return volumes used by service1
volumeOptions = api.VolumesOptions{Services: []string{"service1"}}
volumes, err = tested.Volumes(ctx, project, volumeOptions)
volumes, err = tested.Volumes(ctx, testProject, volumeOptions)
expected = []api.VolumesSummary{vol1, vol2}
assert.NilError(t, err)
assert.DeepEqual(t, volumes, expected)

View File

@ -499,7 +499,7 @@ func (mr *MockServiceMockRecorder) Viz(ctx, project, options any) *gomock.Call {
}
// Volumes mocks base method.
func (m *MockService) Volumes(ctx context.Context, project *types.Project, options api.VolumesOptions) ([]api.VolumesSummary, error) {
func (m *MockService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Volumes", ctx, project, options)
ret0, _ := ret[0].([]api.VolumesSummary)
@ -589,18 +589,6 @@ func (mr *MockLogConsumerMockRecorder) Log(containerName, message any) *gomock.C
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Log", reflect.TypeOf((*MockLogConsumer)(nil).Log), containerName, message)
}
// Register mocks base method.
func (m *MockLogConsumer) Register(container string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Register", container)
}
// Register indicates an expected call of Register.
func (mr *MockLogConsumerMockRecorder) Register(container any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockLogConsumer)(nil).Register), container)
}
// Status mocks base method.
func (m *MockLogConsumer) Status(container, msg string) {
m.ctrl.T.Helper()