mirror of
https://github.com/docker/compose.git
synced 2025-07-23 05:34:36 +02:00
introduce --timeout on compose stop|down
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
de586871de
commit
0b517741a0
@ -64,7 +64,7 @@ func (cs *aciComposeService) Start(ctx context.Context, project *types.Project,
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *aciComposeService) Stop(ctx context.Context, project *types.Project) error {
|
func (cs *aciComposeService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ func (c *composeService) Start(ctx context.Context, project *types.Project, opti
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *composeService) Stop(ctx context.Context, project *types.Project) error {
|
func (c *composeService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package compose
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
)
|
)
|
||||||
@ -36,7 +37,7 @@ type Service interface {
|
|||||||
// Start executes the equivalent to a `compose start`
|
// Start executes the equivalent to a `compose start`
|
||||||
Start(ctx context.Context, project *types.Project, options StartOptions) error
|
Start(ctx context.Context, project *types.Project, options StartOptions) error
|
||||||
// Stop executes the equivalent to a `compose stop`
|
// Stop executes the equivalent to a `compose stop`
|
||||||
Stop(ctx context.Context, project *types.Project) error
|
Stop(ctx context.Context, project *types.Project, options StopOptions) error
|
||||||
// Up executes the equivalent to a `compose up`
|
// Up executes the equivalent to a `compose up`
|
||||||
Up(ctx context.Context, project *types.Project, options UpOptions) error
|
Up(ctx context.Context, project *types.Project, options UpOptions) error
|
||||||
// Down executes the equivalent to a `compose down`
|
// Down executes the equivalent to a `compose down`
|
||||||
@ -71,6 +72,12 @@ type StartOptions struct {
|
|||||||
Attach ContainerEventListener
|
Attach ContainerEventListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StopOptions group options of the Stop API
|
||||||
|
type StopOptions struct {
|
||||||
|
// Timeout override container stop timeout
|
||||||
|
Timeout *time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
// UpOptions group options of the Up API
|
// UpOptions group options of the Up API
|
||||||
type UpOptions struct {
|
type UpOptions struct {
|
||||||
// Detach will create services and return immediately
|
// Detach will create services and return immediately
|
||||||
@ -83,6 +90,8 @@ type DownOptions struct {
|
|||||||
RemoveOrphans bool
|
RemoveOrphans bool
|
||||||
// Project is the compose project used to define this app. Might be nil if user ran `down` just with project name
|
// Project is the compose project used to define this app. Might be nil if user ran `down` just with project name
|
||||||
Project *types.Project
|
Project *types.Project
|
||||||
|
// Timeout override container stop timeout
|
||||||
|
Timeout *time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertOptions group options of the Convert API
|
// ConvertOptions group options of the Convert API
|
||||||
|
@ -18,6 +18,7 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
|
||||||
@ -32,6 +33,8 @@ import (
|
|||||||
type downOptions struct {
|
type downOptions struct {
|
||||||
*projectOptions
|
*projectOptions
|
||||||
removeOrphans bool
|
removeOrphans bool
|
||||||
|
timeChanged bool
|
||||||
|
timeout int
|
||||||
}
|
}
|
||||||
|
|
||||||
func downCommand(p *projectOptions) *cobra.Command {
|
func downCommand(p *projectOptions) *cobra.Command {
|
||||||
@ -42,11 +45,13 @@ func downCommand(p *projectOptions) *cobra.Command {
|
|||||||
Use: "down",
|
Use: "down",
|
||||||
Short: "Stop and remove containers, networks",
|
Short: "Stop and remove containers, networks",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||||
return runDown(cmd.Context(), opts)
|
return runDown(cmd.Context(), opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
flags := downCmd.Flags()
|
flags := downCmd.Flags()
|
||||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
||||||
|
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||||
|
|
||||||
return downCmd
|
return downCmd
|
||||||
}
|
}
|
||||||
@ -69,9 +74,15 @@ func runDown(ctx context.Context, opts downOptions) error {
|
|||||||
name = p.Name
|
name = p.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var timeout *time.Duration
|
||||||
|
if opts.timeChanged {
|
||||||
|
timeoutValue := time.Duration(opts.timeout) * time.Second
|
||||||
|
timeout = &timeoutValue
|
||||||
|
}
|
||||||
return name, c.ComposeService().Down(ctx, name, compose.DownOptions{
|
return name, c.ComposeService().Down(ctx, name, compose.DownOptions{
|
||||||
RemoveOrphans: opts.removeOrphans,
|
RemoveOrphans: opts.removeOrphans,
|
||||||
Project: project,
|
Project: project,
|
||||||
|
Timeout: timeout,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
@ -73,7 +73,7 @@ func runRemove(ctx context.Context, opts removeOptions, services []string) error
|
|||||||
|
|
||||||
if opts.stop {
|
if opts.stop {
|
||||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
err := c.ComposeService().Stop(ctx, project)
|
err := c.ComposeService().Stop(ctx, project, compose.StopOptions{})
|
||||||
return "", err
|
return "", err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,29 +18,37 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/client"
|
"github.com/docker/compose-cli/api/client"
|
||||||
|
"github.com/docker/compose-cli/api/compose"
|
||||||
"github.com/docker/compose-cli/api/progress"
|
"github.com/docker/compose-cli/api/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stopOptions struct {
|
type stopOptions struct {
|
||||||
*projectOptions
|
*projectOptions
|
||||||
|
timeChanged bool
|
||||||
|
timeout int
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopCommand(p *projectOptions) *cobra.Command {
|
func stopCommand(p *projectOptions) *cobra.Command {
|
||||||
opts := stopOptions{
|
opts := stopOptions{
|
||||||
projectOptions: p,
|
projectOptions: p,
|
||||||
}
|
}
|
||||||
stopCmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "stop [SERVICE...]",
|
Use: "stop [SERVICE...]",
|
||||||
Short: "Stop services",
|
Short: "Stop services",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||||
return runStop(cmd.Context(), opts, args)
|
return runStop(cmd.Context(), opts, args)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return stopCmd
|
flags := cmd.Flags()
|
||||||
|
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runStop(ctx context.Context, opts stopOptions, services []string) error {
|
func runStop(ctx context.Context, opts stopOptions, services []string) error {
|
||||||
@ -54,8 +62,15 @@ func runStop(ctx context.Context, opts stopOptions, services []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var timeout *time.Duration
|
||||||
|
if opts.timeChanged {
|
||||||
|
timeoutValue := time.Duration(opts.timeout) * time.Second
|
||||||
|
timeout = &timeoutValue
|
||||||
|
}
|
||||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
return "", c.ComposeService().Stop(ctx, project)
|
return "", c.ComposeService().Stop(ctx, project, compose.StopOptions{
|
||||||
|
Timeout: timeout,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
|||||||
stopFunc := func() error {
|
stopFunc := func() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
return "", c.ComposeService().Stop(ctx, project)
|
return "", c.ComposeService().Stop(ctx, project, compose.StopOptions{})
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ func (e ecsLocalSimulation) Start(ctx context.Context, project *types.Project, o
|
|||||||
return e.compose.Start(ctx, project, options)
|
return e.compose.Start(ctx, project, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ecsLocalSimulation) Stop(ctx context.Context, project *types.Project) error {
|
func (e ecsLocalSimulation) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
return e.compose.Stop(ctx, project)
|
return e.compose.Stop(ctx, project, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ecsLocalSimulation) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
|
func (e ecsLocalSimulation) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
|
||||||
|
@ -51,7 +51,7 @@ func (b *ecsAPIService) Start(ctx context.Context, project *types.Project, optio
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) Stop(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func (s *composeService) Start(ctx context.Context, project *types.Project, opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop executes the equivalent to a `compose stop`
|
// Stop executes the equivalent to a `compose stop`
|
||||||
func (s *composeService) Stop(ctx context.Context, project *types.Project) error {
|
func (s *composeService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
|
|||||||
if len(orphans) > 0 {
|
if len(orphans) > 0 {
|
||||||
if opts.RemoveOrphans {
|
if opts.RemoveOrphans {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
err := s.removeContainers(ctx, w, orphans)
|
err := s.removeContainers(ctx, w, orphans, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/compose"
|
"github.com/docker/compose-cli/api/compose"
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ func (s *composeService) Down(ctx context.Context, projectName string, options c
|
|||||||
|
|
||||||
err = InReverseDependencyOrder(ctx, options.Project, func(c context.Context, service types.ServiceConfig) error {
|
err = InReverseDependencyOrder(ctx, options.Project, func(c context.Context, service types.ServiceConfig) error {
|
||||||
serviceContainers := containers.filter(isService(service.Name))
|
serviceContainers := containers.filter(isService(service.Name))
|
||||||
err := s.removeContainers(ctx, w, serviceContainers)
|
err := s.removeContainers(ctx, w, serviceContainers, options.Timeout)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -67,7 +68,7 @@ func (s *composeService) Down(ctx context.Context, projectName string, options c
|
|||||||
|
|
||||||
orphans := containers.filter(isNotService(options.Project.ServiceNames()...))
|
orphans := containers.filter(isNotService(options.Project.ServiceNames()...))
|
||||||
if options.RemoveOrphans && len(orphans) > 0 {
|
if options.RemoveOrphans && len(orphans) > 0 {
|
||||||
err := s.removeContainers(ctx, w, orphans)
|
err := s.removeContainers(ctx, w, orphans, options.Timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -93,12 +94,12 @@ func (s *composeService) Down(ctx context.Context, projectName string, options c
|
|||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) stopContainers(ctx context.Context, w progress.Writer, containers []moby.Container) error {
|
func (s *composeService) stopContainers(ctx context.Context, w progress.Writer, containers []moby.Container, timeout *time.Duration) error {
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
toStop := container
|
toStop := container
|
||||||
eventName := getContainerProgressName(toStop)
|
eventName := getContainerProgressName(toStop)
|
||||||
w.Event(progress.StoppingEvent(eventName))
|
w.Event(progress.StoppingEvent(eventName))
|
||||||
err := s.apiClient.ContainerStop(ctx, toStop.ID, nil)
|
err := s.apiClient.ContainerStop(ctx, toStop.ID, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
||||||
return err
|
return err
|
||||||
@ -108,14 +109,14 @@ func (s *composeService) stopContainers(ctx context.Context, w progress.Writer,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) removeContainers(ctx context.Context, w progress.Writer, containers []moby.Container) error {
|
func (s *composeService) removeContainers(ctx context.Context, w progress.Writer, containers []moby.Container, timeout *time.Duration) error {
|
||||||
eg, _ := errgroup.WithContext(ctx)
|
eg, _ := errgroup.WithContext(ctx)
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
toDelete := container
|
toDelete := container
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
eventName := getContainerProgressName(toDelete)
|
eventName := getContainerProgressName(toDelete)
|
||||||
w.Event(progress.StoppingEvent(eventName))
|
w.Event(progress.StoppingEvent(eventName))
|
||||||
err := s.stopContainers(ctx, w, []moby.Container{toDelete})
|
err := s.stopContainers(ctx, w, []moby.Container{toDelete}, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
||||||
return err
|
return err
|
||||||
|
@ -20,14 +20,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/docker/compose-cli/api/compose"
|
||||||
"gotest.tools/v3/assert"
|
"github.com/docker/compose-cli/local/mocks"
|
||||||
|
|
||||||
apitypes "github.com/docker/docker/api/types"
|
apitypes "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/docker/compose-cli/api/compose"
|
"gotest.tools/v3/assert"
|
||||||
"github.com/docker/compose-cli/local/mocks"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDown(t *testing.T) {
|
func TestDown(t *testing.T) {
|
||||||
|
@ -19,16 +19,16 @@ package compose
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/docker/compose-cli/api/compose"
|
||||||
|
"github.com/docker/compose-cli/api/progress"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"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/docker/compose-cli/api/progress"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *composeService) Stop(ctx context.Context, project *types.Project) error {
|
func (s *composeService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
|
|
||||||
var containers Containers
|
var containers Containers
|
||||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(projectFilter(project.Name)),
|
Filters: filters.NewArgs(projectFilter(project.Name)),
|
||||||
@ -41,6 +41,6 @@ func (s *composeService) Stop(ctx context.Context, project *types.Project) error
|
|||||||
containers = containers.filter(isService(project.ServiceNames()...))
|
containers = containers.filter(isService(project.ServiceNames()...))
|
||||||
|
|
||||||
return InReverseDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
return InReverseDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
||||||
return s.stopContainers(ctx, w, containers.filter(isService(service.Name)))
|
return s.stopContainers(ctx, w, containers.filter(isService(service.Name)), options.Timeout)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
62
local/compose/stop_test.go
Normal file
62
local/compose/stop_test.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/compose-cli/api/compose"
|
||||||
|
"github.com/docker/compose-cli/local/mocks"
|
||||||
|
moby "github.com/docker/docker/api/types"
|
||||||
|
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStopTimeout(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
api := mocks.NewMockAPIClient(mockCtrl)
|
||||||
|
tested.apiClient = api
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
api.EXPECT().ContainerList(ctx, projectFilterListOpt(testProject)).Return(
|
||||||
|
[]moby.Container{
|
||||||
|
testContainer("service1", "123"),
|
||||||
|
testContainer("service1", "456"),
|
||||||
|
testContainer("service2", "789"),
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
timeout := time.Duration(2) * time.Second
|
||||||
|
api.EXPECT().ContainerStop(ctx, "123", &timeout).Return(nil)
|
||||||
|
api.EXPECT().ContainerStop(ctx, "456", &timeout).Return(nil)
|
||||||
|
api.EXPECT().ContainerStop(ctx, "789", &timeout).Return(nil)
|
||||||
|
|
||||||
|
err := tested.Stop(ctx, &types.Project{
|
||||||
|
Name: testProject,
|
||||||
|
Services: []types.ServiceConfig{
|
||||||
|
{Name: "service1"},
|
||||||
|
{Name: "service2"},
|
||||||
|
},
|
||||||
|
}, compose.StopOptions{
|
||||||
|
Timeout: &timeout,
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user