Apply compose model on `compose kill`, add `--remove-orphans`

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
Laura Brehm 2022-08-19 04:04:46 +02:00
parent 6fe34c45ca
commit fcfcc1524e
No known key found for this signature in database
GPG Key ID: 526E3FC49260D47A
4 changed files with 39 additions and 4 deletions

View File

@ -18,14 +18,17 @@ package compose
import (
"context"
"os"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/utils"
)
type killOptions struct {
*projectOptions
removeOrphans bool
signal string
}
@ -43,18 +46,22 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
}
flags := cmd.Flags()
removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
flags.StringVarP(&opts.signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
return cmd
}
func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
name, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}
return backend.Kill(ctx, name, api.KillOptions{
RemoveOrphans: opts.removeOrphans,
Project: project,
Services: services,
Signal: opts.signal,
})

View File

@ -197,6 +197,10 @@ type ImagesOptions struct {
// KillOptions group options of the Kill API
type KillOptions struct {
// RemoveOrphans will cleanup containers that are not declared on the compose model but own the same labels
RemoveOrphans bool
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
// Services passed in the command line to be killed
Services []string
// Signal to send to containers

View File

@ -45,6 +45,17 @@ func (s *composeService) kill(ctx context.Context, projectName string, options a
return err
}
project := options.Project
if project == nil {
project, err = s.getProjectWithResources(ctx, containers, projectName)
if err != nil {
return err
}
}
if !options.RemoveOrphans {
containers = containers.filter(isService(project.ServiceNames()...))
}
if len(containers) == 0 {
fmt.Fprintf(s.stderr(), "no container to kill")
}

View File

@ -25,6 +25,7 @@ import (
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/volume"
"github.com/golang/mock/gomock"
"gotest.tools/v3/assert"
@ -52,6 +53,12 @@ func TestKillAll(t *testing.T) {
Filters: filters.NewArgs(projectFilter(name)),
}).Return(
[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil)
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
Return(volume.VolumeListOKBody{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
{ID: "abc123", Name: "testProject_default"},
}, nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "456", "").Return(nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "789", "").Return(nil)
@ -77,6 +84,12 @@ func TestKillSignal(t *testing.T) {
ctx := context.Background()
api.EXPECT().ContainerList(ctx, listOptions).Return([]moby.Container{testContainer(serviceName, "123", false)}, nil)
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
Return(volume.VolumeListOKBody{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
{ID: "abc123", Name: "testProject_default"},
}, nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil)
err := tested.kill(ctx, name, compose.KillOptions{Services: []string{serviceName}, Signal: "SIGTERM"})