Browse Source

Merge pull request #9074 from ndeloof/down_volumes

only remove volumes set by compose file
Ulysses Souza 3 years ago
parent
commit
bfd7428619
3 changed files with 40 additions and 22 deletions
  1. 29 18
      pkg/compose/down.go
  2. 8 1
      pkg/compose/down_test.go
  3. 3 3
      pkg/e2e/volumes_test.go

+ 29 - 18
pkg/compose/down.go

@@ -51,7 +51,10 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
 	}
 
 	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 {
@@ -85,11 +88,7 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
 	}
 
 	if options.Volumes {
-		rm, err := s.ensureVolumesDown(ctx, projectName, w)
-		if err != nil {
-			return err
-		}
-		ops = append(ops, rm...)
+		ops = append(ops, s.ensureVolumesDown(ctx, options.Project, w)...)
 	}
 
 	if !resourceToRemove && len(ops) == 0 {
@@ -103,19 +102,15 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
 	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
-	volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
-	if err != nil {
-		return ops, err
-	}
-	for _, vol := range volumes.Volumes {
-		id := vol.Name
+	for _, vol := range project.Volumes {
+		volumeName := vol.Name
 		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 {
@@ -237,12 +232,13 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer
 	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{
 		Name: projectName,
 	}
 	if len(containers) == 0 {
-		return project
+		return project, nil
 	}
 	set := map[string]moby.Container{}
 	for _, c := range containers {
@@ -263,5 +259,20 @@ func (s *composeService) projectFromContainerLabels(containers Containers, proje
 		}
 		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
 }

+ 8 - 1
pkg/compose/down_test.go

@@ -44,6 +44,8 @@ func TestDown(t *testing.T) {
 			testContainer("service2", "789", false),
 			testContainer("service_orphan", "321", true),
 		}, 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(), "456", nil).Return(nil)
@@ -74,6 +76,8 @@ func TestDownRemoveOrphans(t *testing.T) {
 			testContainer("service2", "789", false),
 			testContainer("service_orphan", "321", true),
 		}, 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(), "789", nil).Return(nil)
@@ -100,13 +104,16 @@ func TestDownRemoveVolumes(t *testing.T) {
 
 	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
 		[]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().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().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)
 
 	err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Volumes: true})

+ 3 - 3
pkg/e2e/volumes_test.go

@@ -83,8 +83,8 @@ func TestLocalComposeVolume(t *testing.T) {
 
 	t.Run("cleanup volume project", func(t *testing.T) {
 		c.RunDockerComposeCmd("--project-name", projectName, "down", "--volumes")
-		res := c.RunDockerCmd("volume", "ls")
-		assert.Assert(t, !strings.Contains(res.Stdout(), projectName+"_staticVol"))
-		assert.Assert(t, !strings.Contains(res.Stdout(), "myvolume"))
+		ls := c.RunDockerCmd("volume", "ls").Stdout()
+		assert.Assert(t, !strings.Contains(ls, projectName+"_staticVol"))
+		assert.Assert(t, !strings.Contains(ls, "myvolume"))
 	})
 }