mirror of https://github.com/helm/helm
commit
5d040ec181
@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
|
||||||
|
"github.com/kubernetes/helm/pkg/kube"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO refactor out this global var
|
||||||
|
var tunnel *kube.Tunnel
|
||||||
|
|
||||||
|
func newTillerPortForwarder() (*kube.Tunnel, error) {
|
||||||
|
podName, err := getTillerPodName("helm")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// FIXME use a constain that is accessible on init
|
||||||
|
const tillerPort = 44134
|
||||||
|
return kube.New(nil).ForwardPort("helm", podName, tillerPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTillerPodName(namespace string) (string, error) {
|
||||||
|
client, err := kube.New(nil).Client()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO use a const for labels
|
||||||
|
selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
|
||||||
|
options := api.ListOptions{LabelSelector: selector}
|
||||||
|
pods, err := client.Pods(namespace).List(options)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(pods.Items) < 1 {
|
||||||
|
return "", fmt.Errorf("I could not find tiller")
|
||||||
|
}
|
||||||
|
return pods.Items[0].ObjectMeta.GetName(), nil
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/kubernetes/helm/pkg/version"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RootCommand.AddCommand(versionCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Print the client version information.",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println(version.Version)
|
||||||
|
},
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package kube
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/client/unversioned/portforward"
|
||||||
|
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tunnel describes a ssh-like tunnel to a kubernetes pod
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a url to the portforward endpoing
|
||||||
|
// example: http://localhost: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)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// Package version represents the current version of the project.
|
||||||
|
package version
|
||||||
|
|
||||||
|
// Version is the current version of the Helm.
|
||||||
|
// Update this whenever making a new release.
|
||||||
|
// The version is of the format Major.Minor.Patch
|
||||||
|
// Increment major number for new feature additions and behavioral changes.
|
||||||
|
// Increment minor number for bug fixes and performance enhancements.
|
||||||
|
// Increment patch number for critical fixes to existing releases.
|
||||||
|
var Version = "v2.0.0-alpha.1"
|
Loading…
Reference in new issue