github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/api/client/utils.go (about)

     1  package client
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	gosignal "os/signal"
    11  	"path/filepath"
    12  	"runtime"
    13  	"time"
    14  
    15  	"github.com/Sirupsen/logrus"
    16  	"github.com/docker/docker/pkg/signal"
    17  	"github.com/docker/docker/pkg/term"
    18  	"github.com/docker/docker/registry"
    19  	"github.com/docker/engine-api/client"
    20  	"github.com/docker/engine-api/types"
    21  	registrytypes "github.com/docker/engine-api/types/registry"
    22  )
    23  
    24  func (cli *DockerCli) electAuthServer() string {
    25  	// The daemon `/info` endpoint informs us of the default registry being
    26  	// used. This is essential in cross-platforms environment, where for
    27  	// example a Linux client might be interacting with a Windows daemon, hence
    28  	// the default registry URL might be Windows specific.
    29  	serverAddress := registry.IndexServer
    30  	if info, err := cli.client.Info(); err != nil {
    31  		fmt.Fprintf(cli.out, "Warning: failed to get default registry endpoint from daemon (%v). Using system default: %s\n", err, serverAddress)
    32  	} else {
    33  		serverAddress = info.IndexServerAddress
    34  	}
    35  	return serverAddress
    36  }
    37  
    38  // encodeAuthToBase64 serializes the auth configuration as JSON base64 payload
    39  func encodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
    40  	buf, err := json.Marshal(authConfig)
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  	return base64.URLEncoding.EncodeToString(buf), nil
    45  }
    46  
    47  func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.IndexInfo, cmdName string) client.RequestPrivilegeFunc {
    48  	return func() (string, error) {
    49  		fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
    50  		indexServer := registry.GetAuthConfigKey(index)
    51  		authConfig, err := cli.configureAuth("", "", indexServer, false)
    52  		if err != nil {
    53  			return "", err
    54  		}
    55  		return encodeAuthToBase64(authConfig)
    56  	}
    57  }
    58  
    59  func (cli *DockerCli) resizeTty(id string, isExec bool) {
    60  	height, width := cli.getTtySize()
    61  	cli.resizeTtyTo(id, height, width, isExec)
    62  }
    63  
    64  func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
    65  	if height == 0 && width == 0 {
    66  		return
    67  	}
    68  
    69  	options := types.ResizeOptions{
    70  		ID:     id,
    71  		Height: height,
    72  		Width:  width,
    73  	}
    74  
    75  	var err error
    76  	if isExec {
    77  		err = cli.client.ContainerExecResize(options)
    78  	} else {
    79  		err = cli.client.ContainerResize(options)
    80  	}
    81  
    82  	if err != nil {
    83  		logrus.Debugf("Error resize: %s", err)
    84  	}
    85  }
    86  
    87  // getExitCode perform an inspect on the container. It returns
    88  // the running state and the exit code.
    89  func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
    90  	c, err := cli.client.ContainerInspect(containerID)
    91  	if err != nil {
    92  		// If we can't connect, then the daemon probably died.
    93  		if err != client.ErrConnectionFailed {
    94  			return false, -1, err
    95  		}
    96  		return false, -1, nil
    97  	}
    98  
    99  	return c.State.Running, c.State.ExitCode, nil
   100  }
   101  
   102  // getExecExitCode perform an inspect on the exec command. It returns
   103  // the running state and the exit code.
   104  func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
   105  	resp, err := cli.client.ContainerExecInspect(execID)
   106  	if err != nil {
   107  		// If we can't connect, then the daemon probably died.
   108  		if err != client.ErrConnectionFailed {
   109  			return false, -1, err
   110  		}
   111  		return false, -1, nil
   112  	}
   113  
   114  	return resp.Running, resp.ExitCode, nil
   115  }
   116  
   117  func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
   118  	cli.resizeTty(id, isExec)
   119  
   120  	if runtime.GOOS == "windows" {
   121  		go func() {
   122  			prevH, prevW := cli.getTtySize()
   123  			for {
   124  				time.Sleep(time.Millisecond * 250)
   125  				h, w := cli.getTtySize()
   126  
   127  				if prevW != w || prevH != h {
   128  					cli.resizeTty(id, isExec)
   129  				}
   130  				prevH = h
   131  				prevW = w
   132  			}
   133  		}()
   134  	} else {
   135  		sigchan := make(chan os.Signal, 1)
   136  		gosignal.Notify(sigchan, signal.SIGWINCH)
   137  		go func() {
   138  			for range sigchan {
   139  				cli.resizeTty(id, isExec)
   140  			}
   141  		}()
   142  	}
   143  	return nil
   144  }
   145  
   146  func (cli *DockerCli) getTtySize() (int, int) {
   147  	if !cli.isTerminalOut {
   148  		return 0, 0
   149  	}
   150  	ws, err := term.GetWinsize(cli.outFd)
   151  	if err != nil {
   152  		logrus.Debugf("Error getting size: %s", err)
   153  		if ws == nil {
   154  			return 0, 0
   155  		}
   156  	}
   157  	return int(ws.Height), int(ws.Width)
   158  }
   159  
   160  func copyToFile(outfile string, r io.Reader) error {
   161  	tmpFile, err := ioutil.TempFile(filepath.Dir(outfile), ".docker_temp_")
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	tmpPath := tmpFile.Name()
   167  
   168  	_, err = io.Copy(tmpFile, r)
   169  	tmpFile.Close()
   170  
   171  	if err != nil {
   172  		os.Remove(tmpPath)
   173  		return err
   174  	}
   175  
   176  	if err = os.Rename(tmpPath, outfile); err != nil {
   177  		os.Remove(tmpPath)
   178  		return err
   179  	}
   180  
   181  	return nil
   182  }
   183  
   184  // resolveAuthConfig is like registry.ResolveAuthConfig, but if using the
   185  // default index, it uses the default index name for the daemon's platform,
   186  // not the client's platform.
   187  func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.AuthConfig {
   188  	configKey := index.Name
   189  	if index.Official {
   190  		configKey = cli.electAuthServer()
   191  	}
   192  
   193  	a, _ := getCredentials(cli.configFile, configKey)
   194  	return a
   195  }
   196  
   197  func (cli *DockerCli) retrieveAuthConfigs() map[string]types.AuthConfig {
   198  	acs, _ := getAllCredentials(cli.configFile)
   199  	return acs
   200  }