mirror of
https://github.com/docker/compose.git
synced 2025-07-25 22:54:54 +02:00
kill only need project name
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
6ce57ea2f4
commit
cd8074d501
@ -19,25 +19,44 @@ package compose
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type killOptions struct {
|
||||||
|
*projectOptions
|
||||||
|
signal string
|
||||||
|
}
|
||||||
|
|
||||||
func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||||
var opts api.KillOptions
|
opts := killOptions{
|
||||||
|
projectOptions: p,
|
||||||
|
}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "kill [options] [SERVICE...]",
|
Use: "kill [options] [SERVICE...]",
|
||||||
Short: "Force stop service containers.",
|
Short: "Force stop service containers.",
|
||||||
RunE: p.WithProject(func(ctx context.Context, project *types.Project) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return backend.Kill(ctx, project, opts)
|
return runKill(ctx, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: serviceCompletion(p),
|
ValidArgsFunction: serviceCompletion(p),
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
flags.StringVarP(&opts.Signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
|
flags.StringVarP(&opts.signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
|
||||||
|
projectName, err := opts.toProjectName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend.Kill(ctx, projectName, api.KillOptions{
|
||||||
|
Services: services,
|
||||||
|
Signal: opts.signal,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -54,7 +54,7 @@ type Service interface {
|
|||||||
// Convert translate compose model into backend's native format
|
// Convert translate compose model into backend's native format
|
||||||
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
||||||
// Kill executes the equivalent to a `compose kill`
|
// Kill executes the equivalent to a `compose kill`
|
||||||
Kill(ctx context.Context, project *types.Project, options KillOptions) error
|
Kill(ctx context.Context, project string, options KillOptions) error
|
||||||
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
||||||
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
||||||
// Remove executes the equivalent to a `compose rm`
|
// Remove executes the equivalent to a `compose rm`
|
||||||
|
@ -37,7 +37,7 @@ type ServiceProxy struct {
|
|||||||
PsFn func(ctx context.Context, projectName string, options PsOptions) ([]ContainerSummary, error)
|
PsFn func(ctx context.Context, projectName string, options PsOptions) ([]ContainerSummary, error)
|
||||||
ListFn func(ctx context.Context, options ListOptions) ([]Stack, error)
|
ListFn func(ctx context.Context, options ListOptions) ([]Stack, error)
|
||||||
ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
||||||
KillFn func(ctx context.Context, project *types.Project, options KillOptions) error
|
KillFn func(ctx context.Context, project string, options KillOptions) error
|
||||||
RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
||||||
RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
|
RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
|
||||||
ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
|
ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
|
||||||
@ -219,13 +219,10 @@ func (s *ServiceProxy) Convert(ctx context.Context, project *types.Project, opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Kill implements Service interface
|
// Kill implements Service interface
|
||||||
func (s *ServiceProxy) Kill(ctx context.Context, project *types.Project, options KillOptions) error {
|
func (s *ServiceProxy) Kill(ctx context.Context, project string, options KillOptions) error {
|
||||||
if s.KillFn == nil {
|
if s.KillFn == nil {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
for _, i := range s.interceptors {
|
|
||||||
i(ctx, project)
|
|
||||||
}
|
|
||||||
return s.KillFn(ctx, project, options)
|
return s.KillFn(ctx, project, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
|
||||||
moby "github.com/docker/docker/api/types"
|
moby "github.com/docker/docker/api/types"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
@ -27,29 +27,29 @@ import (
|
|||||||
"github.com/docker/compose/v2/pkg/progress"
|
"github.com/docker/compose/v2/pkg/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *composeService) Kill(ctx context.Context, project *types.Project, options api.KillOptions) error {
|
func (s *composeService) Kill(ctx context.Context, project string, options api.KillOptions) error {
|
||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
return s.kill(ctx, project, options)
|
return s.kill(ctx, project, options)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) kill(ctx context.Context, project *types.Project, options api.KillOptions) error {
|
func (s *composeService) kill(ctx context.Context, project string, options api.KillOptions) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
|
|
||||||
services := options.Services
|
services := options.Services
|
||||||
if len(services) == 0 {
|
|
||||||
services = project.ServiceNames()
|
|
||||||
}
|
|
||||||
|
|
||||||
var containers Containers
|
var containers Containers
|
||||||
containers, err := s.getContainers(ctx, project.Name, oneOffInclude, false, services...)
|
containers, err := s.getContainers(ctx, project, oneOffInclude, false, services...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(containers) == 0 {
|
||||||
|
fmt.Fprintf(s.stderr(), "no container to kill")
|
||||||
|
}
|
||||||
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
containers.
|
containers.
|
||||||
filter(isService(project.ServiceNames()...)).
|
|
||||||
forEach(func(container moby.Container) {
|
forEach(func(container moby.Container) {
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
eventName := getContainerProgressName(container)
|
eventName := getContainerProgressName(container)
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
|
||||||
moby "github.com/docker/docker/api/types"
|
moby "github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@ -45,18 +44,18 @@ func TestKillAll(t *testing.T) {
|
|||||||
tested.dockerCli = cli
|
tested.dockerCli = cli
|
||||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||||
|
|
||||||
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{testService("service1"), testService("service2")}}
|
name := strings.ToLower(testProject)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{
|
api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
Filters: filters.NewArgs(projectFilter(name)),
|
||||||
}).Return(
|
}).Return(
|
||||||
[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil)
|
[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil)
|
||||||
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil)
|
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil)
|
||||||
api.EXPECT().ContainerKill(anyCancellableContext(), "456", "").Return(nil)
|
api.EXPECT().ContainerKill(anyCancellableContext(), "456", "").Return(nil)
|
||||||
api.EXPECT().ContainerKill(anyCancellableContext(), "789", "").Return(nil)
|
api.EXPECT().ContainerKill(anyCancellableContext(), "789", "").Return(nil)
|
||||||
|
|
||||||
err := tested.kill(ctx, &project, compose.KillOptions{})
|
err := tested.kill(ctx, name, compose.KillOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,23 +69,19 @@ func TestKillSignal(t *testing.T) {
|
|||||||
tested.dockerCli = cli
|
tested.dockerCli = cli
|
||||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||||
|
|
||||||
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{testService(serviceName)}}
|
name := strings.ToLower(testProject)
|
||||||
listOptions := moby.ContainerListOptions{
|
listOptions := moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)), serviceFilter(serviceName)),
|
Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName)),
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
api.EXPECT().ContainerList(ctx, listOptions).Return([]moby.Container{testContainer(serviceName, "123", false)}, nil)
|
api.EXPECT().ContainerList(ctx, listOptions).Return([]moby.Container{testContainer(serviceName, "123", false)}, nil)
|
||||||
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil)
|
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil)
|
||||||
|
|
||||||
err := tested.kill(ctx, &project, compose.KillOptions{Services: []string{serviceName}, Signal: "SIGTERM"})
|
err := tested.kill(ctx, name, compose.KillOptions{Services: []string{serviceName}, Signal: "SIGTERM"})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testService(name string) types.ServiceConfig {
|
|
||||||
return types.ServiceConfig{Name: name}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testContainer(service string, id string, oneOff bool) moby.Container {
|
func testContainer(service string, id string, oneOff bool) moby.Container {
|
||||||
return moby.Container{
|
return moby.Container{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
@ -60,7 +60,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
go func() {
|
go func() {
|
||||||
<-signalChan
|
<-signalChan
|
||||||
s.Kill(ctx, project, api.KillOptions{ // nolint:errcheck
|
s.Kill(ctx, project.Name, api.KillOptions{ // nolint:errcheck
|
||||||
Services: options.Create.Services,
|
Services: options.Create.Services,
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user