(ctx context.Context, container string, tty bool, stdout, stderr io.WriteCloser)
| 103 | } |
| 104 | |
| 105 | func (s *composeService) attachContainerStreams(ctx context.Context, container string, tty bool, stdout, stderr io.WriteCloser) error { |
| 106 | streamOut, err := s.getContainerStreams(ctx, container) |
| 107 | if err != nil { |
| 108 | return err |
| 109 | } |
| 110 | |
| 111 | if stdout != nil { |
| 112 | go func() { |
| 113 | defer func() { |
| 114 | if err := stdout.Close(); err != nil { |
| 115 | logrus.Debugf("failed to close stdout: %v", err) |
| 116 | } |
| 117 | if err := stderr.Close(); err != nil { |
| 118 | logrus.Debugf("failed to close stderr: %v", err) |
| 119 | } |
| 120 | if err := streamOut.Close(); err != nil { |
| 121 | logrus.Debugf("failed to close stream output: %v", err) |
| 122 | } |
| 123 | }() |
| 124 | |
| 125 | var err error |
| 126 | if tty { |
| 127 | _, err = io.Copy(stdout, streamOut) |
| 128 | } else { |
| 129 | _, err = stdcopy.StdCopy(stdout, stderr, streamOut) |
| 130 | } |
| 131 | if err != nil && !errors.Is(err, io.EOF) { |
| 132 | logrus.Debugf("stream copy error for container %s: %v", container, err) |
| 133 | } |
| 134 | }() |
| 135 | } |
| 136 | return nil |
| 137 | } |
| 138 | |
| 139 | func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.ReadCloser, error) { |
| 140 | cnx, err := s.apiClient().ContainerAttach(ctx, container, client.ContainerAttachOptions{ |
no test coverage detected