Signed-off-by: Mehrad Dadar <mehrad.dadar@gmail.com>
This commit is contained in:
Mehrad Dadar 2022-02-05 10:27:52 +03:30
parent 5262d3bbf5
commit 65ed8cf4c2
13 changed files with 83 additions and 58 deletions

View File

@ -65,7 +65,7 @@ func runRemove(ctx context.Context, backend api.Service, opts removeOptions, ser
}
if opts.stop {
err := backend.Stop(ctx, project, api.StopOptions{
err := backend.Stop(ctx, project.Name, api.StopOptions{
Services: services,
})
if err != nil {

View File

@ -49,13 +49,13 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
}
func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error {
project, err := opts.toProject(services)
projectName, err := opts.toProjectName()
if err != nil {
return err
}
timeout := time.Duration(opts.timeout) * time.Second
return backend.Restart(ctx, project, api.RestartOptions{
return backend.Restart(ctx, projectName, api.RestartOptions{
Timeout: &timeout,
Services: services,
})

View File

@ -240,5 +240,5 @@ func startDependencies(ctx context.Context, backend api.Service, project types.P
if err := backend.Create(ctx, &project, api.CreateOptions{}); err != nil {
return err
}
return backend.Start(ctx, &project, api.StartOptions{})
return backend.Start(ctx, project.Name, api.StartOptions{})
}

View File

@ -43,10 +43,12 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
}
func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error {
project, err := opts.toProject(services)
projectName, err := opts.toProjectName()
if err != nil {
return err
}
return backend.Start(ctx, project, api.StartOptions{})
return backend.Start(ctx, projectName, api.StartOptions{
AttachTo: services,
})
}

View File

@ -53,7 +53,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
}
func runStop(ctx context.Context, backend api.Service, opts stopOptions, services []string) error {
project, err := opts.toProject(services)
projectName, err := opts.toProjectName()
if err != nil {
return err
}
@ -63,7 +63,7 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service
timeoutValue := time.Duration(opts.timeout) * time.Second
timeout = &timeoutValue
}
return backend.Stop(ctx, project, api.StopOptions{
return backend.Stop(ctx, projectName, api.StopOptions{
Timeout: timeout,
Services: services,
})

View File

@ -37,11 +37,11 @@ type Service interface {
// Create executes the equivalent to a `compose create`
Create(ctx context.Context, project *types.Project, opts CreateOptions) error
// Start executes the equivalent to a `compose start`
Start(ctx context.Context, project *types.Project, options StartOptions) error
Start(ctx context.Context, projectName string, options StartOptions) error
// Restart restarts containers
Restart(ctx context.Context, project *types.Project, options RestartOptions) error
Restart(ctx context.Context, projectName string, options RestartOptions) error
// Stop executes the equivalent to a `compose stop`
Stop(ctx context.Context, project *types.Project, options StopOptions) error
Stop(ctx context.Context, projectName string, options StopOptions) error
// Up executes the equivalent to a `compose up`
Up(ctx context.Context, project *types.Project, options UpOptions) error
// Down executes the equivalent to a `compose down`

View File

@ -28,9 +28,9 @@ type ServiceProxy struct {
PushFn func(ctx context.Context, project *types.Project, options PushOptions) error
PullFn func(ctx context.Context, project *types.Project, opts PullOptions) error
CreateFn func(ctx context.Context, project *types.Project, opts CreateOptions) error
StartFn func(ctx context.Context, project *types.Project, options StartOptions) error
RestartFn func(ctx context.Context, project *types.Project, options RestartOptions) error
StopFn func(ctx context.Context, project *types.Project, options StopOptions) error
StartFn func(ctx context.Context, projectName string, options StartOptions) error
RestartFn func(ctx context.Context, projectName string, options RestartOptions) error
StopFn func(ctx context.Context, projectName string, options StopOptions) error
UpFn func(ctx context.Context, project *types.Project, options UpOptions) error
DownFn func(ctx context.Context, projectName string, options DownOptions) error
LogsFn func(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error
@ -141,36 +141,27 @@ func (s *ServiceProxy) Create(ctx context.Context, project *types.Project, optio
}
// Start implements Service interface
func (s *ServiceProxy) Start(ctx context.Context, project *types.Project, options StartOptions) error {
func (s *ServiceProxy) Start(ctx context.Context, projectName string, options StartOptions) error {
if s.StartFn == nil {
return ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.StartFn(ctx, project, options)
return s.StartFn(ctx, projectName, options)
}
// Restart implements Service interface
func (s *ServiceProxy) Restart(ctx context.Context, project *types.Project, options RestartOptions) error {
func (s *ServiceProxy) Restart(ctx context.Context, projectName string, options RestartOptions) error {
if s.RestartFn == nil {
return ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.RestartFn(ctx, project, options)
return s.RestartFn(ctx, projectName, options)
}
// Stop implements Service interface
func (s *ServiceProxy) Stop(ctx context.Context, project *types.Project, options StopOptions) error {
func (s *ServiceProxy) Stop(ctx context.Context, projectName string, options StopOptions) error {
if s.StopFn == nil {
return ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.StopFn(ctx, project, options)
return s.StopFn(ctx, projectName, options)
}
// Up implements Service interface

View File

@ -92,3 +92,34 @@ func escapeDollarSign(marshal []byte) []byte {
escDollar := []byte{'$', '$'}
return bytes.ReplaceAll(marshal, dollar, escDollar)
}
// projectFromName builds a types.Project based on actual resources with compose labels set
func (s *composeService) projectFromName(containers Containers, projectName string) *types.Project {
project := &types.Project{
Name: projectName,
}
if len(containers) == 0 {
return project
}
set := map[string]moby.Container{}
for _, c := range containers {
set[c.Labels[api.ServiceLabel]] = c
}
for s, c := range set {
service := types.ServiceConfig{
Name: s,
Image: c.Image,
Labels: c.Labels,
}
dependencies := c.Labels[api.DependenciesLabel]
if len(dependencies) > 0 {
service.DependsOn = types.DependsOnConfig{}
for _, d := range strings.Split(dependencies, ",") {
service.DependsOn[d] = types.ServiceDependency{}
}
}
project.Services = append(project.Services, service)
}
return project
}

View File

@ -19,7 +19,6 @@ package compose
import (
"context"
"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/api"
"golang.org/x/sync/errgroup"
@ -27,18 +26,21 @@ import (
"github.com/docker/compose/v2/pkg/utils"
)
func (s *composeService) Restart(ctx context.Context, project *types.Project, options api.RestartOptions) error {
func (s *composeService) Restart(ctx context.Context, projectName string, options api.RestartOptions) error {
return progress.Run(ctx, func(ctx context.Context) error {
return s.restart(ctx, project, options)
return s.restart(ctx, projectName, options)
})
}
func (s *composeService) restart(ctx context.Context, project *types.Project, options api.RestartOptions) error {
observedState, err := s.getContainers(ctx, project.Name, oneOffInclude, true)
func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error {
observedState, err := s.getContainers(ctx, projectName, oneOffInclude, true)
if err != nil {
return err
}
project := s.projectFromName(observedState, projectName)
if len(options.Services) == 0 {
options.Services = project.ServiceNames()
}

View File

@ -28,17 +28,21 @@ import (
"github.com/docker/compose/v2/pkg/progress"
)
func (s *composeService) Start(ctx context.Context, project *types.Project, options api.StartOptions) error {
func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error {
return progress.Run(ctx, func(ctx context.Context) error {
return s.start(ctx, project, options, nil)
return s.start(ctx, projectName, options, nil)
})
}
func (s *composeService) start(ctx context.Context, project *types.Project, options api.StartOptions, listener api.ContainerEventListener) error {
if len(options.AttachTo) == 0 {
options.AttachTo = project.ServiceNames()
func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error {
var containers Containers
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, options.AttachTo...)
if err != nil {
return err
}
project := s.projectFromName(containers, projectName)
eg, ctx := errgroup.WithContext(ctx)
if listener != nil {
attached, err := s.attach(ctx, project, listener, options.AttachTo)
@ -53,7 +57,7 @@ func (s *composeService) start(ctx context.Context, project *types.Project, opti
})
}
err := InDependencyOrder(ctx, project, func(c context.Context, name string) error {
err = InDependencyOrder(ctx, project, func(c context.Context, name string) error {
service, err := project.GetService(name)
if err != nil {
return err

View File

@ -21,29 +21,31 @@ import (
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/compose-spec/compose-go/types"
//"github.com/compose-spec/compose-go/types"
)
func (s *composeService) Stop(ctx context.Context, project *types.Project, options api.StopOptions) error {
func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error {
return progress.Run(ctx, func(ctx context.Context) error {
return s.stop(ctx, project, options)
return s.stop(ctx, projectName, options)
})
}
func (s *composeService) stop(ctx context.Context, project *types.Project, options api.StopOptions) error {
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
w := progress.ContextWriter(ctx)
services := options.Services
if len(services) == 0 {
services = project.ServiceNames()
services = []string{}
}
var containers Containers
containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...)
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, services...)
if err != nil {
return err
}
project := s.projectFromName(containers, projectName)
return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout)
})

View File

@ -25,7 +25,6 @@ import (
compose "github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/mocks"
"github.com/compose-spec/compose-go/types"
moby "github.com/docker/docker/api/types"
"github.com/golang/mock/gomock"
"gotest.tools/v3/assert"
@ -50,13 +49,7 @@ func TestStopTimeout(t *testing.T) {
api.EXPECT().ContainerStop(gomock.Any(), "456", &timeout).Return(nil)
api.EXPECT().ContainerStop(gomock.Any(), "789", &timeout).Return(nil)
err := tested.Stop(ctx, &types.Project{
Name: strings.ToLower(testProject),
Services: []types.ServiceConfig{
{Name: "service1"},
{Name: "service2"},
},
}, compose.StopOptions{
err := tested.Stop(ctx, strings.ToLower(testProject), compose.StopOptions{
Timeout: &timeout,
})
assert.NilError(t, err)

View File

@ -38,7 +38,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
return err
}
if options.Start.Attach == nil {
return s.start(ctx, project, options.Start, nil)
return s.start(ctx, project.Name, options.Start, nil)
}
return nil
})
@ -65,7 +65,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
})
}()
return s.Stop(ctx, project, api.StopOptions{
return s.Stop(ctx, project.Name, api.StopOptions{
Services: options.Create.Services,
})
})
@ -85,7 +85,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
return err
})
err = s.start(ctx, project, options.Start, printer.HandleEvent)
err = s.start(ctx, project.Name, options.Start, printer.HandleEvent)
if err != nil {
return err
}