feat(helm): add --port flag to helm

when 'helm --port port-number [cmd]' is run, this will set the local port
for portforward tunnel to port-number.

Closes #2212
pull/3213/head
silenceshell 8 years ago
parent 06be9d7800
commit de5e70930a

@ -173,7 +173,7 @@ func setupConnection(c *cobra.Command, args []string) error {
return err return err
} }
tunnel, err := portforwarder.New(settings.TillerNamespace, client, config) tunnel, err := portforwarder.New(settings.TillerNamespace, client, config, settings.TunnelLocalPort)
if err != nil { if err != nil {
return err return err
} }

@ -20,6 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv"
"strings" "strings"
"testing" "testing"
@ -179,6 +180,7 @@ func TestSetupEnv(t *testing.T) {
{"HELM_PATH_STARTER", settings.Home.Starters()}, {"HELM_PATH_STARTER", settings.Home.Starters()},
{"TILLER_HOST", settings.TillerHost}, {"TILLER_HOST", settings.TillerHost},
{"TILLER_NAMESPACE", settings.TillerNamespace}, {"TILLER_NAMESPACE", settings.TillerNamespace},
{"TUNNEL_LOCAL_PORT", strconv.Itoa(settings.TunnelLocalPort)},
} { } {
if got := os.Getenv(tt.name); got != tt.expect { if got := os.Getenv(tt.name); got != tt.expect {
t.Errorf("Expected $%s=%q, got %q", tt.name, tt.expect, got) t.Errorf("Expected $%s=%q, got %q", tt.name, tt.expect, got)

@ -39,6 +39,8 @@ var DefaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm")
type EnvSettings struct { type EnvSettings struct {
// TillerHost is the host and port of Tiller. // TillerHost is the host and port of Tiller.
TillerHost string TillerHost string
// TunnelLocalPort is the local port for portforward tunnel.
TunnelLocalPort int
// TillerNamespace is the namespace in which Tiller runs. // TillerNamespace is the namespace in which Tiller runs.
TillerNamespace string TillerNamespace string
// Home is the local path to the Helm home directory. // Home is the local path to the Helm home directory.
@ -59,6 +61,7 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to kubeconfig file. Overrides $KUBECONFIG") fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to kubeconfig file. Overrides $KUBECONFIG")
fs.BoolVar(&s.Debug, "debug", false, "enable verbose output") fs.BoolVar(&s.Debug, "debug", false, "enable verbose output")
fs.StringVar(&s.TillerNamespace, "tiller-namespace", "kube-system", "namespace of Tiller") fs.StringVar(&s.TillerNamespace, "tiller-namespace", "kube-system", "namespace of Tiller")
fs.IntVar(&s.TunnelLocalPort, "port", 0, "local port for portforward tunnel. Overrides $TUNNEL_LOCAL_PORT")
} }
// Init sets values from the environment. // Init sets values from the environment.
@ -83,6 +86,7 @@ var envMap = map[string]string{
"host": "HELM_HOST", "host": "HELM_HOST",
"kubeconfig": "KUBECONFIG", "kubeconfig": "KUBECONFIG",
"tiller-namespace": "TILLER_NAMESPACE", "tiller-namespace": "TILLER_NAMESPACE",
"port": "TUNNEL_LOCAL_PORT",
} }
func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) { func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) {

@ -37,6 +37,7 @@ func TestEnvSettings(t *testing.T) {
// expected values // expected values
home, host, ns, kcontext, plugins string home, host, ns, kcontext, plugins string
debug bool debug bool
port int
}{ }{
{ {
name: "defaults", name: "defaults",
@ -47,30 +48,33 @@ func TestEnvSettings(t *testing.T) {
}, },
{ {
name: "with flags set", name: "with flags set",
args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns", "--port=44443"},
home: "/foo", home: "/foo",
plugins: helmpath.Home("/foo").Plugins(), plugins: helmpath.Home("/foo").Plugins(),
host: "here", host: "here",
ns: "myns", ns: "myns",
debug: true, debug: true,
port: 44443,
}, },
{ {
name: "with envvars set", name: "with envvars set",
args: []string{}, args: []string{},
envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns"}, envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "TUNNEL_LOCAL_PORT": "44444"},
home: "/bar", home: "/bar",
plugins: helmpath.Home("/bar").Plugins(), plugins: helmpath.Home("/bar").Plugins(),
host: "there", host: "there",
ns: "yourns", ns: "yourns",
debug: true, debug: true,
port: 44444,
}, },
{ {
name: "with flags and envvars set", name: "with flags and envvars set",
args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns"}, args: []string{"--home", "/foo", "--host=here", "--debug", "--tiller-namespace=myns", "--port=44443"},
envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"}, envars: map[string]string{"HELM_HOME": "/bar", "HELM_HOST": "there", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade", "TUNNEL_LOCAL_PORT": "44444"},
home: "/foo", home: "/foo",
plugins: "glade", plugins: "glade",
host: "here", host: "here",
port: 44443,
ns: "myns", ns: "myns",
debug: true, debug: true,
}, },
@ -102,6 +106,9 @@ func TestEnvSettings(t *testing.T) {
if settings.TillerHost != tt.host { if settings.TillerHost != tt.host {
t.Errorf("expected host %q, got %q", tt.host, settings.TillerHost) t.Errorf("expected host %q, got %q", tt.host, settings.TillerHost)
} }
if settings.TunnelLocalPort != tt.port {
t.Errorf("expected port %d, got %d", tt.port, settings.TunnelLocalPort)
}
if settings.Debug != tt.debug { if settings.Debug != tt.debug {
t.Errorf("expected debug %t, got %t", tt.debug, settings.Debug) t.Errorf("expected debug %t, got %t", tt.debug, settings.Debug)
} }

@ -34,14 +34,14 @@ var (
) )
// New creates a new and initialized tunnel. // New creates a new and initialized tunnel.
func New(namespace string, client kubernetes.Interface, config *rest.Config) (*kube.Tunnel, error) { func New(namespace string, client kubernetes.Interface, config *rest.Config, localPort int) (*kube.Tunnel, error) {
podName, err := getTillerPodName(client.CoreV1(), namespace) podName, err := getTillerPodName(client.CoreV1(), namespace)
if err != nil { if err != nil {
return nil, err return nil, err
} }
const tillerPort = 44134 const tillerPort = 44134
t := kube.NewTunnel(client.Core().RESTClient(), config, namespace, podName, tillerPort) t := kube.NewTunnel(client.Core().RESTClient(), config, namespace, podName, tillerPort)
return t, t.ForwardPort() return t, t.ForwardPort(localPort)
} }
func getTillerPodName(client corev1.PodsGetter, namespace string) (string, error) { func getTillerPodName(client corev1.PodsGetter, namespace string) (string, error) {

@ -62,7 +62,7 @@ func (t *Tunnel) Close() {
} }
// ForwardPort opens a tunnel to a kubernetes pod // ForwardPort opens a tunnel to a kubernetes pod
func (t *Tunnel) ForwardPort() error { func (t *Tunnel) ForwardPort(localPort int) error {
// Build a url to the portforward endpoint // Build a url to the portforward endpoint
// example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward // example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward
u := t.client.Post(). u := t.client.Post().
@ -77,11 +77,15 @@ func (t *Tunnel) ForwardPort() error {
} }
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", u) dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", u)
local, err := getAvailablePort() if localPort == 0 {
if err != nil { local, err := getAvailablePort()
return fmt.Errorf("could not find an available port: %s", err) if err != nil {
return fmt.Errorf("could not find an available port: %s", err)
}
t.Local = local
} else {
t.Local = localPort
} }
t.Local = local
ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)} ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)}

@ -19,6 +19,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
helm_env "k8s.io/helm/pkg/helm/environment" helm_env "k8s.io/helm/pkg/helm/environment"
@ -190,6 +191,8 @@ func SetupPluginEnv(settings helm_env.EnvSettings,
"TILLER_HOST": settings.TillerHost, "TILLER_HOST": settings.TillerHost,
"TILLER_NAMESPACE": settings.TillerNamespace, "TILLER_NAMESPACE": settings.TillerNamespace,
"TUNNEL_LOCAL_PORT": strconv.Itoa(settings.TunnelLocalPort),
} { } {
os.Setenv(key, val) os.Setenv(key, val)
} }

Loading…
Cancel
Save