diff --git a/cmd/helm/delete.go b/cmd/helm/delete.go index dabc11c76..73187ee82 100644 --- a/cmd/helm/delete.go +++ b/cmd/helm/delete.go @@ -18,12 +18,13 @@ deleting them. var deleteDryRun bool var deleteCommand = &cobra.Command{ - Use: "delete [flags] RELEASE_NAME", - Aliases: []string{"del"}, - SuggestFor: []string{"remove", "rm"}, - Short: "Given a release name, delete the release from Kubernetes", - Long: deleteDesc, - RunE: delRelease, + Use: "delete [flags] RELEASE_NAME", + Aliases: []string{"del"}, + SuggestFor: []string{"remove", "rm"}, + Short: "Given a release name, delete the release from Kubernetes", + Long: deleteDesc, + RunE: delRelease, + PersistentPreRunE: setupConnection, } func init() { diff --git a/cmd/helm/get.go b/cmd/helm/get.go index 9bc976d8f..015cb815b 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -46,10 +46,11 @@ var getOut = "" var errReleaseRequired = errors.New("release name is required") var getCommand = &cobra.Command{ - Use: "get [flags] RELEASE_NAME", - Short: "Download a named release", - Long: getHelp, - RunE: getCmd, + Use: "get [flags] RELEASE_NAME", + Short: "Download a named release", + Long: getHelp, + RunE: getCmd, + PersistentPreRunE: setupConnection, } var getValuesCommand = &cobra.Command{ diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index 9590ead7e..d995f5eaf 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -35,22 +35,22 @@ It will also set up any necessary local configuration. Common actions from this point include: -- helm search: search for charts -- helm fetch: download a chart to your local directory to view -- helm install: upload the chart to Kubernetes -- helm list: list releases of charts +- helm search: search for charts +- helm fetch: download a chart to your local directory to view +- helm install: upload the chart to Kubernetes +- helm list: list releases of charts Environment: - $HELM_HOME Set an alternative location for Helm files. By default, these are stored in ~/.helm - $HELM_HOST Set an alternative Tiller host. The format is host:port (default ":44134"). + $HELM_HOME Set an alternative location for Helm files. By default, these are stored in ~/.helm + $HELM_HOST Set an alternative Tiller host. The format is host:port (default ":44134"). ` // RootCommand is the top-level command for Helm. var RootCommand = &cobra.Command{ - Use: "helm", - Short: "The Helm package manager for Kubernetes.", - Long: globalUsage, - PersistentPreRun: bootstrap, + Use: "helm", + Short: "The Helm package manager for Kubernetes.", + Long: globalUsage, + PersistentPostRun: teardown, } func init() { @@ -59,9 +59,6 @@ func init() { home = "$HOME/.helm" } thost := os.Getenv(hostEnvVar) - if thost == "" { - thost = defaultHost - } p := RootCommand.PersistentFlags() p.StringVar(&helmHome, "home", home, "location of your Helm config. Overrides $HELM_HOME.") p.StringVar(&tillerHost, "host", thost, "address of tiller. Overrides $HELM_HOST.") @@ -74,12 +71,32 @@ func main() { } } -func bootstrap(c *cobra.Command, args []string) { +func setupConnection(c *cobra.Command, args []string) error { + if tillerHost == "" { + // Should failure fall back to default host? + tunnel, err := newTillerPortForwarder() + if err != nil { + return err + } + + tillerHost = fmt.Sprintf(":%d", tunnel.Local) + if flagVerbose { + fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local) + } + } + // Set up the gRPC config. helm.Config.ServAddr = tillerHost if flagVerbose { fmt.Printf("Server: %q\n", helm.Config.ServAddr) } + return nil +} + +func teardown(c *cobra.Command, args []string) { + if tunnel != nil { + tunnel.Close() + } } func checkArgsLength(expectedNum, actualNum int, requiredArgs ...string) error { diff --git a/cmd/helm/install.go b/cmd/helm/install.go index 3863a0a69..c1a260cda 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -35,10 +35,11 @@ var ( ) var installCmd = &cobra.Command{ - Use: "install [CHART]", - Short: "install a chart archive.", - Long: installDesc, - RunE: runInstall, + Use: "install [CHART]", + Short: "install a chart archive.", + Long: installDesc, + RunE: runInstall, + PersistentPreRunE: setupConnection, } func init() { diff --git a/cmd/helm/list.go b/cmd/helm/list.go index 1f1bd0fca..2a8751845 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -37,11 +37,12 @@ flag with the '--offset' flag allows you to page through results. ` var listCommand = &cobra.Command{ - Use: "list [flags] [FILTER]", - Short: "List releases", - Long: listHelp, - RunE: listCmd, - Aliases: []string{"ls"}, + Use: "list [flags] [FILTER]", + Short: "List releases", + Long: listHelp, + RunE: listCmd, + Aliases: []string{"ls"}, + PersistentPreRunE: setupConnection, } var ( diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 7a14cc6f0..6e6afa97c 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -13,10 +13,11 @@ This command shows the status of a named release. ` var statusCommand = &cobra.Command{ - Use: "status [flags] RELEASE_NAME", - Short: "Displays the status of the named release", - Long: statusHelp, - RunE: status, + Use: "status [flags] RELEASE_NAME", + Short: "Displays the status of the named release", + Long: statusHelp, + RunE: status, + PersistentPreRunE: setupConnection, } func init() { diff --git a/cmd/helm/tunnel.go b/cmd/helm/tunnel.go index 34e696e51..97de02960 100644 --- a/cmd/helm/tunnel.go +++ b/cmd/helm/tunnel.go @@ -9,12 +9,17 @@ import ( "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 } - return kube.New(nil).ForwardPort("helm", podName, 44134) + // FIXME use a constain that is accessable on init + const tillerPort = 44134 + return kube.New(nil).ForwardPort("helm", podName, tillerPort) } func getTillerPodName(namespace string) (string, error) { @@ -23,6 +28,7 @@ func getTillerPodName(namespace string) (string, error) { 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)