from Compose CLI, we know the streams used to configure LogConsumer

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof
2025-11-04 10:07:52 +01:00
committed by Guillaume Lours
parent d70bb8cf5e
commit fc2a7d13fa
6 changed files with 33 additions and 31 deletions

View File

@@ -22,6 +22,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/compose"
"github.com/docker/compose/v2/pkg/progress"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/cmd/formatter"
@@ -90,8 +91,7 @@ func runLogs(ctx context.Context, dockerCli command.Cli, backendOptions *Backend
if err != nil {
return err
}
outStream, errStream, _ := backend.GetConfiguredStreams()
consumer := formatter.NewLogConsumer(ctx, outStream, errStream, !opts.noColor, !opts.noPrefix, false)
consumer := formatter.NewLogConsumer(ctx, dockerCli.Out(), dockerCli.Err(), !opts.noColor, !opts.noPrefix, false)
return backend.Logs(ctx, name, consumer, api.LogOptions{
Project: project,
Services: services,
@@ -103,3 +103,32 @@ func runLogs(ctx context.Context, dockerCli command.Cli, backendOptions *Backend
Timestamps: opts.timestamps,
})
}
var _ api.LogConsumer = &logConsumer{}
type logConsumer struct {
events progress.EventProcessor
}
func (l logConsumer) Log(containerName, message string) {
l.events.On(progress.Event{
ID: containerName,
Text: message,
})
}
func (l logConsumer) Err(containerName, message string) {
l.events.On(progress.Event{
ID: containerName,
Status: progress.Error,
Text: message,
})
}
func (l logConsumer) Status(containerName, message string) {
l.events.On(progress.Event{
ID: containerName,
Status: progress.Error,
Text: message,
})
}

View File

@@ -296,8 +296,7 @@ func runUp(
var consumer api.LogConsumer
var attach []string
if !upOptions.Detach {
outStream, errStream, _ := backend.GetConfiguredStreams()
consumer = formatter.NewLogConsumer(ctx, outStream, errStream, !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
consumer = formatter.NewLogConsumer(ctx, dockerCli.Out(), dockerCli.Err(), !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
var attachSet utils.Set[string]
if len(upOptions.attach) != 0 {

View File

@@ -122,8 +122,7 @@ func runWatch(ctx context.Context, dockerCli command.Cli, backendOptions *Backen
}
}
outStream, errStream, _ := backend.GetConfiguredStreams()
consumer := formatter.NewLogConsumer(ctx, outStream, errStream, false, false, false)
consumer := formatter.NewLogConsumer(ctx, dockerCli.Out(), dockerCli.Err(), false, false, false)
return backend.Watch(ctx, project, api.WatchOptions{
Build: &build,
LogTo: consumer,

View File

@@ -140,9 +140,6 @@ type Compose interface {
Generate(ctx context.Context, options GenerateOptions) (*types.Project, error)
// Volumes executes the equivalent to a `docker volume ls`
Volumes(ctx context.Context, project string, options VolumesOptions) ([]VolumesSummary, error)
// GetConfiguredStreams returns the configured I/O streams (stdout, stderr, stdin).
// If no custom streams were configured, it returns the dockerCli streams.
GetConfiguredStreams() (stdout io.Writer, stderr io.Writer, stdin io.Reader)
// LoadProject loads and validates a Compose project from configuration files.
LoadProject(ctx context.Context, options ProjectLoadOptions) (*types.Project, error)
}

View File

@@ -285,11 +285,6 @@ func (s *composeService) stdinfo() *streams.Out {
return s.stderr()
}
// GetConfiguredStreams returns the configured I/O streams (implements api.Compose interface)
func (s *composeService) GetConfiguredStreams() (io.Writer, io.Writer, io.Reader) {
return s.stdout(), s.stderr(), s.stdin()
}
// readCloserAdapter adapts io.Reader to io.ReadCloser
type readCloserAdapter struct {
r io.Reader

View File

@@ -11,7 +11,6 @@ package mocks
import (
context "context"
io "io"
reflect "reflect"
types "github.com/compose-spec/compose-go/v2/types"
@@ -184,22 +183,6 @@ func (mr *MockComposeMockRecorder) Generate(ctx, options any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockCompose)(nil).Generate), ctx, options)
}
// GetConfiguredStreams mocks base method.
func (m *MockCompose) GetConfiguredStreams() (io.Writer, io.Writer, io.Reader) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetConfiguredStreams")
ret0, _ := ret[0].(io.Writer)
ret1, _ := ret[1].(io.Writer)
ret2, _ := ret[2].(io.Reader)
return ret0, ret1, ret2
}
// GetConfiguredStreams indicates an expected call of GetConfiguredStreams.
func (mr *MockComposeMockRecorder) GetConfiguredStreams() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfiguredStreams", reflect.TypeOf((*MockCompose)(nil).GetConfiguredStreams))
}
// Images mocks base method.
func (m *MockCompose) Images(ctx context.Context, projectName string, options api.ImagesOptions) (map[string]api.ImageSummary, error) {
m.ctrl.T.Helper()