Skip to content

Commit 628417f

Browse files
authored
Merge pull request docker-archive#1225 from docker/kill
Add kill command
2 parents 8750d05 + 0aa3f4a commit 628417f

File tree

12 files changed

+173
-2
lines changed

12 files changed

+173
-2
lines changed

aci/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ func (cs *aciComposeService) Convert(ctx context.Context, project *types.Project
203203
return nil, errdefs.ErrNotImplemented
204204
}
205205

206+
func (cs *aciComposeService) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
207+
return errdefs.ErrNotImplemented
208+
}
209+
206210
func (cs *aciComposeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
207211
return errdefs.ErrNotImplemented
208212
}

api/client/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ func (c *composeService) Convert(context.Context, *types.Project, compose.Conver
7676
return nil, errdefs.ErrNotImplemented
7777
}
7878

79+
func (c *composeService) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
80+
return errdefs.ErrNotImplemented
81+
}
82+
7983
func (c *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
8084
return errdefs.ErrNotImplemented
8185
}

api/compose/api.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ type Service interface {
4949
List(ctx context.Context) ([]Stack, error)
5050
// Convert translate compose model into backend's native format
5151
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
52+
// Kill executes the equivalent to a `compose kill`
53+
Kill(ctx context.Context, project *types.Project, options KillOptions) error
5254
// RunOneOffContainer creates a service oneoff container and starts its dependencies
5355
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) error
5456
}
@@ -81,6 +83,12 @@ type ConvertOptions struct {
8183
Format string
8284
}
8385

86+
// KillOptions group options of the Kill API
87+
type KillOptions struct {
88+
// Signal to send to containers
89+
Signal string
90+
}
91+
8492
// RunOptions options to execute compose run
8593
type RunOptions struct {
8694
Service string

api/progress/event.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,26 @@ func CreatedEvent(ID string) Event {
7878
return NewEvent(ID, Done, "Created")
7979
}
8080

81-
// StoppingEvent stops a new Stopping in progress Event
81+
// StoppingEvent creates a new Stopping in progress Event
8282
func StoppingEvent(ID string) Event {
8383
return NewEvent(ID, Working, "Stopping")
8484
}
8585

86-
// StoppedEvent stops a new Stopping in progress Event
86+
// StoppedEvent creates a new Stopping in progress Event
8787
func StoppedEvent(ID string) Event {
8888
return NewEvent(ID, Done, "Stopped")
8989
}
9090

91+
// KillingEvent creates a new Killing in progress Event
92+
func KillingEvent(ID string) Event {
93+
return NewEvent(ID, Working, "Killing")
94+
}
95+
96+
// KilledEvent creates a new Killed in progress Event
97+
func KilledEvent(ID string) Event {
98+
return NewEvent(ID, Done, "Killed")
99+
}
100+
91101
// RemovingEvent creates a new Removing in progress Event
92102
func RemovingEvent(ID string) Event {
93103
return NewEvent(ID, Working, "Removing")

cli/cmd/compose/compose.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ func Command(contextType string) *cobra.Command {
113113
listCommand(),
114114
logsCommand(&opts, contextType),
115115
convertCommand(&opts),
116+
killCommand(&opts),
116117
runCommand(&opts),
117118
)
118119

cli/cmd/compose/kill.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"context"
21+
22+
"github.com/spf13/cobra"
23+
24+
"github.com/docker/compose-cli/api/client"
25+
"github.com/docker/compose-cli/api/compose"
26+
)
27+
28+
type killOptions struct {
29+
*projectOptions
30+
Signal string
31+
}
32+
33+
func killCommand(p *projectOptions) *cobra.Command {
34+
opts := killOptions{
35+
projectOptions: p,
36+
}
37+
cmd := &cobra.Command{
38+
Use: "kill [options] [SERVICE...]",
39+
Short: "Force stop service containers.",
40+
RunE: func(cmd *cobra.Command, args []string) error {
41+
return runKill(cmd.Context(), opts, args)
42+
},
43+
}
44+
45+
flags := cmd.Flags()
46+
flags.StringVarP(&opts.Signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
47+
48+
return cmd
49+
}
50+
51+
func runKill(ctx context.Context, opts killOptions, services []string) error {
52+
c, err := client.NewWithDefaultLocalBackend(ctx)
53+
if err != nil {
54+
return err
55+
}
56+
project, err := opts.toProject(services)
57+
if err != nil {
58+
return err
59+
}
60+
return c.ComposeService().Kill(ctx, project, compose.KillOptions{
61+
Signal: opts.Signal,
62+
})
63+
}

ecs/cloudformation.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"github.com/docker/compose-cli/api/compose"
2727
"github.com/docker/compose-cli/api/config"
28+
"github.com/docker/compose-cli/api/errdefs"
2829

2930
ecsapi "github.com/aws/aws-sdk-go/service/ecs"
3031
"github.com/aws/aws-sdk-go/service/elbv2"
@@ -46,6 +47,10 @@ import (
4647
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
4748
)
4849

50+
func (b *ecsAPIService) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
51+
return errdefs.ErrNotImplemented
52+
}
53+
4954
func (b *ecsAPIService) Convert(ctx context.Context, project *types.Project, options compose.ConvertOptions) ([]byte, error) {
5055
err := b.resolveServiceImagesDigests(ctx, project)
5156
if err != nil {

ecs/local/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func (e ecsLocalSimulation) Up(ctx context.Context, project *types.Project, opti
6565
return errdefs.ErrNotImplemented
6666
}
6767

68+
func (e ecsLocalSimulation) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
69+
return e.compose.Kill(ctx, project, options)
70+
}
71+
6872
func (e ecsLocalSimulation) Convert(ctx context.Context, project *types.Project, options compose.ConvertOptions) ([]byte, error) {
6973
enhanced, err := e.enhanceForLocalSimulation(project)
7074
if err != nil {

kube/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func (s *composeService) Convert(ctx context.Context, project *types.Project, op
103103
return nil, errdefs.ErrNotImplemented
104104
}
105105

106+
func (s *composeService) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
107+
return errdefs.ErrNotImplemented
108+
}
109+
106110
// RunOneOffContainer creates a service oneoff container and starts its dependencies
107111
func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
108112
return errdefs.ErrNotImplemented

local/compose/containers.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,9 @@ func (containers Containers) names() []string {
7070
}
7171
return names
7272
}
73+
74+
func (containers Containers) forEach(fn func(moby.Container)) {
75+
for _, c := range containers {
76+
fn(c)
77+
}
78+
}

local/compose/kill.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"context"
21+
22+
"github.com/compose-spec/compose-go/types"
23+
moby "github.com/docker/docker/api/types"
24+
"github.com/docker/docker/api/types/filters"
25+
"golang.org/x/sync/errgroup"
26+
27+
"github.com/docker/compose-cli/api/compose"
28+
"github.com/docker/compose-cli/api/progress"
29+
)
30+
31+
func (s *composeService) Kill(ctx context.Context, project *types.Project, options compose.KillOptions) error {
32+
w := progress.ContextWriter(ctx)
33+
34+
var containers Containers
35+
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
36+
Filters: filters.NewArgs(projectFilter(project.Name)),
37+
All: true,
38+
})
39+
if err != nil {
40+
return err
41+
}
42+
43+
eg, ctx := errgroup.WithContext(ctx)
44+
containers.
45+
filter(isService(project.ServiceNames()...)).
46+
forEach(func(container moby.Container) {
47+
eg.Go(func() error {
48+
eventName := getContainerProgressName(container)
49+
w.Event(progress.KillingEvent(eventName))
50+
err := s.apiClient.ContainerKill(ctx, container.ID, options.Signal)
51+
if err != nil {
52+
w.Event(progress.ErrorMessageEvent(eventName, "Error while Killing"))
53+
return err
54+
}
55+
w.Event(progress.KilledEvent(eventName))
56+
return nil
57+
})
58+
})
59+
return eg.Wait()
60+
}

local/compose/stop.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ func (s *composeService) Stop(ctx context.Context, project *types.Project) error
3838
return err
3939
}
4040

41+
containers = containers.filter(isService(project.ServiceNames()...))
42+
4143
return InReverseDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
4244
return s.stopContainers(ctx, w, containers.filter(isService(service.Name)))
4345
})

0 commit comments

Comments
 (0)