github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/cli/environment.go (about) 1 /* 2 Copyright The Helm Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 /*Package cli describes the operating environment for the Helm CLI. 18 19 Helm's environment encapsulates all of the service dependencies Helm has. 20 These dependencies are expressed as interfaces so that alternate implementations 21 (mocks, etc.) can be easily generated. 22 */ 23 package cli 24 25 import ( 26 "fmt" 27 "net/http" 28 "os" 29 "strconv" 30 "strings" 31 32 "github.com/spf13/pflag" 33 "k8s.io/cli-runtime/pkg/genericclioptions" 34 "k8s.io/client-go/rest" 35 36 "github.com/stefanmcshane/helm/pkg/helmpath" 37 ) 38 39 // defaultMaxHistory sets the maximum number of releases to 0: unlimited 40 const defaultMaxHistory = 10 41 42 // defaultBurstLimit sets the default client-side throttling limit 43 const defaultBurstLimit = 100 44 45 // EnvSettings describes all of the environment settings. 46 type EnvSettings struct { 47 namespace string 48 config *genericclioptions.ConfigFlags 49 50 // KubeConfig is the path to the kubeconfig file 51 KubeConfig string 52 // KubeContext is the name of the kubeconfig context. 53 KubeContext string 54 // Bearer KubeToken used for authentication 55 KubeToken string 56 // Username to impersonate for the operation 57 KubeAsUser string 58 // Groups to impersonate for the operation, multiple groups parsed from a comma delimited list 59 KubeAsGroups []string 60 // Kubernetes API Server Endpoint for authentication 61 KubeAPIServer string 62 // Custom certificate authority file. 63 KubeCaFile string 64 // KubeInsecureSkipTLSVerify indicates if server's certificate will not be checked for validity. 65 // This makes the HTTPS connections insecure 66 KubeInsecureSkipTLSVerify bool 67 // KubeTLSServerName overrides the name to use for server certificate validation. 68 // If it is not provided, the hostname used to contact the server is used 69 KubeTLSServerName string 70 // Debug indicates whether or not Helm is running in Debug mode. 71 Debug bool 72 // RegistryConfig is the path to the registry config file. 73 RegistryConfig string 74 // RepositoryConfig is the path to the repositories file. 75 RepositoryConfig string 76 // RepositoryCache is the path to the repository cache directory. 77 RepositoryCache string 78 // PluginsDirectory is the path to the plugins directory. 79 PluginsDirectory string 80 // MaxHistory is the max release history maintained. 81 MaxHistory int 82 // BurstLimit is the default client-side throttling limit. 83 BurstLimit int 84 } 85 86 func New() *EnvSettings { 87 env := &EnvSettings{ 88 namespace: os.Getenv("HELM_NAMESPACE"), 89 MaxHistory: envIntOr("HELM_MAX_HISTORY", defaultMaxHistory), 90 KubeContext: os.Getenv("HELM_KUBECONTEXT"), 91 KubeToken: os.Getenv("HELM_KUBETOKEN"), 92 KubeAsUser: os.Getenv("HELM_KUBEASUSER"), 93 KubeAsGroups: envCSV("HELM_KUBEASGROUPS"), 94 KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"), 95 KubeCaFile: os.Getenv("HELM_KUBECAFILE"), 96 KubeTLSServerName: os.Getenv("HELM_KUBETLS_SERVER_NAME"), 97 KubeInsecureSkipTLSVerify: envBoolOr("HELM_KUBEINSECURE_SKIP_TLS_VERIFY", false), 98 PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")), 99 RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")), 100 RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")), 101 RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")), 102 BurstLimit: envIntOr("HELM_BURST_LIMIT", defaultBurstLimit), 103 } 104 env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG")) 105 106 // bind to kubernetes config flags 107 env.config = &genericclioptions.ConfigFlags{ 108 Namespace: &env.namespace, 109 Context: &env.KubeContext, 110 BearerToken: &env.KubeToken, 111 APIServer: &env.KubeAPIServer, 112 CAFile: &env.KubeCaFile, 113 KubeConfig: &env.KubeConfig, 114 Impersonate: &env.KubeAsUser, 115 Insecure: &env.KubeInsecureSkipTLSVerify, 116 TLSServerName: &env.KubeTLSServerName, 117 ImpersonateGroup: &env.KubeAsGroups, 118 WrapConfigFn: func(config *rest.Config) *rest.Config { 119 config.Burst = env.BurstLimit 120 config.Wrap(func(rt http.RoundTripper) http.RoundTripper { 121 return &retryingRoundTripper{wrapped: rt} 122 }) 123 return config 124 }, 125 } 126 return env 127 } 128 129 // AddFlags binds flags to the given flagset. 130 func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) { 131 fs.StringVarP(&s.namespace, "namespace", "n", s.namespace, "namespace scope for this request") 132 fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file") 133 fs.StringVar(&s.KubeContext, "kube-context", s.KubeContext, "name of the kubeconfig context to use") 134 fs.StringVar(&s.KubeToken, "kube-token", s.KubeToken, "bearer token used for authentication") 135 fs.StringVar(&s.KubeAsUser, "kube-as-user", s.KubeAsUser, "username to impersonate for the operation") 136 fs.StringArrayVar(&s.KubeAsGroups, "kube-as-group", s.KubeAsGroups, "group to impersonate for the operation, this flag can be repeated to specify multiple groups.") 137 fs.StringVar(&s.KubeAPIServer, "kube-apiserver", s.KubeAPIServer, "the address and the port for the Kubernetes API server") 138 fs.StringVar(&s.KubeCaFile, "kube-ca-file", s.KubeCaFile, "the certificate authority file for the Kubernetes API server connection") 139 fs.StringVar(&s.KubeTLSServerName, "kube-tls-server-name", s.KubeTLSServerName, "server name to use for Kubernetes API server certificate validation. If it is not provided, the hostname used to contact the server is used") 140 fs.BoolVar(&s.KubeInsecureSkipTLSVerify, "kube-insecure-skip-tls-verify", s.KubeInsecureSkipTLSVerify, "if true, the Kubernetes API server's certificate will not be checked for validity. This will make your HTTPS connections insecure") 141 fs.BoolVar(&s.Debug, "debug", s.Debug, "enable verbose output") 142 fs.StringVar(&s.RegistryConfig, "registry-config", s.RegistryConfig, "path to the registry config file") 143 fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs") 144 fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes") 145 fs.IntVar(&s.BurstLimit, "burst-limit", s.BurstLimit, "client-side default throttling limit") 146 } 147 148 func envOr(name, def string) string { 149 if v, ok := os.LookupEnv(name); ok { 150 return v 151 } 152 return def 153 } 154 155 func envBoolOr(name string, def bool) bool { 156 if name == "" { 157 return def 158 } 159 envVal := envOr(name, strconv.FormatBool(def)) 160 ret, err := strconv.ParseBool(envVal) 161 if err != nil { 162 return def 163 } 164 return ret 165 } 166 167 func envIntOr(name string, def int) int { 168 if name == "" { 169 return def 170 } 171 envVal := envOr(name, strconv.Itoa(def)) 172 ret, err := strconv.Atoi(envVal) 173 if err != nil { 174 return def 175 } 176 return ret 177 } 178 179 func envCSV(name string) (ls []string) { 180 trimmed := strings.Trim(os.Getenv(name), ", ") 181 if trimmed != "" { 182 ls = strings.Split(trimmed, ",") 183 } 184 return 185 } 186 187 func (s *EnvSettings) EnvVars() map[string]string { 188 envvars := map[string]string{ 189 "HELM_BIN": os.Args[0], 190 "HELM_CACHE_HOME": helmpath.CachePath(""), 191 "HELM_CONFIG_HOME": helmpath.ConfigPath(""), 192 "HELM_DATA_HOME": helmpath.DataPath(""), 193 "HELM_DEBUG": fmt.Sprint(s.Debug), 194 "HELM_PLUGINS": s.PluginsDirectory, 195 "HELM_REGISTRY_CONFIG": s.RegistryConfig, 196 "HELM_REPOSITORY_CACHE": s.RepositoryCache, 197 "HELM_REPOSITORY_CONFIG": s.RepositoryConfig, 198 "HELM_NAMESPACE": s.Namespace(), 199 "HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory), 200 "HELM_BURST_LIMIT": strconv.Itoa(s.BurstLimit), 201 202 // broken, these are populated from helm flags and not kubeconfig. 203 "HELM_KUBECONTEXT": s.KubeContext, 204 "HELM_KUBETOKEN": s.KubeToken, 205 "HELM_KUBEASUSER": s.KubeAsUser, 206 "HELM_KUBEASGROUPS": strings.Join(s.KubeAsGroups, ","), 207 "HELM_KUBEAPISERVER": s.KubeAPIServer, 208 "HELM_KUBECAFILE": s.KubeCaFile, 209 "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": strconv.FormatBool(s.KubeInsecureSkipTLSVerify), 210 "HELM_KUBETLS_SERVER_NAME": s.KubeTLSServerName, 211 } 212 if s.KubeConfig != "" { 213 envvars["KUBECONFIG"] = s.KubeConfig 214 } 215 return envvars 216 } 217 218 // Namespace gets the namespace from the configuration 219 func (s *EnvSettings) Namespace() string { 220 if ns, _, err := s.config.ToRawKubeConfigLoader().Namespace(); err == nil { 221 return ns 222 } 223 return "default" 224 } 225 226 // SetNamespace sets the namespace in the configuration 227 func (s *EnvSettings) SetNamespace(namespace string) { 228 s.namespace = namespace 229 } 230 231 // RESTClientGetter gets the kubeconfig from EnvSettings 232 func (s *EnvSettings) RESTClientGetter() genericclioptions.RESTClientGetter { 233 return s.config 234 }