// ExecInContainer exec a command in container with specified io, tty and timeout
ExecInContainer exec a command in container with specified io, tty and timeout
// ExecInContainer exec a command in container with specified io tty and timeout
func (c *Client) ExecInContainer(containerId string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
	execID, err := c.ContainerExecCreate(containerId, cmd, tty)
	if err != nil {
		return err
	}
	req := types.ExecStartRequest{
		ContainerID: containerId,
		ExecID:      execID,
	}
	var (
		ctx    context.Context
		cancel context.CancelFunc
	)
	if timeout > 0 {
		ctx, cancel = getContextWithTimeout(timeout)
	} else if timeout == 0 {
		ctx, cancel = getContextWithCancel()
	} else {
		return fmt.Errorf("timeout should be non-negative")
	}
	defer cancel()
	kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
		if err := c.TTYResize(containerId, execID, int32(size.Height), int32(size.Width)); err != nil {
			glog.Errorf("Resize tty failed: %v", err)
		}
	})
	stream, err := c.client.ExecStart(ctx)
	if err != nil {
		return err
	}
	if err := stream.Send(&req); err != nil {
		return err
	}
	var recvStdoutError chan error
	extractor := NewExtractor(tty)
	if stdout != nil || stderr != nil {
		recvStdoutError = promiseGo(func() (err error) {
			for {
				out, err := stream.Recv()
				if err != nil && err != io.EOF {
					return err
				}
				if out != nil && out.Stdout != nil {
					so, se, ee := extractor.Extract(out.Stdout)
					if ee != nil {
						return ee
					}
					if len(so) > 0 && stdout != nil {
						nw, ew := stdout.Write(so)
						if ew != nil {
							return ew
						}
						if nw != len(so) {
							return io.ErrShortWrite
						}
					}
					if len(se) > 0 && stderr != nil {
						nw, ew := stderr.Write(se)
						if ew != nil {
							return ew
						}
						if nw != len(se) {
							return io.ErrShortWrite
						}
					}
				}
				if err == io.EOF {
					break
				}
			}
			return nil
		})
	}
	if stdin != nil {
		go func() error {
			defer stream.CloseSend()
			buf := make([]byte, 1024)
			for {
				nr, err := stdin.Read(buf)
				if nr > 0 {
					if err := stream.Send(&types.ExecStartRequest{Stdin: buf[:nr]}); err != nil {
						return err
					}
				}
				if err == io.EOF {
					break
				}
				if err != nil {
					return err
				}
			}
			return nil
		}()
	}
	if stdout != nil || stderr != nil {
		if err := <-recvStdoutError; err != nil {
			return err
		}
	}
	exitCode, err := c.Wait(containerId, execID, false)
	if err != nil {
		return err
	}
	return utilexec.CodeExitError{Err: fmt.Errorf("Exit with code %d", exitCode), Code: int(exitCode)}
}
func ( c * Client ) ExecInContainer ( containerId string , cmd [ ] string , stdin io . Reader , stdout , stderr io . WriteCloser , tty bool , resize <- chan remotecommand . TerminalSize , timeout time . Duration ) error { execID , err := c . ContainerExecCreate ( containerId , cmd , tty ) if err != nil { return err } req := types . ExecStartRequest { ContainerID : containerId , ExecID : execID , } var ( ctx context . Context cancel context . CancelFunc ) if timeout > 0 { ctx , cancel = getContextWithTimeout ( timeout ) } else if timeout == 0 { ctx , cancel = getContextWithCancel ( ) } else { return fmt . Errorf ( " " ) } defer cancel ( ) kubecontainer . HandleResizing ( resize , func ( size remotecommand . TerminalSize ) { if err := c . TTYResize ( containerId , execID , int32 ( size . Height ) , int32 ( size . Width ) ) ; err != nil { glog . Errorf ( " " , err ) } } ) stream , err := c . client . ExecStart ( ctx ) if err != nil { return err } if err := stream . Send ( & req ) ; err != nil { return err } var recvStdoutError chan error extractor := NewExtractor ( tty ) if stdout != nil || stderr != nil { recvStdoutError = promiseGo ( func ( ) ( err error ) { for { out , err := stream . Recv ( ) if err != nil && err != io . EOF { return err } if out != nil && out . Stdout != nil { so , se , ee := extractor . Extract ( out . Stdout ) if ee != nil { return ee } if len ( so ) > 0 && stdout != nil { nw , ew := stdout . Write ( so ) if ew != nil { return ew } if nw != len ( so ) { return io . ErrShortWrite } } if len ( se ) > 0 && stderr != nil { nw , ew := stderr . Write ( se ) if ew != nil { return ew } if nw != len ( se ) { return io . ErrShortWrite } } } if err == io . EOF { break } } return nil } ) } if stdin != nil { go func ( ) error { defer stream . CloseSend ( ) buf := make ( [ ] byte , 1024 ) for { nr , err := stdin . Read ( buf ) if nr > 0 { if err := stream . Send ( & types . ExecStartRequest { Stdin : buf [ : nr ] } ) ; err != nil { return err } } if err == io . EOF { break } if err != nil { return err } } return nil } ( ) } if stdout != nil || stderr != nil { if err := <- recvStdoutError ; err != nil { return err } } exitCode , err := c . Wait ( containerId , execID , false ) if err != nil { return err } return utilexec . CodeExitError { Err : fmt . Errorf ( " " , exitCode ) , Code : int ( exitCode ) } }
ExecInContainer exec a command in container with specified io, tty and timeout
ExecInContainer exec a command in container with specified io tty and timeout
// get exit code