@@ -29,7 +29,6 @@ import (
2929 "net/http"
3030 "net/http/httputil"
3131 "net/url"
32- "strconv"
3332 "strings"
3433 "time"
3534
@@ -702,30 +701,91 @@ func (client *HyperClient) Exec(opts ExecInContainerOptions) error {
702701 return fmt .Errorf ("No Such Container %s" , opts .Container )
703702 }
704703
705- command , err := json .Marshal (opts .Commands )
704+ createRequest := grpctypes.ExecCreateRequest {
705+ ContainerID : opts .Container ,
706+ Command : opts .Commands ,
707+ Tty : opts .TTY ,
708+ }
709+
710+ createResponse , err := client .client .ExecCreate (context .Background (), & createRequest )
706711 if err != nil {
707712 return err
708713 }
709714
710- v := url.Values {}
711- tag := client .GetTag ()
712- v .Set (KEY_TYPE , TYPE_CONTAINER )
713- v .Set (KEY_VALUE , opts .Container )
714- v .Set (KEY_TAG , tag )
715- v .Set (KEY_COMMAND , string (command ))
716- v .Set (KEY_TTY , strconv .FormatBool (opts .TTY ))
717- path := "/exec?" + v .Encode ()
718- err = client .hijack ("POST" , path , hijackOptions {
719- in : opts .InputStream ,
720- stdout : opts .OutputStream ,
721- stderr : opts .ErrorStream ,
722- tty : opts .TTY ,
723- })
715+ execId := createResponse .ExecID
716+
717+ stream , err := client .client .ExecStart (context .Background ())
724718 if err != nil {
725719 return err
726720 }
727721
728- return client .GetExitCode (opts .Container , tag )
722+ startRequest := grpctypes.ExecStartRequest {
723+ ContainerID : opts .Container ,
724+ ExecID : execId ,
725+ }
726+ err = stream .Send (& startRequest )
727+ if err != nil {
728+ return err
729+ }
730+
731+ var recvStdoutError chan error
732+ if opts .OutputStream != nil {
733+ recvStdoutError = getReturnValue (func () error {
734+ for {
735+ res , err := stream .Recv ()
736+ if err != nil {
737+ if err == io .EOF {
738+ return nil
739+ }
740+ return err
741+ }
742+ n , err := opts .OutputStream .Write (res .Stdout )
743+ if err != nil {
744+ return err
745+ }
746+ if n != len (res .Stdout ) {
747+ return io .ErrShortWrite
748+ }
749+ }
750+ })
751+ }
752+
753+ var reqStdinError chan error
754+ if opts .InputStream != nil {
755+ reqStdinError = getReturnValue (func () error {
756+ for {
757+ req := make ([]byte , 512 )
758+ n , err := opts .InputStream .Read (req )
759+ if err := stream .Send (& grpctypes.ExecStartRequest {Stdin : req [:n ]}); err != nil {
760+ return err
761+ }
762+ if err == io .EOF {
763+ return nil
764+ }
765+ if err != nil {
766+ return err
767+ }
768+ }
769+ })
770+ }
771+
772+ if opts .OutputStream != nil && opts .InputStream != nil {
773+ select {
774+ case err = <- recvStdoutError :
775+ case err = <- reqStdinError :
776+ }
777+ } else if opts .OutputStream != nil {
778+ err = <- recvStdoutError
779+ } else if opts .InputStream != nil {
780+ err = <- reqStdinError
781+ }
782+
783+ if err != nil {
784+ return err
785+ }
786+
787+ //TODO: GetExitCode
788+ return nil
729789}
730790
731791func (client * HyperClient ) ContainerLogs (opts ContainerLogsOptions ) error {
0 commit comments