mirror of https://github.com/docker/compose.git
only remove volumes set by compose file
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
9f06a02eb5
commit
feba34e406
|
@ -51,7 +51,10 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Project == nil {
|
if options.Project == nil {
|
||||||
options.Project = s.projectFromContainerLabels(containers.filter(isNotOneOff), projectName)
|
options.Project, err = s.projectFromLabels(ctx, containers.filter(isNotOneOff), projectName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(containers) > 0 {
|
if len(containers) > 0 {
|
||||||
|
@ -85,11 +88,7 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Volumes {
|
if options.Volumes {
|
||||||
rm, err := s.ensureVolumesDown(ctx, projectName, w)
|
ops = append(ops, s.ensureVolumesDown(ctx, options.Project, w)...)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ops = append(ops, rm...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !resourceToRemove && len(ops) == 0 {
|
if !resourceToRemove && len(ops) == 0 {
|
||||||
|
@ -103,19 +102,15 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) ensureVolumesDown(ctx context.Context, projectName string, w progress.Writer) ([]downOp, error) {
|
func (s *composeService) ensureVolumesDown(ctx context.Context, project *types.Project, w progress.Writer) []downOp {
|
||||||
var ops []downOp
|
var ops []downOp
|
||||||
volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
|
for _, vol := range project.Volumes {
|
||||||
if err != nil {
|
volumeName := vol.Name
|
||||||
return ops, err
|
|
||||||
}
|
|
||||||
for _, vol := range volumes.Volumes {
|
|
||||||
id := vol.Name
|
|
||||||
ops = append(ops, func() error {
|
ops = append(ops, func() error {
|
||||||
return s.removeVolume(ctx, id, w)
|
return s.removeVolume(ctx, volumeName, w)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return ops, nil
|
return ops
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) ensureImagesDown(ctx context.Context, projectName string, options api.DownOptions, w progress.Writer) []downOp {
|
func (s *composeService) ensureImagesDown(ctx context.Context, projectName string, options api.DownOptions, w progress.Writer) []downOp {
|
||||||
|
@ -237,12 +232,13 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) projectFromContainerLabels(containers Containers, projectName string) *types.Project {
|
// projectFromLabels builds a types.Project based on actual resources with compose labels set
|
||||||
|
func (s *composeService) projectFromLabels(ctx context.Context, containers Containers, projectName string) (*types.Project, error) {
|
||||||
project := &types.Project{
|
project := &types.Project{
|
||||||
Name: projectName,
|
Name: projectName,
|
||||||
}
|
}
|
||||||
if len(containers) == 0 {
|
if len(containers) == 0 {
|
||||||
return project
|
return project, nil
|
||||||
}
|
}
|
||||||
set := map[string]moby.Container{}
|
set := map[string]moby.Container{}
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
|
@ -263,5 +259,20 @@ func (s *composeService) projectFromContainerLabels(containers Containers, proje
|
||||||
}
|
}
|
||||||
project.Services = append(project.Services, service)
|
project.Services = append(project.Services, service)
|
||||||
}
|
}
|
||||||
return project
|
|
||||||
|
volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
project.Volumes = types.Volumes{}
|
||||||
|
for _, vol := range volumes.Volumes {
|
||||||
|
project.Volumes[vol.Labels[api.VolumeLabel]] = types.VolumeConfig{
|
||||||
|
Name: vol.Name,
|
||||||
|
Driver: vol.Driver,
|
||||||
|
Labels: vol.Labels,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return project, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ func TestDown(t *testing.T) {
|
||||||
testContainer("service2", "789", false),
|
testContainer("service2", "789", false),
|
||||||
testContainer("service_orphan", "321", true),
|
testContainer("service_orphan", "321", true),
|
||||||
}, nil)
|
}, nil)
|
||||||
|
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||||
|
Return(volume.VolumeListOKBody{}, nil)
|
||||||
|
|
||||||
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
||||||
api.EXPECT().ContainerStop(gomock.Any(), "456", nil).Return(nil)
|
api.EXPECT().ContainerStop(gomock.Any(), "456", nil).Return(nil)
|
||||||
|
@ -74,6 +76,8 @@ func TestDownRemoveOrphans(t *testing.T) {
|
||||||
testContainer("service2", "789", false),
|
testContainer("service2", "789", false),
|
||||||
testContainer("service_orphan", "321", true),
|
testContainer("service_orphan", "321", true),
|
||||||
}, nil)
|
}, nil)
|
||||||
|
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||||
|
Return(volume.VolumeListOKBody{}, nil)
|
||||||
|
|
||||||
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
||||||
api.EXPECT().ContainerStop(gomock.Any(), "789", nil).Return(nil)
|
api.EXPECT().ContainerStop(gomock.Any(), "789", nil).Return(nil)
|
||||||
|
@ -100,13 +104,16 @@ func TestDownRemoveVolumes(t *testing.T) {
|
||||||
|
|
||||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||||
[]moby.Container{testContainer("service1", "123", false)}, nil)
|
[]moby.Container{testContainer("service1", "123", false)}, nil)
|
||||||
|
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
|
||||||
|
Return(volume.VolumeListOKBody{
|
||||||
|
Volumes: []*moby.Volume{{Name: "myProject_volume"}},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
api.EXPECT().ContainerStop(gomock.Any(), "123", nil).Return(nil)
|
||||||
api.EXPECT().ContainerRemove(gomock.Any(), "123", moby.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).Return(nil)
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", moby.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).Return(nil)
|
||||||
|
|
||||||
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).Return(nil, nil)
|
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).Return(nil, nil)
|
||||||
|
|
||||||
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).Return(volume.VolumeListOKBody{Volumes: []*moby.Volume{{Name: "myProject_volume"}}}, nil)
|
|
||||||
api.EXPECT().VolumeRemove(gomock.Any(), "myProject_volume", true).Return(nil)
|
api.EXPECT().VolumeRemove(gomock.Any(), "myProject_volume", true).Return(nil)
|
||||||
|
|
||||||
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Volumes: true})
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Volumes: true})
|
||||||
|
|
|
@ -83,8 +83,8 @@ func TestLocalComposeVolume(t *testing.T) {
|
||||||
|
|
||||||
t.Run("cleanup volume project", func(t *testing.T) {
|
t.Run("cleanup volume project", func(t *testing.T) {
|
||||||
c.RunDockerComposeCmd("--project-name", projectName, "down", "--volumes")
|
c.RunDockerComposeCmd("--project-name", projectName, "down", "--volumes")
|
||||||
res := c.RunDockerCmd("volume", "ls")
|
ls := c.RunDockerCmd("volume", "ls").Stdout()
|
||||||
assert.Assert(t, !strings.Contains(res.Stdout(), projectName+"_staticVol"))
|
assert.Assert(t, !strings.Contains(ls, projectName+"_staticVol"))
|
||||||
assert.Assert(t, !strings.Contains(res.Stdout(), "myvolume"))
|
assert.Assert(t, !strings.Contains(ls, "myvolume"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue