// TODO(random-liu): Add unit test for exec and attach functions, just like what go-dockerclient did.
func (d *kubeDockerClient) CreateExec(id string, opts dockertypes.ExecConfig) (*dockertypes.ContainerExecCreateResponse, error) {
	opts.Container = id
	resp, err := d.client.ContainerExecCreate(getDefaultContext(), opts)
	if err != nil {
		return nil, err
	}
	return &resp, nil
}
Example #2
0
File: exec.go Project: yiduoyunQ/sm
func (s *Swarm) Exec(cmd []string, containName string) (types.HijackedResponse, error) {
	var err error
	defer func() {
		if err != nil {
			log.WithFields(log.Fields{
				"cmd":         cmd,
				"ContainName": containName,
				"err":         err.Error(),
			}).Error("swarm exec error")
		}
	}()
	timeEnd := time.Now().Add(s.config.SwarmRetryTimeoutAll)
	defaultHeaders := map[string]string{"User-Agent": s.config.SwarmUserAgent}

	// for set client.Timeout do what engine-api do start
	// transport = defaultTransport(proto, addr)
	transport := new(http.Transport)
	sockets.ConfigureTransport(transport, "tcp", s.host)
	// for set client.Timeout do what engine-api do end
	c := &http.Client{
		Timeout:   s.config.SwarmRetryTimeout,
		Transport: transport,
	}
	// get last swarm host when connect error and retry once
	bRegetSwarmHost := false
	for i := 1; i <= s.config.SwarmRetryTimes; i++ {
		if timeEnd.Before(time.Now()) {
			return types.HijackedResponse{}, errors.New(fmt.Sprintf("time out after %+v\n", s.config.SwarmRetryTimeoutAll))
		}

		cli, err := client.NewClient("tcp://"+s.host, s.ApiVersion, c, defaultHeaders)
		if err != nil {
			log.WithFields(log.Fields{
				"cmd":         cmd,
				"ContainName": containName,
				"RetryTimes":  i,
				"err":         err.Error(),
			}).Error("swarm NewClient error")
			if !bRegetSwarmHost && s.consul != nil {
				log.Info("try to get swarm host from consul once again")
				bRegetSwarmHost = true
				swarmHost, err := s.consul.GetVal(s.config.SwarmHostKey)
				if err != nil {
					log.WithFields(log.Fields{
						"err": err.Error(),
					}).Error("consul connect error")
					time.Sleep(s.config.SwarmRetryInterval)
				} else if swarmHost == "" {
					log.WithFields(log.Fields{
						"key": s.config.SwarmHostKey,
						"err": err.Error(),
					}).Error("get empty SwarmHost from consul")
					time.Sleep(s.config.SwarmRetryInterval)
				} else {
					log.WithFields(log.Fields{
						"OldSwarmHost": s.host,
						"NewSwarmHost": swarmHost,
					}).Info("swarm host updated from consul")
					s.host = swarmHost
					// retry once
					cli, err = client.NewClient("tcp://"+s.host, s.ApiVersion, c, defaultHeaders)
					if err != nil {
						log.WithFields(log.Fields{
							"err": err.Error(),
						}).Error("swarm reconnect error")
					}
				}
			} else {
				time.Sleep(s.config.SwarmRetryInterval)
				continue
			}
		}

		execConfig := types.ExecConfig{
			Tty:          true,
			Detach:       false,
			AttachStdin:  true,
			AttachStderr: true,
			AttachStdout: true,
		}
		//execConfig.Container = containName
		execConfig.Cmd = cmd

		creres, err := cli.ContainerExecCreate(context.Background(), containName, execConfig)
		if err != nil {
			log.WithFields(log.Fields{
				"cmd":         cmd,
				"ContainName": containName,
				"RetryTimes":  i,
				"err":         err.Error(),
			}).Error("swarm ContainerExecCreate error")
			time.Sleep(s.config.SwarmRetryInterval)
			continue
		}
		res, err := cli.ContainerExecAttach(context.Background(), creres.ID, execConfig)
		if err != nil {
			log.WithFields(log.Fields{
				"cmd":         cmd,
				"ContainName": containName,
				"RetryTimes":  i,
				"err":         err.Error(),
			}).Error("swarm ContainerExecAttach error")
			time.Sleep(s.config.SwarmRetryInterval)
			continue
		}
		return res, nil
	}
	return types.HijackedResponse{}, errors.New(fmt.Sprintf("swarm exec cmd:%+v, containName:%s, retry %d times fail\n", cmd, containName, s.config.SwarmRetryTimes))
}