2014-03-28 19:21:55 -04:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
2015-12-11 23:11:42 -05:00
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
2014-03-28 19:21:55 -04:00
|
|
|
"fmt"
|
2015-12-13 20:25:28 -05:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2014-03-28 19:21:55 -04:00
|
|
|
"os"
|
|
|
|
gosignal "os/signal"
|
2015-12-13 20:25:28 -05:00
|
|
|
"path/filepath"
|
2015-03-26 18:52:16 -04:00
|
|
|
"runtime"
|
|
|
|
"time"
|
2014-03-28 19:21:55 -04:00
|
|
|
|
2015-03-26 18:22:04 -04:00
|
|
|
"github.com/Sirupsen/logrus"
|
2014-11-13 13:40:22 -05:00
|
|
|
"github.com/docker/docker/pkg/signal"
|
2014-07-24 18:19:50 -04:00
|
|
|
"github.com/docker/docker/pkg/term"
|
|
|
|
"github.com/docker/docker/registry"
|
2016-01-04 19:05:26 -05:00
|
|
|
"github.com/docker/engine-api/client"
|
|
|
|
"github.com/docker/engine-api/types"
|
|
|
|
registrytypes "github.com/docker/engine-api/types/registry"
|
2014-03-28 19:21:55 -04:00
|
|
|
)
|
|
|
|
|
2015-12-11 23:11:42 -05:00
|
|
|
// encodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
2015-12-11 21:14:52 -05:00
|
|
|
func encodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
|
2015-12-11 23:11:42 -05:00
|
|
|
buf, err := json.Marshal(authConfig)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return base64.URLEncoding.EncodeToString(buf), nil
|
|
|
|
}
|
|
|
|
|
2015-12-11 21:14:52 -05:00
|
|
|
func (cli *DockerCli) encodeRegistryAuth(index *registrytypes.IndexInfo) (string, error) {
|
2015-12-11 22:11:20 -05:00
|
|
|
authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, index)
|
2015-12-11 21:14:52 -05:00
|
|
|
return encodeAuthToBase64(authConfig)
|
2015-12-06 15:17:34 -05:00
|
|
|
}
|
|
|
|
|
2016-01-04 19:05:26 -05:00
|
|
|
func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.IndexInfo, cmdName string) client.RequestPrivilegeFunc {
|
2015-12-06 15:17:34 -05:00
|
|
|
return func() (string, error) {
|
|
|
|
fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
|
2015-12-11 21:14:52 -05:00
|
|
|
if err := cli.CmdLogin(registry.GetAuthConfigKey(index)); err != nil {
|
2015-12-06 15:17:34 -05:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return cli.encodeRegistryAuth(index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-16 02:43:43 -04:00
|
|
|
func (cli *DockerCli) resizeTty(id string, isExec bool) {
|
2014-03-28 19:21:55 -04:00
|
|
|
height, width := cli.getTtySize()
|
|
|
|
if height == 0 && width == 0 {
|
|
|
|
return
|
|
|
|
}
|
2014-09-16 02:43:43 -04:00
|
|
|
|
2015-12-06 18:41:57 -05:00
|
|
|
options := types.ResizeOptions{
|
|
|
|
ID: id,
|
|
|
|
Height: height,
|
|
|
|
Width: width,
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
2015-12-09 22:55:01 -05:00
|
|
|
if isExec {
|
2015-12-06 18:41:57 -05:00
|
|
|
err = cli.client.ContainerExecResize(options)
|
2014-09-16 02:43:43 -04:00
|
|
|
} else {
|
2015-12-06 18:41:57 -05:00
|
|
|
err = cli.client.ContainerResize(options)
|
2014-09-16 02:43:43 -04:00
|
|
|
}
|
|
|
|
|
2015-12-06 18:41:57 -05:00
|
|
|
if err != nil {
|
2015-03-26 18:22:04 -04:00
|
|
|
logrus.Debugf("Error resize: %s", err)
|
2014-03-28 19:21:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// getExitCode perform an inspect on the container. It returns
|
|
|
|
// the running state and the exit code.
|
2015-03-25 22:31:29 -04:00
|
|
|
func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
|
2015-12-04 14:49:22 -05:00
|
|
|
c, err := cli.client.ContainerInspect(containerID)
|
2014-03-28 19:21:55 -04:00
|
|
|
if err != nil {
|
|
|
|
// If we can't connect, then the daemon probably died.
|
2016-01-04 19:05:26 -05:00
|
|
|
if err != client.ErrConnectionFailed {
|
2014-03-28 19:21:55 -04:00
|
|
|
return false, -1, err
|
|
|
|
}
|
|
|
|
return false, -1, nil
|
|
|
|
}
|
2014-06-04 18:11:11 -04:00
|
|
|
|
2015-04-13 10:17:14 -04:00
|
|
|
return c.State.Running, c.State.ExitCode, nil
|
2014-03-28 19:21:55 -04:00
|
|
|
}
|
|
|
|
|
2014-11-17 18:50:09 -05:00
|
|
|
// getExecExitCode perform an inspect on the exec command. It returns
|
|
|
|
// the running state and the exit code.
|
2015-03-25 22:31:29 -04:00
|
|
|
func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
|
2015-12-06 00:33:38 -05:00
|
|
|
resp, err := cli.client.ContainerExecInspect(execID)
|
2014-11-17 18:50:09 -05:00
|
|
|
if err != nil {
|
|
|
|
// If we can't connect, then the daemon probably died.
|
2016-01-04 19:05:26 -05:00
|
|
|
if err != client.ErrConnectionFailed {
|
2014-11-17 18:50:09 -05:00
|
|
|
return false, -1, err
|
|
|
|
}
|
|
|
|
return false, -1, nil
|
|
|
|
}
|
|
|
|
|
2015-12-06 00:33:38 -05:00
|
|
|
return resp.Running, resp.ExitCode, nil
|
2014-11-17 18:50:09 -05:00
|
|
|
}
|
|
|
|
|
2014-09-16 02:43:43 -04:00
|
|
|
func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
|
|
|
|
cli.resizeTty(id, isExec)
|
2014-03-28 19:21:55 -04:00
|
|
|
|
2015-03-26 18:52:16 -04:00
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
go func() {
|
2015-04-06 17:31:42 -04:00
|
|
|
prevH, prevW := cli.getTtySize()
|
2015-03-26 18:52:16 -04:00
|
|
|
for {
|
|
|
|
time.Sleep(time.Millisecond * 250)
|
2015-04-06 17:31:42 -04:00
|
|
|
h, w := cli.getTtySize()
|
2015-03-26 18:52:16 -04:00
|
|
|
|
|
|
|
if prevW != w || prevH != h {
|
|
|
|
cli.resizeTty(id, isExec)
|
|
|
|
}
|
|
|
|
prevH = h
|
2015-04-06 17:31:42 -04:00
|
|
|
prevW = w
|
2015-03-26 18:52:16 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
sigchan := make(chan os.Signal, 1)
|
|
|
|
gosignal.Notify(sigchan, signal.SIGWINCH)
|
|
|
|
go func() {
|
2015-04-01 18:39:37 -04:00
|
|
|
for range sigchan {
|
2015-03-26 18:52:16 -04:00
|
|
|
cli.resizeTty(id, isExec)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2014-03-28 19:21:55 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *DockerCli) getTtySize() (int, int) {
|
2014-09-10 09:35:48 -04:00
|
|
|
if !cli.isTerminalOut {
|
2014-03-28 19:21:55 -04:00
|
|
|
return 0, 0
|
|
|
|
}
|
2014-09-10 09:35:48 -04:00
|
|
|
ws, err := term.GetWinsize(cli.outFd)
|
2014-03-28 19:21:55 -04:00
|
|
|
if err != nil {
|
2015-03-26 18:22:04 -04:00
|
|
|
logrus.Debugf("Error getting size: %s", err)
|
2014-03-28 19:21:55 -04:00
|
|
|
if ws == nil {
|
|
|
|
return 0, 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return int(ws.Height), int(ws.Width)
|
|
|
|
}
|
2015-12-13 20:25:28 -05:00
|
|
|
|
|
|
|
func copyToFile(outfile string, r io.Reader) error {
|
|
|
|
tmpFile, err := ioutil.TempFile(filepath.Dir(outfile), ".docker_temp_")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpPath := tmpFile.Name()
|
|
|
|
|
|
|
|
_, err = io.Copy(tmpFile, r)
|
|
|
|
tmpFile.Close()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
os.Remove(tmpPath)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = os.Rename(tmpPath, outfile); err != nil {
|
|
|
|
os.Remove(tmpPath)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|