// ForwardPorts will forward a set of ports from a pod, the stopChan will stop the forwarding // when it's closed or receives a struct{} func (f *portForwarder) ForwardPorts(ports []string, stopChan <-chan struct{}) error { req := f.Client.RESTClient.Post(). Resource("pods"). Namespace(f.Namespace). Name(f.PodName). SubResource("portforward") dialer, err := remotecommand.NewExecutor(f.Config, "POST", req.URL()) if err != nil { return err } // TODO: Make os.Stdout/Stderr configurable // TODO: Accept a ready channel? fw, err := portforward.New(dialer, ports, stopChan, nil, f.Out, f.ErrOut) if err != nil { return err } ready := make(chan struct{}) errChan := make(chan error) fw.Ready = ready go func() { errChan <- fw.ForwardPorts() }() select { case <-ready: return nil case err = <-errChan: return err } }
func (*defaultPortForwarder) ForwardPorts(req *client.Request, config *client.Config, ports []string, stopChan <-chan struct{}) error { fw, err := portforward.New(req, config, ports, stopChan) if err != nil { return err } return fw.ForwardPorts() }
// ForwardPort opens a tunnel to a kubernetes pod func (c *Client) ForwardPort(namespace, podName string, remote int) (*Tunnel, error) { client, err := c.Client() if err != nil { return nil, err } config, err := c.ClientConfig() if err != nil { return nil, err } // Build a url to the portforward endpoing // example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward u := client.RESTClient.Post(). Resource("pods"). Namespace(namespace). Name(podName). SubResource("portforward").URL() dialer, err := remotecommand.NewExecutor(config, "POST", u) if err != nil { return nil, err } local, err := getAvailablePort() if err != nil { return nil, err } t := &Tunnel{ Local: local, Remote: remote, stopChan: make(chan struct{}, 1), } ports := []string{fmt.Sprintf("%d:%d", local, remote)} var b bytes.Buffer pf, err := portforward.New(dialer, ports, t.stopChan, &b, &b) if err != nil { return nil, err } errChan := make(chan error) go func() { errChan <- pf.ForwardPorts() }() select { case err = <-errChan: return t, fmt.Errorf("Error forwarding ports: %v\n", err) case <-pf.Ready: return t, nil } }
func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, opts PortForwardOptions) error { dialer, err := remotecommand.NewExecutor(opts.Config, method, url) if err != nil { return err } fw, err := portforward.New(dialer, opts.Ports, opts.StopChannel, opts.ReadyChannel, f.cmdOut, f.cmdErr) if err != nil { return err } return fw.ForwardPorts() }
func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, config *restclient.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, f.cmdOut, f.cmdErr) if err != nil { return err } return fw.ForwardPorts() }
// ForwardPort opens a tunnel to a kubernetes pod func (t *Tunnel) ForwardPort() error { // Build a url to the portforward endpoint // example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward u := t.client.Post(). Resource("pods"). Namespace(t.Namespace). Name(t.PodName). SubResource("portforward").URL() dialer, err := remotecommand.NewExecutor(t.config, "POST", u) if err != nil { return err } local, err := getAvailablePort() if err != nil { return fmt.Errorf("could not find an available port: %s", err) } t.Local = local ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)} pf, err := portforward.New(dialer, ports, t.stopChan, t.readyChan, t.Out, t.Out) if err != nil { return err } errChan := make(chan error) go func() { errChan <- pf.ForwardPorts() }() select { case err = <-errChan: return fmt.Errorf("forwarding ports: %v", err) case <-pf.Ready: return nil } }
// StartForwardingToPod starts forwarding requests to the given pod on the given target port // If no localPort has been defined on the tunnel, a random available port will be assigned // The tunnel is started in the background (using a goroutine), and will need to be stopped with Stop() // It returns an error if it can't start the tunnel. func (tunnel *Tunnel) StartForwardingToPod(podName string, namespace string, targetPort int, restClient *kclientapi.RESTClient, clientConfig *kclientapi.Config) error { req := restClient.Post(). Resource("pods"). Namespace(namespace). Name(podName). SubResource("portforward") if tunnel.LocalPort == 0 { port, err := getRandomAvailableLocalPort() if err != nil { return err } tunnel.LocalPort = port } port := fmt.Sprintf("%v:%v", tunnel.LocalPort, targetPort) ports := []string{port} dialer, err := remotecommand.NewExecutor(clientConfig, "POST", req.URL()) if err != nil { return err } fw, err := portforward.New(dialer, ports, tunnel.stopChan) if err != nil { return err } go func(localPort int) { err = fw.ForwardPorts() if err != nil { fmt.Printf("Failed to forward localPort %v to remotePort %v on pod %s: %v\n", localPort, targetPort, podName, err) } }(tunnel.LocalPort) return nil }