github.com/tilt-dev/tilt@v0.36.0/internal/k8s/exec.go (about) 1 package k8s 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 9 corev1 "k8s.io/api/core/v1" 10 "k8s.io/apimachinery/pkg/util/httpstream" 11 "k8s.io/client-go/tools/remotecommand" 12 "k8s.io/kubectl/pkg/scheme" 13 14 "github.com/tilt-dev/tilt/internal/container" 15 ) 16 17 func (k *K8sClient) Exec(ctx context.Context, podID PodID, cName container.Name, n Namespace, cmd []string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 18 req := k.core.RESTClient().Post(). 19 Resource("pods"). 20 Namespace(n.String()). 21 Name(podID.String()). 22 SubResource("exec"). 23 Param("container", cName.String()) 24 req.VersionedParams(&corev1.PodExecOptions{ 25 Container: cName.String(), 26 Command: cmd, 27 Stdin: stdin != nil, 28 Stdout: stdout != nil, 29 Stderr: stderr != nil, 30 }, scheme.ParameterCodec) 31 32 spdyExec, err := remotecommand.NewSPDYExecutor(k.restConfig, "POST", req.URL()) 33 if err != nil { 34 return fmt.Errorf("failed to create spdy executor: %w", err) 35 } 36 websocketExec, err := remotecommand.NewWebSocketExecutor(k.restConfig, "GET", req.URL().String()) 37 if err != nil { 38 return fmt.Errorf("failed to create websocket executor: %w", err) 39 } 40 41 exec, _ := remotecommand.NewFallbackExecutor(websocketExec, spdyExec, func(err error) bool { 42 return httpstream.IsUpgradeFailure(err) || httpstream.IsHTTPSProxyError(err) 43 }) 44 45 err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{ 46 Stdin: stdin, 47 Stdout: stdout, 48 Stderr: stderr, 49 }) 50 if err != nil { 51 if err.Error() == "" { 52 // Executor::Stream() attempts to decode metav1.Status errors to 53 // handle non-zero exit codes from commands; unfortunately, for 54 // all _other_ failure cases, the error returned is the `Message` 55 // field, which might be empty and there's no way for us to further 56 // introspect at this point, so a generic message is the best we 57 // can do here 58 return errors.New("unknown server failure") 59 } 60 return err 61 } 62 return nil 63 }