func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *client.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { exec, err := remotecommand.NewExecutor(config, method, url) if err != nil { return err } return exec.Stream(stdin, stdout, stderr, tty) }
func TestForwardPortsReturnsErrorWhenAllBindsFailed(t *testing.T) { server := httptest.NewServer(fakePortForwardServer(t, "allBindsFailed", nil, nil)) defer server.Close() url, _ := url.Parse(server.URL) exec, err := remotecommand.NewExecutor(&client.Config{}, "POST", url) if err != nil { t.Fatal(err) } stopChan1 := make(chan struct{}, 1) defer close(stopChan1) pf1, err := New(exec, []string{"5555"}, stopChan1) if err != nil { t.Fatalf("error creating pf1: %v", err) } go pf1.ForwardPorts() <-pf1.Ready stopChan2 := make(chan struct{}, 1) pf2, err := New(exec, []string{"5555"}, stopChan2) if err != nil { t.Fatalf("error creating pf2: %v", err) } if err := pf2.ForwardPorts(); err == nil { t.Fatal("expected non-nil error for pf2.ForwardPorts") } }
func (*defaultPortForwarder) ForwardPorts(method string, url *url.URL, config *client.Config, ports []string, stopChan <-chan struct{}) error { dialer, err := remotecommand.NewExecutor(config, method, url) if err != nil { return err } fw, err := portforward.New(dialer, ports, stopChan) if err != nil { return err } return fw.ForwardPorts() }
func TestForwardPorts(t *testing.T) { tests := map[string]struct { ports []string clientSends map[uint16]string serverSends map[uint16]string }{ "forward 1 port with no data either direction": { ports: []string{"5000"}, }, "forward 2 ports with bidirectional data": { ports: []string{"5001", "6000"}, clientSends: map[uint16]string{ 5001: "abcd", 6000: "ghij", }, serverSends: map[uint16]string{ 5001: "1234", 6000: "5678", }, }, } for testName, test := range tests { server := httptest.NewServer(fakePortForwardServer(t, testName, test.serverSends, test.clientSends)) url, _ := url.Parse(server.URL) exec, err := remotecommand.NewExecutor(&client.Config{}, "POST", url) if err != nil { t.Fatal(err) } stopChan := make(chan struct{}, 1) pf, err := New(exec, test.ports, stopChan) if err != nil { t.Fatalf("%s: unexpected error calling New: %v", testName, err) } doneChan := make(chan error) go func() { doneChan <- pf.ForwardPorts() }() <-pf.Ready for port, data := range test.clientSends { clientConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port)) if err != nil { t.Errorf("%s: error dialing %d: %s", testName, port, err) server.Close() continue } defer clientConn.Close() n, err := clientConn.Write([]byte(data)) if err != nil && err != io.EOF { t.Errorf("%s: Error sending data '%s': %s", testName, data, err) server.Close() continue } if n == 0 { t.Errorf("%s: unexpected write of 0 bytes", testName) server.Close() continue } b := make([]byte, 4) n, err = clientConn.Read(b) if err != nil && err != io.EOF { t.Errorf("%s: Error reading data: %s", testName, err) server.Close() continue } if !bytes.Equal([]byte(test.serverSends[port]), b) { t.Errorf("%s: expected to read '%s', got '%s'", testName, test.serverSends[port], b) server.Close() continue } } // tell r.ForwardPorts to stop close(stopChan) // wait for r.ForwardPorts to actually return err = <-doneChan if err != nil { t.Errorf("%s: unexpected error: %s", testName, err) } server.Close() } }