Przeglądaj źródła

revisit `run` implementation as create, attach, start, wait

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 4 lat temu
rodzic
commit
4462f12249

+ 2 - 2
aci/compose.go

@@ -207,6 +207,6 @@ func (cs *aciComposeService) Kill(ctx context.Context, project *types.Project, o
 	return errdefs.ErrNotImplemented
 }
 
-func (cs *aciComposeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
-	return errdefs.ErrNotImplemented
+func (cs *aciComposeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
+	return 0, errdefs.ErrNotImplemented
 }

+ 2 - 2
api/client/compose.go

@@ -80,6 +80,6 @@ func (c *composeService) Kill(ctx context.Context, project *types.Project, optio
 	return errdefs.ErrNotImplemented
 }
 
-func (c *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
-	return errdefs.ErrNotImplemented
+func (c *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
+	return 0, errdefs.ErrNotImplemented
 }

+ 1 - 1
api/compose/api.go

@@ -52,7 +52,7 @@ type Service interface {
 	// Kill executes the equivalent to a `compose kill`
 	Kill(ctx context.Context, project *types.Project, options KillOptions) error
 	// RunOneOffContainer creates a service oneoff container and starts its dependencies
-	RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) error
+	RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
 }
 
 // CreateOptions group options of the Create API

+ 6 - 1
cli/cmd/compose/run.go

@@ -26,6 +26,7 @@ import (
 	"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/cli/cmd"
 )
 
 type runOptions struct {
@@ -85,7 +86,11 @@ func runRun(ctx context.Context, opts runOptions) error {
 		Writer:     os.Stdout,
 		Reader:     os.Stdin,
 	}
-	return c.ComposeService().RunOneOffContainer(ctx, project, runOpts)
+	exitCode, err := c.ComposeService().RunOneOffContainer(ctx, project, runOpts)
+	if exitCode != 0 {
+		return cmd.ExitCodeError{ExitCode: exitCode}
+	}
+	return err
 }
 
 func startDependencies(ctx context.Context, c *client.Client, project types.Project, requestedServiceName string) error {

+ 2 - 2
ecs/local/compose.go

@@ -172,6 +172,6 @@ func (e ecsLocalSimulation) Ps(ctx context.Context, projectName string, options
 func (e ecsLocalSimulation) List(ctx context.Context) ([]compose.Stack, error) {
 	return e.compose.List(ctx)
 }
-func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
-	return errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run")
+func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
+	return 0, errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run")
 }

+ 2 - 2
ecs/run.go

@@ -25,6 +25,6 @@ import (
 	"github.com/docker/compose-cli/api/errdefs"
 )
 
-func (b *ecsAPIService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
-	return errdefs.ErrNotImplemented
+func (b *ecsAPIService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
+	return 0, errdefs.ErrNotImplemented
 }

+ 2 - 2
kube/compose.go

@@ -194,6 +194,6 @@ func (s *composeService) Kill(ctx context.Context, project *types.Project, optio
 }
 
 // RunOneOffContainer creates a service oneoff container and starts its dependencies
-func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
-	return errdefs.ErrNotImplemented
+func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
+	return 0, errdefs.ErrNotImplemented
 }

+ 26 - 18
local/compose/run.go

@@ -20,17 +20,16 @@ import (
 	"context"
 	"fmt"
 
+	"github.com/docker/compose-cli/api/compose"
+
 	"github.com/compose-spec/compose-go/types"
 	apitypes "github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"
-	"golang.org/x/sync/errgroup"
-
-	"github.com/docker/compose-cli/api/compose"
-
 	moby "github.com/docker/docker/pkg/stringid"
 )
 
-func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
+func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
 	originalServices := project.Services
 	var requestedService types.ServiceConfig
 	for _, service := range originalServices {
@@ -53,23 +52,23 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
 	requestedService.Labels = requestedService.Labels.Add(oneoffLabel, "True")
 
 	if err := s.ensureImagesExists(ctx, project); err != nil { // all dependencies already checked, but might miss requestedService img
-		return err
+		return 0, err
 	}
 	if err := s.waitDependencies(ctx, project, requestedService); err != nil {
-		return err
+		return 0, err
 	}
 	if err := s.createContainer(ctx, project, requestedService, requestedService.ContainerName, 1, opts.AutoRemove); err != nil {
-		return err
+		return 0, err
 	}
 	containerID := requestedService.ContainerName
 
 	if opts.Detach {
 		err := s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
 		if err != nil {
-			return err
+			return 0, err
 		}
 		fmt.Fprintln(opts.Writer, containerID)
-		return nil
+		return 0, nil
 	}
 
 	containers, err := s.apiClient.ContainerList(ctx, apitypes.ContainerListOptions{
@@ -79,16 +78,25 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
 		All: true,
 	})
 	if err != nil {
-		return err
+		return 0, err
 	}
 	oneoffContainer := containers[0]
-	eg := errgroup.Group{}
-	eg.Go(func() error {
-		return s.attachContainerStreams(ctx, oneoffContainer, true, opts.Reader, opts.Writer)
-	})
+	err = s.attachContainerStreams(ctx, oneoffContainer, true, opts.Reader, opts.Writer)
+	if err != nil {
+		return 0, err
+	}
+
+	err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
+	if err != nil {
+		return 0, err
+	}
 
-	if err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{}); err != nil {
-		return err
+	statusC, errC := s.apiClient.ContainerWait(context.Background(), oneoffContainer.ID, container.WaitConditionNotRunning)
+	select {
+	case status := <-statusC:
+		return int(status.StatusCode), nil
+	case err := <-errC:
+		return 0, err
 	}
-	return eg.Wait()
+
 }