mirror of
				https://github.com/docker/compose.git
				synced 2025-11-03 21:25:21 +01:00 
			
		
		
		
	revisit run implementation as create, attach, start, wait
				
					
				
			Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
		
							parent
							
								
									d56745cba4
								
							
						
					
					
						commit
						4462f12249
					
				@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,17 +20,16 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/compose-spec/compose-go/types"
 | 
			
		||||
	apitypes "github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"golang.org/x/sync/errgroup"
 | 
			
		||||
 | 
			
		||||
	"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"
 | 
			
		||||
	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)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	err = s.attachContainerStreams(ctx, oneoffContainer, true, opts.Reader, opts.Writer)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return eg.Wait()
 | 
			
		||||
 | 
			
		||||
	err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user