Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit da04d2d

Browse files
author
harry zhang
authored
Merge pull request #133 from YaoZengzeng/grpc-exec
grpc for exec
2 parents 32e3bdc + 3dbcd5f commit da04d2d

File tree

2 files changed

+87
-17
lines changed

2 files changed

+87
-17
lines changed

pkg/kubelet/hyper/hyperclient.go

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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

731791
func (client *HyperClient) ContainerLogs(opts ContainerLogsOptions) error {

pkg/kubelet/hyper/utils.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,13 @@ type nopCloser struct {
2727
func (nopCloser) Close() error {
2828
return nil
2929
}
30+
31+
// getReturnValue wraps calls a function in a goroutine,
32+
// and returns a channel which will later return the function's return value.
33+
func getReturnValue(f func() error) chan error {
34+
ch := make(chan error, 1)
35+
go func() {
36+
ch <- f()
37+
}()
38+
return ch
39+
}

0 commit comments

Comments
 (0)