mirror of
https://github.com/docker/compose.git
synced 2025-07-16 18:24:26 +02:00
cli: option to write status messages on stdout (#10549)
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
0363d9260a
commit
a14abb9044
@ -52,7 +52,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
|
|||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
_, err := s.build(ctx, project, options)
|
_, err := s.build(ctx, project, options)
|
||||||
return err
|
return err
|
||||||
}, s.stderr(), "Building")
|
}, s.stdinfo(), "Building")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions) (map[string]string, error) { //nolint:gocyclo
|
func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions) (map[string]string, error) { //nolint:gocyclo
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -40,6 +41,15 @@ import (
|
|||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var stdioToStdout bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
out, ok := os.LookupEnv("COMPOSE_STATUS_STDOUT")
|
||||||
|
if ok {
|
||||||
|
stdioToStdout, _ = strconv.ParseBool(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewComposeService create a local implementation of the compose.Service API
|
// NewComposeService create a local implementation of the compose.Service API
|
||||||
func NewComposeService(dockerCli command.Cli) api.Service {
|
func NewComposeService(dockerCli command.Cli) api.Service {
|
||||||
return &composeService{
|
return &composeService{
|
||||||
@ -97,6 +107,13 @@ func (s *composeService) stderr() io.Writer {
|
|||||||
return s.dockerCli.Err()
|
return s.dockerCli.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *composeService) stdinfo() io.Writer {
|
||||||
|
if stdioToStdout {
|
||||||
|
return s.dockerCli.Out()
|
||||||
|
}
|
||||||
|
return s.dockerCli.Err()
|
||||||
|
}
|
||||||
|
|
||||||
func getCanonicalContainerName(c moby.Container) string {
|
func getCanonicalContainerName(c moby.Container) string {
|
||||||
if len(c.Names) == 0 {
|
if len(c.Names) == 0 {
|
||||||
// corner case, sometime happens on removal. return short ID as a safeguard value
|
// corner case, sometime happens on removal. return short ID as a safeguard value
|
||||||
|
@ -46,7 +46,7 @@ const (
|
|||||||
func (s *composeService) Copy(ctx context.Context, projectName string, options api.CopyOptions) error {
|
func (s *composeService) Copy(ctx context.Context, projectName string, options api.CopyOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.copy(ctx, projectName, options)
|
return s.copy(ctx, projectName, options)
|
||||||
}, s.stderr(), "Copying")
|
}, s.stdinfo(), "Copying")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) copy(ctx context.Context, projectName string, options api.CopyOptions) error {
|
func (s *composeService) copy(ctx context.Context, projectName string, options api.CopyOptions) error {
|
||||||
|
@ -51,7 +51,7 @@ import (
|
|||||||
func (s *composeService) Create(ctx context.Context, project *types.Project, options api.CreateOptions) error {
|
func (s *composeService) Create(ctx context.Context, project *types.Project, options api.CreateOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.create(ctx, project, options)
|
return s.create(ctx, project, options)
|
||||||
}, s.stderr(), "Creating")
|
}, s.stdinfo(), "Creating")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) create(ctx context.Context, project *types.Project, options api.CreateOptions) error {
|
func (s *composeService) create(ctx context.Context, project *types.Project, options api.CreateOptions) error {
|
||||||
|
@ -41,7 +41,7 @@ type downOp func() error
|
|||||||
func (s *composeService) Down(ctx context.Context, projectName string, options api.DownOptions) error {
|
func (s *composeService) Down(ctx context.Context, projectName string, options api.DownOptions) error {
|
||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
return s.down(ctx, strings.ToLower(projectName), options)
|
return s.down(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) down(ctx context.Context, projectName string, options api.DownOptions) error {
|
func (s *composeService) down(ctx context.Context, projectName string, options api.DownOptions) error {
|
||||||
|
@ -31,7 +31,7 @@ import (
|
|||||||
func (s *composeService) Kill(ctx context.Context, projectName string, options api.KillOptions) error {
|
func (s *composeService) Kill(ctx context.Context, projectName string, options api.KillOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.kill(ctx, strings.ToLower(projectName), options)
|
return s.kill(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr(), "Killing")
|
}, s.stdinfo(), "Killing")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) kill(ctx context.Context, projectName string, options api.KillOptions) error {
|
func (s *composeService) kill(ctx context.Context, projectName string, options api.KillOptions) error {
|
||||||
@ -57,7 +57,8 @@ func (s *composeService) kill(ctx context.Context, projectName string, options a
|
|||||||
containers = containers.filter(isService(project.ServiceNames()...))
|
containers = containers.filter(isService(project.ServiceNames()...))
|
||||||
}
|
}
|
||||||
if len(containers) == 0 {
|
if len(containers) == 0 {
|
||||||
fmt.Fprintf(s.stderr(), "no container to kill")
|
fmt.Fprintf(s.stdinfo(), "no container to kill")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
@ -30,7 +30,7 @@ import (
|
|||||||
func (s *composeService) Pause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
func (s *composeService) Pause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.pause(ctx, strings.ToLower(projectName), options)
|
return s.pause(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr(), "Pausing")
|
}, s.stdinfo(), "Pausing")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
||||||
@ -62,7 +62,7 @@ func (s *composeService) pause(ctx context.Context, projectName string, options
|
|||||||
func (s *composeService) UnPause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
func (s *composeService) UnPause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
return s.unPause(ctx, strings.ToLower(projectName), options)
|
return s.unPause(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) unPause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
func (s *composeService) unPause(ctx context.Context, projectName string, options api.PauseOptions) error {
|
||||||
|
@ -44,7 +44,7 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project, optio
|
|||||||
}
|
}
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.pull(ctx, project, options)
|
return s.pull(ctx, project, options)
|
||||||
}, s.stderr(), "Pulling")
|
}, s.stdinfo(), "Pulling")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) pull(ctx context.Context, project *types.Project, opts api.PullOptions) error { //nolint:gocyclo
|
func (s *composeService) pull(ctx context.Context, project *types.Project, opts api.PullOptions) error { //nolint:gocyclo
|
||||||
@ -305,7 +305,7 @@ func (s *composeService) pullRequiredImages(ctx context.Context, project *types.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func isServiceImageToBuild(service types.ServiceConfig, services []types.ServiceConfig) bool {
|
func isServiceImageToBuild(service types.ServiceConfig, services []types.ServiceConfig) bool {
|
||||||
|
@ -42,7 +42,7 @@ func (s *composeService) Push(ctx context.Context, project *types.Project, optio
|
|||||||
}
|
}
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.push(ctx, project, options)
|
return s.push(ctx, project, options)
|
||||||
}, s.stderr(), "Pushing")
|
}, s.stdinfo(), "Pushing")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
|
func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
|
||||||
|
@ -75,10 +75,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
|||||||
stoppedContainers.forEach(func(c moby.Container) {
|
stoppedContainers.forEach(func(c moby.Container) {
|
||||||
names = append(names, getCanonicalContainerName(c))
|
names = append(names, getCanonicalContainerName(c))
|
||||||
})
|
})
|
||||||
fmt.Fprintln(s.stderr(), names)
|
fmt.Fprintln(s.stdinfo(), names)
|
||||||
|
|
||||||
if len(names) == 0 {
|
if len(names) == 0 {
|
||||||
fmt.Fprintln(s.stderr(), "No stopped containers")
|
fmt.Fprintln(s.stdinfo(), "No stopped containers")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", "))
|
msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", "))
|
||||||
@ -95,7 +95,7 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
|||||||
}
|
}
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.remove(ctx, stoppedContainers, options)
|
return s.remove(ctx, stoppedContainers, options)
|
||||||
}, s.stderr(), "Removing")
|
}, s.stdinfo(), "Removing")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) remove(ctx context.Context, containers Containers, options api.RemoveOptions) error {
|
func (s *composeService) remove(ctx context.Context, containers Containers, options api.RemoveOptions) error {
|
||||||
|
@ -31,7 +31,7 @@ import (
|
|||||||
func (s *composeService) Restart(ctx context.Context, projectName string, options api.RestartOptions) error {
|
func (s *composeService) Restart(ctx context.Context, projectName string, options api.RestartOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.restart(ctx, strings.ToLower(projectName), options)
|
return s.restart(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr(), "Restarting")
|
}, s.stdinfo(), "Restarting")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error {
|
func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error {
|
||||||
|
@ -38,7 +38,7 @@ import (
|
|||||||
func (s *composeService) Start(ctx context.Context, projectName string, 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 progress.Run(ctx, func(ctx context.Context) error {
|
||||||
return s.start(ctx, strings.ToLower(projectName), options, nil)
|
return s.start(ctx, strings.ToLower(projectName), options, nil)
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error {
|
func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error {
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
||||||
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
return s.stop(ctx, strings.ToLower(projectName), options)
|
return s.stop(ctx, strings.ToLower(projectName), options)
|
||||||
}, s.stderr(), "Stopping")
|
}, s.stdinfo(), "Stopping")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
||||||
|
@ -40,7 +40,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
return s.start(ctx, project.Name, options.Start, nil)
|
return s.start(ctx, project.Name, options.Start, nil)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
stopFunc := func() error {
|
stopFunc := func() error {
|
||||||
fmt.Fprintln(s.stderr(), "Aborting on container exit...")
|
fmt.Fprintln(s.stdinfo(), "Aborting on container exit...")
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
go func() {
|
go func() {
|
||||||
@ -74,7 +74,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
Services: options.Create.Services,
|
Services: options.Create.Services,
|
||||||
Project: project,
|
Project: project,
|
||||||
})
|
})
|
||||||
}, s.stderr())
|
}, s.stdinfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
var isTerminated bool
|
var isTerminated bool
|
||||||
@ -83,7 +83,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
<-signalChan
|
<-signalChan
|
||||||
isTerminated = true
|
isTerminated = true
|
||||||
printer.Cancel()
|
printer.Cancel()
|
||||||
fmt.Fprintln(s.stderr(), "Gracefully stopping... (press Ctrl+C again to force)")
|
fmt.Fprintln(s.stdinfo(), "Gracefully stopping... (press Ctrl+C again to force)")
|
||||||
eg.Go(stopFunc)
|
eg.Go(stopFunc)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(s.stderr(), "watching %s\n", bc)
|
fmt.Fprintf(s.stdinfo(), "watching %s\n", bc)
|
||||||
err = watcher.Start()
|
err = watcher.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -207,7 +207,7 @@ WATCH:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(s.stderr(), "change detected on %s\n", hostPath)
|
fmt.Fprintf(s.stdinfo(), "change detected on %s\n", hostPath)
|
||||||
|
|
||||||
f := fileMapping{
|
f := fileMapping{
|
||||||
HostPath: hostPath,
|
HostPath: hostPath,
|
||||||
@ -283,7 +283,7 @@ func (s *composeService) makeRebuildFn(ctx context.Context, project *types.Proje
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(
|
fmt.Fprintf(
|
||||||
s.stderr(),
|
s.stdinfo(),
|
||||||
"Rebuilding %s after changes were detected:%s\n",
|
"Rebuilding %s after changes were detected:%s\n",
|
||||||
strings.Join(serviceNames, ", "),
|
strings.Join(serviceNames, ", "),
|
||||||
strings.Join(append([]string{""}, allPaths.Elements()...), "\n - "),
|
strings.Join(append([]string{""}, allPaths.Elements()...), "\n - "),
|
||||||
@ -319,7 +319,7 @@ func (s *composeService) makeSyncFn(ctx context.Context, project *types.Project,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(s.stderr(), "%s updated\n", opt.ContainerPath)
|
fmt.Fprintf(s.stdinfo(), "%s updated\n", opt.ContainerPath)
|
||||||
} else if errors.Is(statErr, fs.ErrNotExist) {
|
} else if errors.Is(statErr, fs.ErrNotExist) {
|
||||||
_, err := s.Exec(ctx, project.Name, api.RunOptions{
|
_, err := s.Exec(ctx, project.Name, api.RunOptions{
|
||||||
Service: opt.Service,
|
Service: opt.Service,
|
||||||
@ -329,7 +329,7 @@ func (s *composeService) makeSyncFn(ctx context.Context, project *types.Project,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnf("failed to delete %q from %s: %v", opt.ContainerPath, opt.Service, err)
|
logrus.Warnf("failed to delete %q from %s: %v", opt.ContainerPath, opt.Service, err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(s.stderr(), "%s deleted from container\n", opt.ContainerPath)
|
fmt.Fprintf(s.stdinfo(), "%s deleted from container\n", opt.ContainerPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user