mirror of
https://github.com/docker/compose.git
synced 2025-07-23 05:34:36 +02:00
set terminal in character mode when attached to a container
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
9f81314124
commit
d4a8e92f46
@ -181,8 +181,8 @@ type RunOptions struct {
|
|||||||
Entrypoint []string
|
Entrypoint []string
|
||||||
Detach bool
|
Detach bool
|
||||||
AutoRemove bool
|
AutoRemove bool
|
||||||
Writer io.Writer
|
Writer io.WriteCloser
|
||||||
Reader io.Reader
|
Reader io.ReadCloser
|
||||||
Tty bool
|
Tty bool
|
||||||
WorkingDir string
|
WorkingDir string
|
||||||
User string
|
User string
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/docker/compose-cli/utils"
|
"github.com/docker/compose-cli/utils"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
"github.com/docker/cli/cli/streams"
|
||||||
moby "github.com/docker/docker/api/types"
|
moby "github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
)
|
)
|
||||||
@ -108,26 +109,40 @@ func (s *composeService) attachContainer(ctx context.Context, container moby.Con
|
|||||||
Service: container.Labels[serviceLabel],
|
Service: container.Labels[serviceLabel],
|
||||||
})
|
})
|
||||||
|
|
||||||
return s.attachContainerStreams(ctx, container.ID, service.Tty, nil, w)
|
_, err = s.attachContainerStreams(ctx, container.ID, service.Tty, nil, w)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) attachContainerStreams(ctx context.Context, container string, tty bool, r io.Reader, w io.Writer) error {
|
func (s *composeService) attachContainerStreams(ctx context.Context, container string, tty bool, r io.ReadCloser, w io.Writer) (func(), error) {
|
||||||
|
var (
|
||||||
|
in *streams.In
|
||||||
|
restore = func() { /* noop */ }
|
||||||
|
)
|
||||||
|
if r != nil {
|
||||||
|
in = streams.NewIn(r)
|
||||||
|
restore = in.RestoreTerminal
|
||||||
|
}
|
||||||
|
|
||||||
stdin, stdout, err := s.getContainerStreams(ctx, container)
|
stdin, stdout, err := s.getContainerStreams(ctx, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return restore, err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
stdout.Close() //nolint:errcheck
|
if in != nil {
|
||||||
if stdin != nil {
|
in.Close() //nolint:errcheck
|
||||||
stdin.Close() //nolint:errcheck
|
|
||||||
}
|
}
|
||||||
|
stdout.Close() //nolint:errcheck
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if r != nil && stdin != nil {
|
if in != nil && stdin != nil {
|
||||||
|
err := in.SetRawTerminal()
|
||||||
|
if err != nil {
|
||||||
|
return restore, err
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
io.Copy(stdin, r) //nolint:errcheck
|
io.Copy(stdin, in) //nolint:errcheck
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +155,7 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return nil
|
return restore, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.WriteCloser, io.ReadCloser, error) {
|
func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.WriteCloser, io.ReadCloser, error) {
|
||||||
|
@ -247,7 +247,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
|||||||
ExposedPorts: buildContainerPorts(service),
|
ExposedPorts: buildContainerPorts(service),
|
||||||
Tty: tty,
|
Tty: tty,
|
||||||
OpenStdin: stdinOpen,
|
OpenStdin: stdinOpen,
|
||||||
StdinOnce: true,
|
StdinOnce: attachStdin && stdinOpen,
|
||||||
AttachStdin: attachStdin,
|
AttachStdin: attachStdin,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
|
@ -86,10 +86,11 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
oneoffContainer := containers[0]
|
oneoffContainer := containers[0]
|
||||||
err = s.attachContainerStreams(ctx, oneoffContainer.ID, service.Tty, opts.Reader, opts.Writer)
|
restore, err := s.attachContainerStreams(ctx, oneoffContainer.ID, service.Tty, opts.Reader, opts.Writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
defer restore()
|
||||||
|
|
||||||
err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
|
err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -62,7 +62,7 @@ func (a *allowListLogConsumer) Register(name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetWriter creates a io.Writer that will actually split by line and format by LogConsumer
|
// GetWriter creates a io.Writer that will actually split by line and format by LogConsumer
|
||||||
func GetWriter(container, service string, events compose.ContainerEventListener) io.Writer {
|
func GetWriter(container, service string, events compose.ContainerEventListener) io.WriteCloser {
|
||||||
return &splitBuffer{
|
return &splitBuffer{
|
||||||
buffer: bytes.Buffer{},
|
buffer: bytes.Buffer{},
|
||||||
service: service,
|
service: service,
|
||||||
@ -100,3 +100,17 @@ func (s *splitBuffer) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *splitBuffer) Close() error {
|
||||||
|
b := s.buffer.Bytes()
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s.consumer(compose.ContainerEvent{
|
||||||
|
Type: compose.ContainerEventLog,
|
||||||
|
Service: s.service,
|
||||||
|
Container: s.container,
|
||||||
|
Line: string(b),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user