mirror of
https://github.com/containers/podman
synced 2024-10-20 17:23:30 +00:00
Fix terminal attach
Re-order the startup of a new container via run from initialize > start > attach to initialize > attach > start. This fixes output when running: kpod run -i -t IMAGE command and kpod run IMAGE command Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
parent
5cfd7a313f
commit
acd9c66864
|
@ -10,6 +10,8 @@ host:
|
||||||
|
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
timeout: 45m
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
# mount yum repos to inherit injected mirrors from PAPR
|
# mount yum repos to inherit injected mirrors from PAPR
|
||||||
- docker run --net=host --privileged -v /etc/yum.repos.d:/etc/yum.repos.d.host:ro
|
- docker run --net=host --privileged -v /etc/yum.repos.d:/etc/yum.repos.d.host:ro
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -112,7 +112,7 @@ testunit:
|
||||||
$(GO) test -tags "$(BUILDTAGS)" -cover $(PACKAGES)
|
$(GO) test -tags "$(BUILDTAGS)" -cover $(PACKAGES)
|
||||||
|
|
||||||
localintegration: test-binaries
|
localintegration: test-binaries
|
||||||
./test/test_runner.sh ${TESTFLAGS}
|
bash -i ./test/test_runner.sh ${TESTFLAGS}
|
||||||
|
|
||||||
binaries: conmon kpod
|
binaries: conmon kpod
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,14 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
|
||||||
blkioWeight = uint16(u)
|
blkioWeight = uint16(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because we cannot do a non-terminal attach, we need to set tty to true
|
||||||
|
// if detach is not false
|
||||||
|
// TODO Allow non-terminal attach
|
||||||
|
tty := c.Bool("tty")
|
||||||
|
if !c.Bool("detach") && !tty {
|
||||||
|
tty = true
|
||||||
|
}
|
||||||
|
|
||||||
config := &createConfig{
|
config := &createConfig{
|
||||||
capAdd: c.StringSlice("cap-add"),
|
capAdd: c.StringSlice("cap-add"),
|
||||||
capDrop: c.StringSlice("cap-drop"),
|
capDrop: c.StringSlice("cap-drop"),
|
||||||
|
@ -387,7 +395,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
|
||||||
storageOpts: c.StringSlice("storage-opt"),
|
storageOpts: c.StringSlice("storage-opt"),
|
||||||
sysctl: sysctl,
|
sysctl: sysctl,
|
||||||
tmpfs: c.StringSlice("tmpfs"),
|
tmpfs: c.StringSlice("tmpfs"),
|
||||||
tty: c.Bool("tty"),
|
tty: tty,
|
||||||
user: uid,
|
user: uid,
|
||||||
group: gid,
|
group: gid,
|
||||||
volumes: c.StringSlice("volume"),
|
volumes: c.StringSlice("volume"),
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/projectatomic/libpod/libpod"
|
"github.com/projectatomic/libpod/libpod"
|
||||||
|
@ -91,20 +92,38 @@ func runCmd(c *cli.Context) error {
|
||||||
libpod.WriteFile(ctr.ID(), c.String("cidfile"))
|
libpod.WriteFile(ctr.ID(), c.String("cidfile"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a bool channel to track that the console socket attach
|
||||||
|
// is successful.
|
||||||
|
attached := make(chan bool)
|
||||||
|
// Create a waitgroup so we can sync and wait for all goroutines
|
||||||
|
// to finish before exiting main
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
if !createConfig.detach {
|
||||||
|
// We increment the wg counter because we need to do the attach
|
||||||
|
wg.Add(1)
|
||||||
|
// Attach to the running container
|
||||||
|
go func() {
|
||||||
|
logrus.Debug("trying to attach to the container %s", ctr.ID())
|
||||||
|
defer wg.Done()
|
||||||
|
if err := ctr.Attach(false, c.String("detach-keys"), attached); err != nil {
|
||||||
|
logrus.Errorf("unable to attach to container %s: %q", ctr.ID(), err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if !<-attached {
|
||||||
|
return errors.Errorf("unable to attach to container %s", ctr.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
// Start the container
|
// Start the container
|
||||||
if err := ctr.Start(); err != nil {
|
if err := ctr.Start(); err != nil {
|
||||||
return errors.Wrapf(err, "unable to start container %q", ctr.ID())
|
return errors.Wrapf(err, "unable to start container %q", ctr.ID())
|
||||||
}
|
}
|
||||||
logrus.Debug("started container ", ctr.ID())
|
logrus.Debug("started container ", ctr.ID())
|
||||||
if createConfig.tty {
|
|
||||||
// Attach to the running container
|
if createConfig.detach {
|
||||||
logrus.Debug("trying to attach to the container %s", ctr.ID())
|
|
||||||
if err := ctr.Attach(false, c.String("detach-keys")); err != nil {
|
|
||||||
return errors.Wrapf(err, "unable to attach to container %s", ctr.ID())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%s\n", ctr.ID())
|
fmt.Printf("%s\n", ctr.ID())
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,7 +393,7 @@ func (c *Container) Exec(cmd []string, tty bool, stdin bool) (string, error) {
|
||||||
|
|
||||||
// Attach attaches to a container
|
// Attach attaches to a container
|
||||||
// Returns fully qualified URL of streaming server for the container
|
// Returns fully qualified URL of streaming server for the container
|
||||||
func (c *Container) Attach(noStdin bool, keys string) error {
|
func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error {
|
||||||
// Check the validity of the provided keys first
|
// Check the validity of the provided keys first
|
||||||
var err error
|
var err error
|
||||||
detachKeys := []byte{}
|
detachKeys := []byte{}
|
||||||
|
@ -410,7 +410,7 @@ func (c *Container) Attach(noStdin bool, keys string) error {
|
||||||
}
|
}
|
||||||
resize := make(chan remotecommand.TerminalSize)
|
resize := make(chan remotecommand.TerminalSize)
|
||||||
defer close(resize)
|
defer close(resize)
|
||||||
err = c.attachContainerSocket(resize, noStdin, detachKeys)
|
err = c.attachContainerSocket(resize, noStdin, detachKeys, attached)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package libpod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
@ -25,7 +26,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// attachContainerSocket connects to the container's attach socket and deals with the IO
|
// attachContainerSocket connects to the container's attach socket and deals with the IO
|
||||||
func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, noStdIn bool, detachKeys []byte) error {
|
func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, noStdIn bool, detachKeys []byte, attached chan<- bool) error {
|
||||||
inputStream := os.Stdin
|
inputStream := os.Stdin
|
||||||
outputStream := os.Stdout
|
outputStream := os.Stdout
|
||||||
errorStream := os.Stderr
|
errorStream := os.Stderr
|
||||||
|
@ -38,12 +39,14 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
|
||||||
return errors.Errorf("no tty available for %s", c.ID())
|
return errors.Errorf("no tty available for %s", c.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
oldTermState, err := term.SaveState(inputStream.Fd())
|
if terminal.IsTerminal(int(inputStream.Fd())) {
|
||||||
if err != nil {
|
oldTermState, err := term.SaveState(inputStream.Fd())
|
||||||
return errors.Wrapf(err, "unable to save terminal state")
|
if err != nil {
|
||||||
}
|
return errors.Wrapf(err, "unable to save terminal state")
|
||||||
|
}
|
||||||
|
|
||||||
defer term.RestoreTerminal(inputStream.Fd(), oldTermState)
|
defer term.RestoreTerminal(inputStream.Fd(), oldTermState)
|
||||||
|
}
|
||||||
|
|
||||||
// Put both input and output into raw
|
// Put both input and output into raw
|
||||||
if !noStdIn {
|
if !noStdIn {
|
||||||
|
@ -71,6 +74,9 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
// signal back that the connection was made
|
||||||
|
attached <- true
|
||||||
|
|
||||||
receiveStdoutError := make(chan error)
|
receiveStdoutError := make(chan error)
|
||||||
if outputStream != nil || errorStream != nil {
|
if outputStream != nil || errorStream != nil {
|
||||||
go func() {
|
go func() {
|
||||||
|
|
Loading…
Reference in a new issue