1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
// +build varlink
package varlinkapi
import (
"io"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
"k8s.io/client-go/tools/remotecommand"
)
// Close is method to close the writer
// Attach ...
func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string) error {
var finalErr error
resize := make(chan remotecommand.TerminalSize)
errChan := make(chan error)
if !call.WantsUpgrade() {
return call.ReplyErrorOccurred("client must use upgraded connection to attach")
}
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
// These are the varlink sockets
reader := call.Call.Reader
writer := call.Call.Writer
// This pipe is used to pass stdin from the client to the input stream
// once the msg has been "decoded"
pr, pw := io.Pipe()
stdoutWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdout)
// TODO if runc ever starts passing stderr, we can too
//stderrWriter := NewVirtWriteCloser(writer, ToStderr)
streams := libpod.AttachStreams{
OutputStream: stdoutWriter,
InputStream: pr,
// Runc eats the error stream
ErrorStream: stdoutWriter,
AttachInput: true,
AttachOutput: true,
// Runc eats the error stream
AttachError: true,
}
go func() {
if err := virtwriter.Reader(reader, nil, nil, pw, resize); err != nil {
errChan <- err
}
}()
go func() {
// TODO allow for customizable detach keys
if err := ctr.Attach(&streams, "", resize); err != nil {
errChan <- err
}
}()
select {
// Blocking on an error
case finalErr = <-errChan:
// Need to close up shop
_ = finalErr
}
quitWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.Quit)
_, err = quitWriter.Write([]byte("HANG-UP"))
return call.Writer.Flush()
}
|