From 1a508ccdd18dcf342ac6218334320da9a7ee8f5f Mon Sep 17 00:00:00 2001
From: Adam Reese <adam@reese.io>
Date: Mon, 23 Apr 2018 12:05:45 -0700
Subject: [PATCH] ref(*): move kubeconfig flags to helm/environment

---
 cmd/helm/get.go                          |  4 +---
 cmd/helm/helm.go                         | 19 ++++++++++-----
 cmd/helm/history.go                      |  6 ++---
 cmd/helm/install_test.go                 |  1 +
 cmd/helm/list.go                         |  4 +---
 cmd/helm/status.go                       |  4 +---
 pkg/helm/environment/environment.go      | 20 ++++++++++++----
 pkg/helm/environment/environment_test.go | 30 ++++++++++++++----------
 pkg/kube/config.go                       | 16 +++++--------
 9 files changed, 57 insertions(+), 47 deletions(-)

diff --git a/cmd/helm/get.go b/cmd/helm/get.go
index 35ee7dbff..8e6ff8cc0 100644
--- a/cmd/helm/get.go
+++ b/cmd/helm/get.go
@@ -62,9 +62,7 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
 				return errReleaseRequired
 			}
 			get.release = args[0]
-			if get.client == nil {
-				get.client = newClient()
-			}
+			get.client = ensureHelmClient(get.client)
 			return get.run()
 		},
 	}
diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go
index 5f6adcf5a..89f85a15c 100644
--- a/cmd/helm/helm.go
+++ b/cmd/helm/helm.go
@@ -21,6 +21,7 @@ import (
 	"log"
 	"os"
 	"strings"
+	"sync"
 
 	"github.com/spf13/cobra"
 	// Import to initialize client auth plugins.
@@ -34,8 +35,9 @@ import (
 )
 
 var (
-	settings helm_env.EnvSettings
-	config   clientcmd.ClientConfig
+	settings   helm_env.EnvSettings
+	config     clientcmd.ClientConfig
+	configOnce sync.Once
 )
 
 var globalUsage = `The Kubernetes package manager
@@ -70,8 +72,6 @@ func newRootCmd(args []string) *cobra.Command {
 
 	settings.AddFlags(flags)
 
-	config = kube.GetConfig(flags)
-
 	out := cmd.OutOrStdout()
 
 	cmd.AddCommand(
@@ -159,7 +159,7 @@ func ensureHelmClient(h helm.Interface) helm.Interface {
 }
 
 func newClient() helm.Interface {
-	kc := kube.New(config)
+	kc := kube.New(kubeConfig())
 	kc.Log = logf
 
 	clientset, err := kc.KubernetesClientSet()
@@ -178,8 +178,15 @@ func newClient() helm.Interface {
 	)
 }
 
+func kubeConfig() clientcmd.ClientConfig {
+	configOnce.Do(func() {
+		config = kube.GetConfig(settings.KubeConfig, settings.KubeContext, settings.Namespace)
+	})
+	return config
+}
+
 func getNamespace() string {
-	if ns, _, err := config.Namespace(); err == nil {
+	if ns, _, err := kubeConfig().Namespace(); err == nil {
 		return ns
 	}
 	return "default"
diff --git a/cmd/helm/history.go b/cmd/helm/history.go
index ab5810a67..90efd9db9 100644
--- a/cmd/helm/history.go
+++ b/cmd/helm/history.go
@@ -74,12 +74,10 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command {
 		Short:   "fetch release history",
 		Aliases: []string{"hist"},
 		RunE: func(cmd *cobra.Command, args []string) error {
-			switch {
-			case len(args) == 0:
+			if len(args) == 0 {
 				return errReleaseRequired
-			case his.helmc == nil:
-				his.helmc = newClient()
 			}
+			his.helmc = ensureHelmClient(his.helmc)
 			his.rls = args[0]
 			return his.run()
 		},
diff --git a/cmd/helm/install_test.go b/cmd/helm/install_test.go
index aa828c6ce..8a0aed552 100644
--- a/cmd/helm/install_test.go
+++ b/cmd/helm/install_test.go
@@ -24,6 +24,7 @@ import (
 	"testing"
 
 	"github.com/spf13/cobra"
+
 	"k8s.io/helm/pkg/helm"
 )
 
diff --git a/cmd/helm/list.go b/cmd/helm/list.go
index 793512c72..98b9486e4 100644
--- a/cmd/helm/list.go
+++ b/cmd/helm/list.go
@@ -90,9 +90,7 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
 			if len(args) > 0 {
 				list.filter = strings.Join(args, " ")
 			}
-			if list.client == nil {
-				list.client = newClient()
-			}
+			list.client = ensureHelmClient(list.client)
 			return list.run()
 		},
 	}
diff --git a/cmd/helm/status.go b/cmd/helm/status.go
index 83211eee0..4c7c4f31e 100644
--- a/cmd/helm/status.go
+++ b/cmd/helm/status.go
@@ -67,9 +67,7 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
 				return errReleaseRequired
 			}
 			status.release = args[0]
-			if status.client == nil {
-				status.client = newClient()
-			}
+			status.client = ensureHelmClient(status.client)
 			return status.run()
 		},
 	}
diff --git a/pkg/helm/environment/environment.go b/pkg/helm/environment/environment.go
index 1cc6447e6..1a7de9ac2 100644
--- a/pkg/helm/environment/environment.go
+++ b/pkg/helm/environment/environment.go
@@ -32,20 +32,29 @@ import (
 	"k8s.io/helm/pkg/helm/helmpath"
 )
 
-// DefaultHelmHome is the default HELM_HOME.
-var DefaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm")
+// defaultHelmHome is the default HELM_HOME.
+var defaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm")
 
 // EnvSettings describes all of the environment settings.
 type EnvSettings struct {
 	// Home is the local path to the Helm home directory.
 	Home helmpath.Home
+	// Namespace is the namespace scope.
+	Namespace string
+	// KubeConfig is the path to the kubeconfig file.
+	KubeConfig string
+	// KubeContext is the name of the kubeconfig context.
+	KubeContext string
 	// Debug indicates whether or not Helm is running in Debug mode.
 	Debug bool
 }
 
 // AddFlags binds flags to the given flagset.
 func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
-	fs.StringVar((*string)(&s.Home), "home", DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
+	fs.StringVar((*string)(&s.Home), "home", defaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
+	fs.StringVarP(&s.Namespace, "namespace", "n", "", "namespace scope for this request")
+	fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file")
+	fs.StringVar(&s.KubeContext, "kube-context", "", "name of the kubeconfig context to use")
 	fs.BoolVar(&s.Debug, "debug", false, "enable verbose output")
 }
 
@@ -66,8 +75,9 @@ func (s EnvSettings) PluginDirs() string {
 
 // envMap maps flag names to envvars
 var envMap = map[string]string{
-	"debug": "HELM_DEBUG",
-	"home":  "HELM_HOME",
+	"debug":     "HELM_DEBUG",
+	"home":      "HELM_HOME",
+	"namespace": "HELM_NAMESPACE",
 }
 
 func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) {
diff --git a/pkg/helm/environment/environment_test.go b/pkg/helm/environment/environment_test.go
index 52f51fa66..ebc5822b4 100644
--- a/pkg/helm/environment/environment_test.go
+++ b/pkg/helm/environment/environment_test.go
@@ -31,23 +31,22 @@ func TestEnvSettings(t *testing.T) {
 		name string
 
 		// input
-		args   []string
+		args   string
 		envars map[string]string
 
 		// expected values
-		home, ns, plugins string
-		debug             bool
+		home, ns, kcontext, plugins string
+		debug                       bool
 	}{
 		{
 			name:    "defaults",
-			args:    []string{},
-			home:    DefaultHelmHome,
-			plugins: helmpath.Home(DefaultHelmHome).Plugins(),
-			ns:      "kube-system",
+			home:    defaultHelmHome,
+			plugins: helmpath.Home(defaultHelmHome).Plugins(),
+			ns:      "",
 		},
 		{
 			name:    "with flags set",
-			args:    []string{"--home", "/foo", "--debug"},
+			args:    "--home /foo --debug --namespace=myns",
 			home:    "/foo",
 			plugins: helmpath.Home("/foo").Plugins(),
 			ns:      "myns",
@@ -55,8 +54,7 @@ func TestEnvSettings(t *testing.T) {
 		},
 		{
 			name:    "with envvars set",
-			args:    []string{},
-			envars:  map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1"},
+			envars:  map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns"},
 			home:    "/bar",
 			plugins: helmpath.Home("/bar").Plugins(),
 			ns:      "yourns",
@@ -64,8 +62,8 @@ func TestEnvSettings(t *testing.T) {
 		},
 		{
 			name:    "with flags and envvars set",
-			args:    []string{"--home", "/foo", "--debug"},
-			envars:  map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "HELM_PLUGIN": "glade"},
+			args:    "--home /foo --debug --namespace=myns",
+			envars:  map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"},
 			home:    "/foo",
 			plugins: "glade",
 			ns:      "myns",
@@ -86,7 +84,7 @@ func TestEnvSettings(t *testing.T) {
 
 			settings := &EnvSettings{}
 			settings.AddFlags(flags)
-			flags.Parse(tt.args)
+			flags.Parse(strings.Split(tt.args, " "))
 
 			settings.Init(flags)
 
@@ -99,6 +97,12 @@ func TestEnvSettings(t *testing.T) {
 			if settings.Debug != tt.debug {
 				t.Errorf("expected debug %t, got %t", tt.debug, settings.Debug)
 			}
+			if settings.Namespace != tt.ns {
+				t.Errorf("expected namespace %q, got %q", tt.ns, settings.Namespace)
+			}
+			if settings.KubeContext != tt.kcontext {
+				t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext)
+			}
 
 			cleanup()
 		})
diff --git a/pkg/kube/config.go b/pkg/kube/config.go
index 5538d6008..5038f49c4 100644
--- a/pkg/kube/config.go
+++ b/pkg/kube/config.go
@@ -16,21 +16,17 @@ limitations under the License.
 
 package kube // import "k8s.io/helm/pkg/kube"
 
-import (
-	"github.com/spf13/pflag"
-	"k8s.io/client-go/tools/clientcmd"
-)
+import "k8s.io/client-go/tools/clientcmd"
 
-// GetConfig returns a Kubernetes client config for a given context.
-func GetConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
+// GetConfig returns a Kubernetes client config.
+func GetConfig(kubeconfig, context, namespace string) clientcmd.ClientConfig {
 	rules := clientcmd.NewDefaultClientConfigLoadingRules()
 	rules.DefaultClientConfig = &clientcmd.DefaultClientConfig
-
-	flags.StringVar(&rules.ExplicitPath, "kubeconfig", "", "path to the kubeconfig file to use for CLI requests")
+	rules.ExplicitPath = kubeconfig
 
 	overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}
-	flags.StringVarP(&overrides.Context.Namespace, "namespace", "n", "", "if present, the namespace scope for this CLI request")
-	flags.StringVar(&overrides.CurrentContext, "context", "", "the name of the kubeconfig context to use")
+	overrides.CurrentContext = context
+	overrides.Context.Namespace = namespace
 
 	return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides)
 }
-- 
GitLab