Create separate Settings struct and update usage

Signed-off-by: lucperkins <lucperkins@gmail.com>
pull/8032/head
lucperkins 6 years ago
parent 6fc9353056
commit b25f86ab01

@ -43,7 +43,7 @@ import (
// FeatureGateOCI is the feature gate for checking if `helm chart` and `helm registry` commands should work // FeatureGateOCI is the feature gate for checking if `helm chart` and `helm registry` commands should work
const FeatureGateOCI = gates.Gate("HELM_EXPERIMENTAL_OCI") const FeatureGateOCI = gates.Gate("HELM_EXPERIMENTAL_OCI")
var settings = cli.New() var settings = cli.SettingsFromEnv()
func init() { func init() {
log.SetFlags(log.Lshortfile) log.SetFlags(log.Lshortfile)
@ -72,8 +72,10 @@ func main() {
// run when each command's execute method is called // run when each command's execute method is called
cobra.OnInitialize(func() { cobra.OnInitialize(func() {
helmDriver := os.Getenv("HELM_DRIVER") namespace := settings.GetNamespace()
if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), helmDriver, debug); err != nil { helmDriver := settings.HelmDriver
if err := actionConfig.Init(settings.RESTClientGetter(), namespace, helmDriver, debug); err != nil {
log.Fatal(err) log.Fatal(err)
} }
if helmDriver == "memory" { if helmDriver == "memory" {
@ -141,5 +143,5 @@ func loadReleasesInMemory(actionConfig *action.Configuration) {
} }
} }
// Must reset namespace to the proper one // Must reset namespace to the proper one
mem.SetNamespace(settings.Namespace()) mem.SetNamespace(settings.GetNamespace())
} }

@ -127,7 +127,7 @@ func executeActionCommandStdinC(store *storage.Storage, in *os.File, cmd string)
} }
if mem, ok := store.Driver.(*driver.Memory); ok { if mem, ok := store.Driver.(*driver.Memory); ok {
mem.SetNamespace(settings.Namespace()) mem.SetNamespace(settings.GetNamespace())
} }
c, err := root.ExecuteC() c, err := root.ExecuteC()
@ -163,7 +163,7 @@ func resetEnv() func() {
kv := strings.SplitN(pair, "=", 2) kv := strings.SplitN(pair, "=", 2)
os.Setenv(kv[0], kv[1]) os.Setenv(kv[0], kv[1])
} }
settings = cli.New() settings = cli.SettingsFromEnv()
} }
} }

@ -225,7 +225,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options
} }
} }
client.Namespace = settings.Namespace() client.Namespace = settings.GetNamespace()
return client.Run(chartRequested, vals) return client.Run(chartRequested, vals)
} }

@ -68,7 +68,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
} }
} }
client.Namespace = settings.Namespace() client.Namespace = settings.GetNamespace()
vals, err := valueOpts.MergeValues(getter.All(settings)) vals, err := valueOpts.MergeValues(getter.All(settings))
if err != nil { if err != nil {
return err return err

@ -47,7 +47,7 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
Long: releaseTestHelp, Long: releaseTestHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
client.Namespace = settings.Namespace() client.Namespace = settings.GetNamespace()
rel, runErr := client.Run(args[0]) rel, runErr := client.Run(args[0])
// We only return an error if we weren't even able to get the // We only return an error if we weren't even able to get the
// release, otherwise we keep going so we can print status and logs // release, otherwise we keep going so we can print status and logs

@ -73,7 +73,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: upgradeDesc, Long: upgradeDesc,
Args: require.ExactArgs(2), Args: require.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
client.Namespace = settings.Namespace() client.Namespace = settings.GetNamespace()
// Fixes #7002 - Support reading values from STDIN for `upgrade` command // Fixes #7002 - Support reading values from STDIN for `upgrade` command
// Must load values AFTER determining if we have to call install so that values loaded from stdin are are not read twice // Must load values AFTER determining if we have to call install so that values loaded from stdin are are not read twice

@ -174,7 +174,7 @@ func (d BashCompDirective) string() string {
} }
// NewCompleteCmd add a special hidden command that an be used to request completions // NewCompleteCmd add a special hidden command that an be used to request completions
func NewCompleteCmd(settings *cli.EnvSettings, out io.Writer) *cobra.Command { func NewCompleteCmd(settings *cli.Settings, out io.Writer) *cobra.Command {
debug = settings.Debug debug = settings.Debug
return &cobra.Command{ return &cobra.Command{
Use: fmt.Sprintf("%s [command-line]", CompRequestCmd), Use: fmt.Sprintf("%s [command-line]", CompRequestCmd),

@ -613,7 +613,7 @@ OUTER:
// - URL // - URL
// //
// If 'verify' was set on ChartPathOptions, this will attempt to also verify the chart. // If 'verify' was set on ChartPathOptions, this will attempt to also verify the chart.
func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (string, error) { func (c *ChartPathOptions) LocateChart(name string, settings *cli.Settings) (string, error) {
name = strings.TrimSpace(name) name = strings.TrimSpace(name)
version := strings.TrimSpace(c.Version) version := strings.TrimSpace(c.Version)

@ -38,7 +38,7 @@ import (
type Pull struct { type Pull struct {
ChartPathOptions ChartPathOptions
Settings *cli.EnvSettings // TODO: refactor this out of pkg/action Settings *cli.Settings // TODO: refactor this out of pkg/action
Devel bool Devel bool
Untar bool Untar bool

@ -1,43 +1,18 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*Package cli describes the operating environment for the Helm CLI.
Helm's environment encapsulates all of the service dependencies Helm has.
These dependencies are expressed as interfaces so that alternate implementations
(mocks, etc.) can be easily generated.
*/
package cli package cli
import ( import (
"fmt" "fmt"
"os"
"strconv"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericclioptions"
"helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/helmpath"
"k8s.io/cli-runtime/pkg/genericclioptions"
"os"
"strconv"
) )
// EnvSettings describes all of the environment settings. // Settings describes all of the settings required by the Helm client.
type EnvSettings struct { type Settings struct {
namespace string Namespace string
config *genericclioptions.ConfigFlags HelmDriver string
// KubeConfig is the path to the kubeconfig file // KubeConfig is the path to the kubeconfig file
KubeConfig string KubeConfig string
// KubeContext is the name of the kubeconfig context. // KubeContext is the name of the kubeconfig context.
@ -56,11 +31,15 @@ type EnvSettings struct {
RepositoryCache string RepositoryCache string
// PluginsDirectory is the path to the plugins directory. // PluginsDirectory is the path to the plugins directory.
PluginsDirectory string PluginsDirectory string
config *genericclioptions.ConfigFlags
} }
func New() *EnvSettings { // The default Settings struct for the Helm client, largely drawn from environment variables.
env := &EnvSettings{ func SettingsFromEnv() *Settings {
namespace: os.Getenv("HELM_NAMESPACE"), env := &Settings{
Namespace: os.Getenv("HELM_NAMESPACE"),
HelmDriver: os.Getenv("HELM_DRIVER"),
KubeContext: os.Getenv("HELM_KUBECONTEXT"), KubeContext: os.Getenv("HELM_KUBECONTEXT"),
KubeToken: os.Getenv("HELM_KUBETOKEN"), KubeToken: os.Getenv("HELM_KUBETOKEN"),
KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"), KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"),
@ -73,7 +52,7 @@ func New() *EnvSettings {
// bind to kubernetes config flags // bind to kubernetes config flags
env.config = &genericclioptions.ConfigFlags{ env.config = &genericclioptions.ConfigFlags{
Namespace: &env.namespace, Namespace: &env.Namespace,
Context: &env.KubeContext, Context: &env.KubeContext,
BearerToken: &env.KubeToken, BearerToken: &env.KubeToken,
APIServer: &env.KubeAPIServer, APIServer: &env.KubeAPIServer,
@ -83,8 +62,8 @@ func New() *EnvSettings {
} }
// AddFlags binds flags to the given flagset. // AddFlags binds flags to the given flagset.
func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) { func (s *Settings) AddFlags(fs *pflag.FlagSet) {
fs.StringVarP(&s.namespace, "namespace", "n", s.namespace, "namespace scope for this request") fs.StringVarP(&s.Namespace, "namespace", "n", s.Namespace, "namespace scope for this request")
fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file") fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file")
fs.StringVar(&s.KubeContext, "kube-context", s.KubeContext, "name of the kubeconfig context to use") fs.StringVar(&s.KubeContext, "kube-context", s.KubeContext, "name of the kubeconfig context to use")
fs.StringVar(&s.KubeToken, "kube-token", s.KubeToken, "bearer token used for authentication") fs.StringVar(&s.KubeToken, "kube-token", s.KubeToken, "bearer token used for authentication")
@ -95,6 +74,19 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes") fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes")
} }
// GetNamespace gets the namespace from the configuration
func (s *Settings) GetNamespace() string {
if ns, _, err := s.config.ToRawKubeConfigLoader().Namespace(); err == nil {
return ns
}
return "default"
}
// RESTClientGetter gets the kubeconfig from Settings
func (s *Settings) RESTClientGetter() genericclioptions.RESTClientGetter {
return s.config
}
func envOr(name, def string) string { func envOr(name, def string) string {
if v, ok := os.LookupEnv(name); ok { if v, ok := os.LookupEnv(name); ok {
return v return v
@ -102,7 +94,7 @@ func envOr(name, def string) string {
return def return def
} }
func (s *EnvSettings) EnvVars() map[string]string { func (s *Settings) EnvVars() map[string]string {
envvars := map[string]string{ envvars := map[string]string{
"HELM_BIN": os.Args[0], "HELM_BIN": os.Args[0],
"HELM_DEBUG": fmt.Sprint(s.Debug), "HELM_DEBUG": fmt.Sprint(s.Debug),
@ -110,7 +102,7 @@ func (s *EnvSettings) EnvVars() map[string]string {
"HELM_REGISTRY_CONFIG": s.RegistryConfig, "HELM_REGISTRY_CONFIG": s.RegistryConfig,
"HELM_REPOSITORY_CACHE": s.RepositoryCache, "HELM_REPOSITORY_CACHE": s.RepositoryCache,
"HELM_REPOSITORY_CONFIG": s.RepositoryConfig, "HELM_REPOSITORY_CONFIG": s.RepositoryConfig,
"HELM_NAMESPACE": s.Namespace(), "HELM_NAMESPACE": s.GetNamespace(),
// broken, these are populated from helm flags and not kubeconfig. // broken, these are populated from helm flags and not kubeconfig.
"HELM_KUBECONTEXT": s.KubeContext, "HELM_KUBECONTEXT": s.KubeContext,
@ -123,15 +115,6 @@ func (s *EnvSettings) EnvVars() map[string]string {
return envvars return envvars
} }
// Namespace gets the namespace from the configuration func (s *Settings) validate() error {
func (s *EnvSettings) Namespace() string { return nil
if ns, _, err := s.config.ToRawKubeConfigLoader().Namespace(); err == nil {
return ns
}
return "default"
}
// RESTClientGetter gets the kubeconfig from EnvSettings
func (s *EnvSettings) RESTClientGetter() genericclioptions.RESTClientGetter {
return s.config
} }

@ -71,15 +71,15 @@ func TestEnvSettings(t *testing.T) {
flags := pflag.NewFlagSet("testing", pflag.ContinueOnError) flags := pflag.NewFlagSet("testing", pflag.ContinueOnError)
settings := New() settings := SettingsFromEnv()
settings.AddFlags(flags) settings.AddFlags(flags)
flags.Parse(strings.Split(tt.args, " ")) flags.Parse(strings.Split(tt.args, " "))
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)
} }
if settings.Namespace() != tt.ns { if settings.GetNamespace() != tt.ns {
t.Errorf("expected namespace %q, got %q", tt.ns, settings.Namespace()) t.Errorf("expected namespace %q, got %q", tt.ns, settings.GetNamespace())
} }
if settings.KubeContext != tt.kcontext { if settings.KubeContext != tt.kcontext {
t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext) t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext)
@ -92,7 +92,7 @@ func resetEnv() func() {
origEnv := os.Environ() origEnv := os.Environ()
// ensure any local envvars do not hose us // ensure any local envvars do not hose us
for e := range New().EnvVars() { for e := range SettingsFromEnv().EnvVars() {
os.Unsetenv(e) os.Unsetenv(e)
} }

@ -133,7 +133,7 @@ var httpProvider = Provider{
// All finds all of the registered getters as a list of Provider instances. // All finds all of the registered getters as a list of Provider instances.
// Currently, the built-in getters and the discovered plugins with downloader // Currently, the built-in getters and the discovered plugins with downloader
// notations are collected. // notations are collected.
func All(settings *cli.EnvSettings) Providers { func All(settings *cli.Settings) Providers {
result := Providers{httpProvider} result := Providers{httpProvider}
pluginDownloaders, _ := collectPlugins(settings) pluginDownloaders, _ := collectPlugins(settings)
result = append(result, pluginDownloaders...) result = append(result, pluginDownloaders...)

@ -53,7 +53,7 @@ func TestProviders(t *testing.T) {
} }
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
env := cli.New() env := cli.SettingsFromEnv()
env.PluginsDirectory = pluginDir env.PluginsDirectory = pluginDir
all := All(env) all := All(env)
@ -67,7 +67,7 @@ func TestAll(t *testing.T) {
} }
func TestByScheme(t *testing.T) { func TestByScheme(t *testing.T) {
env := cli.New() env := cli.SettingsFromEnv()
env.PluginsDirectory = pluginDir env.PluginsDirectory = pluginDir
g := All(env) g := All(env)

@ -122,7 +122,7 @@ func TestDownload(t *testing.T) {
})) }))
defer srv.Close() defer srv.Close()
g, err := All(cli.New()).ByScheme("http") g, err := All(cli.SettingsFromEnv()).ByScheme("http")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

@ -30,7 +30,7 @@ import (
// collectPlugins scans for getter plugins. // collectPlugins scans for getter plugins.
// This will load plugins according to the cli. // This will load plugins according to the cli.
func collectPlugins(settings *cli.EnvSettings) (Providers, error) { func collectPlugins(settings *cli.Settings) (Providers, error) {
plugins, err := plugin.FindPlugins(settings.PluginsDirectory) plugins, err := plugin.FindPlugins(settings.PluginsDirectory)
if err != nil { if err != nil {
return nil, err return nil, err
@ -56,7 +56,7 @@ func collectPlugins(settings *cli.EnvSettings) (Providers, error) {
// implemented in plugins. // implemented in plugins.
type pluginGetter struct { type pluginGetter struct {
command string command string
settings *cli.EnvSettings settings *cli.Settings
name string name string
base string base string
opts options opts options
@ -86,7 +86,7 @@ func (p *pluginGetter) Get(href string, options ...Option) (*bytes.Buffer, error
} }
// NewPluginGetter constructs a valid plugin getter // NewPluginGetter constructs a valid plugin getter
func NewPluginGetter(command string, settings *cli.EnvSettings, name, base string) Constructor { func NewPluginGetter(command string, settings *cli.Settings, name, base string) Constructor {
return func(options ...Option) (Getter, error) { return func(options ...Option) (Getter, error) {
result := &pluginGetter{ result := &pluginGetter{
command: command, command: command,

@ -24,10 +24,10 @@ import (
) )
func TestCollectPlugins(t *testing.T) { func TestCollectPlugins(t *testing.T) {
env := cli.New() settings := cli.SettingsFromEnv()
env.PluginsDirectory = pluginDir settings.PluginsDirectory = pluginDir
p, err := collectPlugins(env) p, err := collectPlugins(settings)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -54,9 +54,9 @@ func TestPluginGetter(t *testing.T) {
t.Skip("TODO: refactor this test to work on windows") t.Skip("TODO: refactor this test to work on windows")
} }
env := cli.New() settings := cli.SettingsFromEnv()
env.PluginsDirectory = pluginDir settings.PluginsDirectory = pluginDir
pg := NewPluginGetter("echo", env, "test", ".") pg := NewPluginGetter("echo", settings, "test", ".")
g, err := pg() g, err := pg()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -79,10 +79,10 @@ func TestPluginSubCommands(t *testing.T) {
t.Skip("TODO: refactor this test to work on windows") t.Skip("TODO: refactor this test to work on windows")
} }
env := cli.New() settings := cli.SettingsFromEnv()
env.PluginsDirectory = pluginDir settings.PluginsDirectory = pluginDir
pg := NewPluginGetter("echo -n", env, "test", ".") pg := NewPluginGetter("echo -n", settings, "test", ".")
g, err := pg() g, err := pg()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

@ -79,7 +79,7 @@ func NewHTTPInstaller(source string) (*HTTPInstaller, error) {
return nil, err return nil, err
} }
get, err := getter.All(new(cli.EnvSettings)).ByScheme("http") get, err := getter.All(new(cli.Settings)).ByScheme("http")
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -215,7 +215,7 @@ func FindPlugins(plugdirs string) ([]*Plugin, error) {
// SetupPluginEnv prepares os.Env for plugins. It operates on os.Env because // SetupPluginEnv prepares os.Env for plugins. It operates on os.Env because
// the plugin subsystem itself needs access to the environment variables // the plugin subsystem itself needs access to the environment variables
// created here. // created here.
func SetupPluginEnv(settings *cli.EnvSettings, name, base string) { func SetupPluginEnv(settings *cli.Settings, name, base string) {
env := settings.EnvVars() env := settings.EnvVars()
env["HELM_PLUGIN_NAME"] = name env["HELM_PLUGIN_NAME"] = name
env["HELM_PLUGIN_DIR"] = base env["HELM_PLUGIN_DIR"] = base

Loading…
Cancel
Save