Skip to content

Commit

Permalink
if command is ran with a compose file, apply the compose model, not j…
Browse files Browse the repository at this point in the history
…ust project name

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
  • Loading branch information
ndeloof authored and laurazard committed Aug 2, 2022
1 parent 765c071 commit f6e96dd
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 76 deletions.
14 changes: 14 additions & 0 deletions cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) {
_ = f.MarkHidden("workdir")
}

func (o *projectOptions) projectOrName() (*types.Project, string, error) {
name := o.ProjectName
var project *types.Project
if o.ProjectName == "" {
p, err := o.toProject(nil)
if err != nil {
return nil, "", err
}
project = p
name = p.Name
}
return project, name, nil
}

func (o *projectOptions) toProjectName() (string, error) {
if o.ProjectName != "" {
return o.ProjectName, nil
Expand Down
13 changes: 3 additions & 10 deletions cmd/compose/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"os"
"time"

"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -79,15 +78,9 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runDown(ctx context.Context, backend api.Service, opts downOptions) error {
name := opts.ProjectName
var project *types.Project
if opts.ProjectName == "" {
p, err := opts.toProject(nil)
if err != nil {
return err
}
project = p
name = p.Name
project, name, err := opts.projectOrName()
if err != nil {
return err
}

var timeout *time.Duration
Expand Down
4 changes: 2 additions & 2 deletions cmd/compose/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
project, err := opts.toProjectName()
name, err := opts.toProjectName()
if err != nil {
return err
}

return backend.Events(ctx, project, api.EventsOptions{
return backend.Events(ctx, name, api.EventsOptions{
Services: services,
Consumer: func(event api.Event) error {
if opts.json {
Expand Down
4 changes: 2 additions & 2 deletions cmd/compose/kill.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
projectName, err := opts.toProjectName()
name, err := opts.toProjectName()
if err != nil {
return err
}

return backend.Kill(ctx, projectName, api.KillOptions{
return backend.Kill(ctx, name, api.KillOptions{
Services: services,
Signal: opts.signal,
})
Expand Down
10 changes: 6 additions & 4 deletions cmd/compose/pause.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runPause(ctx context.Context, backend api.Service, opts pauseOptions, services []string) error {
project, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}

return backend.Pause(ctx, project, api.PauseOptions{
return backend.Pause(ctx, name, api.PauseOptions{
Services: services,
Project: project,
})
}

Expand All @@ -74,12 +75,13 @@ func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runUnPause(ctx context.Context, backend api.Service, opts unpauseOptions, services []string) error {
project, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}

return backend.UnPause(ctx, project, api.PauseOptions{
return backend.UnPause(ctx, name, api.PauseOptions{
Services: services,
Project: project,
})
}
8 changes: 5 additions & 3 deletions cmd/compose/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,25 @@ Any data which is not in a volume will be lost.`,
}

func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error {
project, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}

if opts.stop {
err := backend.Stop(ctx, project, api.StopOptions{
err := backend.Stop(ctx, name, api.StopOptions{
Services: services,
Project: project,
})
if err != nil {
return err
}
}

return backend.Remove(ctx, project, api.RemoveOptions{
return backend.Remove(ctx, name, api.RemoveOptions{
Services: services,
Force: opts.force,
Volumes: opts.volumes,
Project: project,
})
}
5 changes: 3 additions & 2 deletions cmd/compose/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error {
projectName, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}

timeout := time.Duration(opts.timeout) * time.Second
return backend.Restart(ctx, projectName, api.RestartOptions{
return backend.Restart(ctx, name, api.RestartOptions{
Timeout: &timeout,
Services: services,
Project: project,
})
}
5 changes: 3 additions & 2 deletions cmd/compose/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
}

func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error {
projectName, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}

return backend.Start(ctx, projectName, api.StartOptions{
return backend.Start(ctx, name, api.StartOptions{
AttachTo: services,
Project: project,
})
}
5 changes: 3 additions & 2 deletions cmd/compose/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
projectName, err := opts.toProjectName()
project, name, err := opts.projectOrName()
if err != nil {
return err
}
Expand All @@ -63,8 +63,9 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service
timeoutValue := time.Duration(opts.timeout) * time.Second
timeout = &timeoutValue
}
return backend.Stop(ctx, projectName, api.StopOptions{
return backend.Stop(ctx, name, api.StopOptions{
Timeout: timeout,
Services: services,
Project: project,
})
}
12 changes: 11 additions & 1 deletion pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ type CreateOptions struct {

// StartOptions group options of the Start API
type StartOptions struct {
// Project is the compose project used to define this app. Might be nil if user ran `start` just with project name
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
// Attach to container and forward logs if not nil
Attach LogConsumer
Expand All @@ -133,6 +133,8 @@ type StartOptions struct {

// RestartOptions group options of the Restart API
type RestartOptions struct {
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
// Timeout override container restart timeout
Timeout *time.Duration
// Services passed in the command line to be restarted
Expand All @@ -141,6 +143,8 @@ type RestartOptions struct {

// StopOptions group options of the Stop API
type StopOptions struct {
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
// Timeout override container stop timeout
Timeout *time.Duration
// Services passed in the command line to be stopped
Expand Down Expand Up @@ -201,6 +205,8 @@ type KillOptions struct {

// RemoveOptions group options of the Remove API
type RemoveOptions struct {
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
// DryRun just list removable resources
DryRun bool
// Volumes remove anonymous volumes
Expand All @@ -213,6 +219,8 @@ type RemoveOptions struct {

// RunOptions group options of the Run API
type RunOptions struct {
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
Name string
Service string
Command []string
Expand Down Expand Up @@ -377,6 +385,8 @@ type LogOptions struct {
type PauseOptions struct {
// Services passed in the command line to be started
Services []string
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
Project *types.Project
}

const (
Expand Down
20 changes: 0 additions & 20 deletions pkg/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,26 +172,6 @@ SERVICES:
return project, nil
}

// actualState list resources labelled by projectName to rebuild compose project model
func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) {
var containers Containers
// don't filter containers by options.Services so projectFromName can rebuild project with all existing resources
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
if err != nil {
return nil, nil, err
}

project, err := s.projectFromName(containers, projectName, services...)
if err != nil && !api.IsNotFoundError(err) {
return nil, nil, err
}

if len(services) > 0 {
containers = containers.filter(isService(services...))
}
return containers, project, nil
}

func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions pkg/compose/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
w := progress.ContextWriter(ctx)
resourceToRemove := false

var containers Containers
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
include := oneOffExclude
if options.RemoveOrphans {
include = oneOffInclude
}
containers, err := s.getContainers(ctx, projectName, include, true)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/compose/down_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestDown(t *testing.T) {
tested.dockerCli = cli
cli.EXPECT().Client().Return(api).AnyTimes()

api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
[]moby.Container{
testContainer("service1", "123", false),
testContainer("service2", "456", false),
Expand Down Expand Up @@ -88,7 +88,7 @@ func TestDownRemoveOrphans(t *testing.T) {
tested.dockerCli = cli
cli.EXPECT().Client().Return(api).AnyTimes()

api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return(
[]moby.Container{
testContainer("service1", "123", false),
testContainer("service2", "789", false),
Expand Down Expand Up @@ -125,7 +125,7 @@ func TestDownRemoveVolumes(t *testing.T) {
tested.dockerCli = cli
cli.EXPECT().Client().Return(api).AnyTimes()

api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
[]moby.Container{testContainer("service1", "123", false)}, nil)
api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
Return(volume.VolumeListOKBody{
Expand Down
11 changes: 9 additions & 2 deletions pkg/compose/kill_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package compose

import (
"context"
"fmt"
"path/filepath"
"strings"
"testing"
Expand Down Expand Up @@ -110,9 +111,15 @@ func anyCancellableContext() gomock.Matcher {
return gomock.AssignableToTypeOf(ctxWithCancel)
}

func projectFilterListOpt() moby.ContainerListOptions {
func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions {
filter := filters.NewArgs(
projectFilter(strings.ToLower(testProject)),
)
if !withOneOff {
filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel))
}
return moby.ContainerListOptions{
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
Filters: filter,
All: true,
}
}
12 changes: 10 additions & 2 deletions pkg/compose/pause.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ func (s *composeService) Pause(ctx context.Context, projectName string, options
})
}

func (s *composeService) pause(ctx context.Context, project string, options api.PauseOptions) error {
containers, err := s.getContainers(ctx, project, oneOffExclude, false, options.Services...)
func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
containers, err := s.getContainers(ctx, projectName, oneOffExclude, false, options.Services...)
if err != nil {
return err
}

if options.Project != nil {
containers = containers.filter(isService(options.Project.ServiceNames()...))
}

w := progress.ContextWriter(ctx)
eg, ctx := errgroup.WithContext(ctx)
containers.forEach(func(container moby.Container) {
Expand Down Expand Up @@ -67,6 +71,10 @@ func (s *composeService) unPause(ctx context.Context, projectName string, option
return err
}

if options.Project != nil {
containers = containers.filter(isService(options.Project.ServiceNames()...))
}

w := progress.ContextWriter(ctx)
eg, ctx := errgroup.WithContext(ctx)
containers.forEach(func(container moby.Container) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/compose/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
projectName = strings.ToLower(projectName)
containers, _, err := s.actualState(ctx, projectName, options.Services)
containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.Services...)
if err != nil {
if api.IsNotFoundError(err) {
fmt.Fprintln(s.stderr(), "No stopped containers")
Expand All @@ -40,6 +40,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
return err
}

if options.Project != nil {
containers = containers.filter(isService(options.Project.ServiceNames()...))
}

stoppedContainers := containers.filter(func(c moby.Container) bool {
return c.State != ContainerRunning
})
Expand Down
Loading

0 comments on commit f6e96dd

Please sign in to comment.