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