141 lines
3.3 KiB
Go
141 lines
3.3 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
gosignal "os/signal"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/docker/pkg/signal"
|
|
"github.com/docker/docker/pkg/term"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/docker/engine-api/client"
|
|
"github.com/docker/engine-api/types"
|
|
registrytypes "github.com/docker/engine-api/types/registry"
|
|
)
|
|
|
|
// encodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
|
func encodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
|
|
buf, err := json.Marshal(authConfig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return base64.URLEncoding.EncodeToString(buf), nil
|
|
}
|
|
|
|
func (cli *DockerCli) encodeRegistryAuth(index *registrytypes.IndexInfo) (string, error) {
|
|
authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, index)
|
|
return encodeAuthToBase64(authConfig)
|
|
}
|
|
|
|
func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.IndexInfo, cmdName string) client.RequestPrivilegeFunc {
|
|
return func() (string, error) {
|
|
fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
|
|
if err := cli.CmdLogin(registry.GetAuthConfigKey(index)); err != nil {
|
|
return "", err
|
|
}
|
|
return cli.encodeRegistryAuth(index)
|
|
}
|
|
}
|
|
|
|
func (cli *DockerCli) resizeTty(id string, isExec bool) {
|
|
height, width := cli.getTtySize()
|
|
if height == 0 && width == 0 {
|
|
return
|
|
}
|
|
|
|
options := types.ResizeOptions{
|
|
ID: id,
|
|
Height: height,
|
|
Width: width,
|
|
}
|
|
|
|
var err error
|
|
if isExec {
|
|
err = cli.client.ContainerExecResize(options)
|
|
} else {
|
|
err = cli.client.ContainerResize(options)
|
|
}
|
|
|
|
if err != nil {
|
|
logrus.Debugf("Error resize: %s", err)
|
|
}
|
|
}
|
|
|
|
// getExitCode perform an inspect on the container. It returns
|
|
// the running state and the exit code.
|
|
func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
|
|
c, err := cli.client.ContainerInspect(containerID)
|
|
if err != nil {
|
|
// If we can't connect, then the daemon probably died.
|
|
if err != client.ErrConnectionFailed {
|
|
return false, -1, err
|
|
}
|
|
return false, -1, nil
|
|
}
|
|
|
|
return c.State.Running, c.State.ExitCode, nil
|
|
}
|
|
|
|
// getExecExitCode perform an inspect on the exec command. It returns
|
|
// the running state and the exit code.
|
|
func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
|
|
resp, err := cli.client.ContainerExecInspect(execID)
|
|
if err != nil {
|
|
// If we can't connect, then the daemon probably died.
|
|
if err != client.ErrConnectionFailed {
|
|
return false, -1, err
|
|
}
|
|
return false, -1, nil
|
|
}
|
|
|
|
return resp.Running, resp.ExitCode, nil
|
|
}
|
|
|
|
func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
|
|
cli.resizeTty(id, isExec)
|
|
|
|
if runtime.GOOS == "windows" {
|
|
go func() {
|
|
prevH, prevW := cli.getTtySize()
|
|
for {
|
|
time.Sleep(time.Millisecond * 250)
|
|
h, w := cli.getTtySize()
|
|
|
|
if prevW != w || prevH != h {
|
|
cli.resizeTty(id, isExec)
|
|
}
|
|
prevH = h
|
|
prevW = w
|
|
}
|
|
}()
|
|
} else {
|
|
sigchan := make(chan os.Signal, 1)
|
|
gosignal.Notify(sigchan, signal.SIGWINCH)
|
|
go func() {
|
|
for range sigchan {
|
|
cli.resizeTty(id, isExec)
|
|
}
|
|
}()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (cli *DockerCli) getTtySize() (int, int) {
|
|
if !cli.isTerminalOut {
|
|
return 0, 0
|
|
}
|
|
ws, err := term.GetWinsize(cli.outFd)
|
|
if err != nil {
|
|
logrus.Debugf("Error getting size: %s", err)
|
|
if ws == nil {
|
|
return 0, 0
|
|
}
|
|
}
|
|
return int(ws.Height), int(ws.Width)
|
|
}
|