2024-01-14 20:46:32 +00:00
|
|
|
package qpty
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"github.com/creack/pty"
|
|
|
|
"github.com/fsouza/go-dockerclient"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Qpty struct {
|
|
|
|
dock *docker.Client
|
|
|
|
container string
|
2024-01-14 21:07:01 +00:00
|
|
|
pty, tty *os.File
|
|
|
|
ir, or *io.PipeReader
|
|
|
|
iw, ow *io.PipeWriter
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
func New(client *docker.Client, container string, size *pty.Winsize) (*Qpty, error) {
|
|
|
|
iPty, iTty, err := pty.Open()
|
2024-01-14 20:46:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-01-14 21:07:01 +00:00
|
|
|
q := &Qpty{
|
|
|
|
dock: client,
|
|
|
|
container: container,
|
|
|
|
pty: iPty, tty: iTty,
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
2024-01-14 21:07:01 +00:00
|
|
|
if err := q.SetSize(size); err != nil {
|
2024-01-14 20:46:32 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2024-01-14 21:07:01 +00:00
|
|
|
q.ir, q.iw = io.Pipe()
|
|
|
|
q.or, q.ow = io.Pipe()
|
|
|
|
return q, nil
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
func (q *Qpty) Pty() *os.File {
|
|
|
|
return q.pty
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
func (q *Qpty) SetSize(winsize *pty.Winsize) error {
|
|
|
|
return pty.Setsize(q.pty, winsize)
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
func (q *Qpty) Send(p []byte) (int, error) {
|
|
|
|
return q.iw.Write(p)
|
2024-01-14 20:46:32 +00:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
func (q *Qpty) Run(shell string) error {
|
|
|
|
execInst, err := q.dock.CreateExec(docker.CreateExecOptions{
|
2024-01-14 20:46:32 +00:00
|
|
|
Cmd: []string{shell},
|
2024-01-14 21:07:01 +00:00
|
|
|
Container: q.container,
|
2024-01-14 20:46:32 +00:00
|
|
|
User: "root",
|
|
|
|
WorkingDir: "/",
|
|
|
|
Context: context.Background(),
|
|
|
|
AttachStdin: true,
|
|
|
|
AttachStdout: true,
|
|
|
|
Tty: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
2024-01-14 21:07:01 +00:00
|
|
|
_, _ = io.Copy(q.tty, q.or)
|
2024-01-14 20:46:32 +00:00
|
|
|
}()
|
|
|
|
|
2024-01-14 21:07:01 +00:00
|
|
|
return q.dock.StartExec(execInst.ID, docker.StartExecOptions{
|
|
|
|
InputStream: q.ir,
|
|
|
|
OutputStream: q.ow,
|
2024-01-14 20:46:32 +00:00
|
|
|
ErrorStream: nil,
|
|
|
|
Tty: true,
|
|
|
|
RawTerminal: true,
|
|
|
|
Context: context.Background(),
|
|
|
|
})
|
|
|
|
}
|