mirror of https://github.com/helm/helm
Merge pull request #757 from adamreese/feat/tunnel2
feat(kube): create tunnel for clientpull/758/head
commit
7241ac9263
@ -0,0 +1,92 @@
|
||||
package kube
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/portforward"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
|
||||
)
|
||||
|
||||
type Tunnel struct {
|
||||
Local int
|
||||
Remote int
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
// Close disconnects a tunnel connection
|
||||
func (t *Tunnel) Close() {
|
||||
close(t.stopChan)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// http://192.168.64.94:8080/api/v1/namespaces/helm/pods/tiller-rc-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
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := pf.ForwardPorts(); err != nil {
|
||||
fmt.Printf("Error forwarding ports: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// wait for listeners to start
|
||||
<-pf.Ready
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func getAvailablePort() (int, error) {
|
||||
l, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
_, p, err := net.SplitHostPort(l.Addr().String())
|
||||
port, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return port, err
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package kube
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAvailablePort(t *testing.T) {
|
||||
port, err := getAvailablePort()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if port < 1 {
|
||||
t.Fatalf("generated port should be > 1, got %d", port)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue