1
16
17
24 package cli
25
26 import (
27 "fmt"
28 "net/http"
29 "os"
30 "strconv"
31 "strings"
32
33 "github.com/spf13/pflag"
34 "k8s.io/cli-runtime/pkg/genericclioptions"
35 "k8s.io/client-go/rest"
36
37 "helm.sh/helm/v3/internal/version"
38 "helm.sh/helm/v3/pkg/helmpath"
39 )
40
41
42 const defaultMaxHistory = 10
43
44
45 const defaultBurstLimit = 100
46
47
48 const defaultQPS = float32(0)
49
50
51 type EnvSettings struct {
52 namespace string
53 config *genericclioptions.ConfigFlags
54
55
56 KubeConfig string
57
58 KubeContext string
59
60 KubeToken string
61
62 KubeAsUser string
63
64 KubeAsGroups []string
65
66 KubeAPIServer string
67
68 KubeCaFile string
69
70
71 KubeInsecureSkipTLSVerify bool
72
73
74 KubeTLSServerName string
75
76 Debug bool
77
78 RegistryConfig string
79
80 RepositoryConfig string
81
82 RepositoryCache string
83
84 PluginsDirectory string
85
86 MaxHistory int
87
88 BurstLimit int
89
90 QPS float32
91 }
92
93 func New() *EnvSettings {
94 env := &EnvSettings{
95 namespace: os.Getenv("HELM_NAMESPACE"),
96 MaxHistory: envIntOr("HELM_MAX_HISTORY", defaultMaxHistory),
97 KubeContext: os.Getenv("HELM_KUBECONTEXT"),
98 KubeToken: os.Getenv("HELM_KUBETOKEN"),
99 KubeAsUser: os.Getenv("HELM_KUBEASUSER"),
100 KubeAsGroups: envCSV("HELM_KUBEASGROUPS"),
101 KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"),
102 KubeCaFile: os.Getenv("HELM_KUBECAFILE"),
103 KubeTLSServerName: os.Getenv("HELM_KUBETLS_SERVER_NAME"),
104 KubeInsecureSkipTLSVerify: envBoolOr("HELM_KUBEINSECURE_SKIP_TLS_VERIFY", false),
105 PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")),
106 RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")),
107 RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")),
108 RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
109 BurstLimit: envIntOr("HELM_BURST_LIMIT", defaultBurstLimit),
110 QPS: envFloat32Or("HELM_QPS", defaultQPS),
111 }
112 env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG"))
113
114
115 env.config = &genericclioptions.ConfigFlags{
116 Namespace: &env.namespace,
117 Context: &env.KubeContext,
118 BearerToken: &env.KubeToken,
119 APIServer: &env.KubeAPIServer,
120 CAFile: &env.KubeCaFile,
121 KubeConfig: &env.KubeConfig,
122 Impersonate: &env.KubeAsUser,
123 Insecure: &env.KubeInsecureSkipTLSVerify,
124 TLSServerName: &env.KubeTLSServerName,
125 ImpersonateGroup: &env.KubeAsGroups,
126 WrapConfigFn: func(config *rest.Config) *rest.Config {
127 config.Burst = env.BurstLimit
128 config.QPS = env.QPS
129 config.Wrap(func(rt http.RoundTripper) http.RoundTripper {
130 return &retryingRoundTripper{wrapped: rt}
131 })
132 config.UserAgent = version.GetUserAgent()
133 return config
134 },
135 }
136 return env
137 }
138
139
140 func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
141 fs.StringVarP(&s.namespace, "namespace", "n", s.namespace, "namespace scope for this request")
142 fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file")
143 fs.StringVar(&s.KubeContext, "kube-context", s.KubeContext, "name of the kubeconfig context to use")
144 fs.StringVar(&s.KubeToken, "kube-token", s.KubeToken, "bearer token used for authentication")
145 fs.StringVar(&s.KubeAsUser, "kube-as-user", s.KubeAsUser, "username to impersonate for the operation")
146 fs.StringArrayVar(&s.KubeAsGroups, "kube-as-group", s.KubeAsGroups, "group to impersonate for the operation, this flag can be repeated to specify multiple groups.")
147 fs.StringVar(&s.KubeAPIServer, "kube-apiserver", s.KubeAPIServer, "the address and the port for the Kubernetes API server")
148 fs.StringVar(&s.KubeCaFile, "kube-ca-file", s.KubeCaFile, "the certificate authority file for the Kubernetes API server connection")
149 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")
150 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")
151 fs.BoolVar(&s.Debug, "debug", s.Debug, "enable verbose output")
152 fs.StringVar(&s.RegistryConfig, "registry-config", s.RegistryConfig, "path to the registry config file")
153 fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs")
154 fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes")
155 fs.IntVar(&s.BurstLimit, "burst-limit", s.BurstLimit, "client-side default throttling limit")
156 fs.Float32Var(&s.QPS, "qps", s.QPS, "queries per second used when communicating with the Kubernetes API, not including bursting")
157 }
158
159 func envOr(name, def string) string {
160 if v, ok := os.LookupEnv(name); ok {
161 return v
162 }
163 return def
164 }
165
166 func envBoolOr(name string, def bool) bool {
167 if name == "" {
168 return def
169 }
170 envVal := envOr(name, strconv.FormatBool(def))
171 ret, err := strconv.ParseBool(envVal)
172 if err != nil {
173 return def
174 }
175 return ret
176 }
177
178 func envIntOr(name string, def int) int {
179 if name == "" {
180 return def
181 }
182 envVal := envOr(name, strconv.Itoa(def))
183 ret, err := strconv.Atoi(envVal)
184 if err != nil {
185 return def
186 }
187 return ret
188 }
189
190 func envFloat32Or(name string, def float32) float32 {
191 if name == "" {
192 return def
193 }
194 envVal := envOr(name, strconv.FormatFloat(float64(def), 'f', 2, 32))
195 ret, err := strconv.ParseFloat(envVal, 32)
196 if err != nil {
197 return def
198 }
199 return float32(ret)
200 }
201
202 func envCSV(name string) (ls []string) {
203 trimmed := strings.Trim(os.Getenv(name), ", ")
204 if trimmed != "" {
205 ls = strings.Split(trimmed, ",")
206 }
207 return
208 }
209
210 func (s *EnvSettings) EnvVars() map[string]string {
211 envvars := map[string]string{
212 "HELM_BIN": os.Args[0],
213 "HELM_CACHE_HOME": helmpath.CachePath(""),
214 "HELM_CONFIG_HOME": helmpath.ConfigPath(""),
215 "HELM_DATA_HOME": helmpath.DataPath(""),
216 "HELM_DEBUG": fmt.Sprint(s.Debug),
217 "HELM_PLUGINS": s.PluginsDirectory,
218 "HELM_REGISTRY_CONFIG": s.RegistryConfig,
219 "HELM_REPOSITORY_CACHE": s.RepositoryCache,
220 "HELM_REPOSITORY_CONFIG": s.RepositoryConfig,
221 "HELM_NAMESPACE": s.Namespace(),
222 "HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory),
223 "HELM_BURST_LIMIT": strconv.Itoa(s.BurstLimit),
224 "HELM_QPS": strconv.FormatFloat(float64(s.QPS), 'f', 2, 32),
225
226
227 "HELM_KUBECONTEXT": s.KubeContext,
228 "HELM_KUBETOKEN": s.KubeToken,
229 "HELM_KUBEASUSER": s.KubeAsUser,
230 "HELM_KUBEASGROUPS": strings.Join(s.KubeAsGroups, ","),
231 "HELM_KUBEAPISERVER": s.KubeAPIServer,
232 "HELM_KUBECAFILE": s.KubeCaFile,
233 "HELM_KUBEINSECURE_SKIP_TLS_VERIFY": strconv.FormatBool(s.KubeInsecureSkipTLSVerify),
234 "HELM_KUBETLS_SERVER_NAME": s.KubeTLSServerName,
235 }
236 if s.KubeConfig != "" {
237 envvars["KUBECONFIG"] = s.KubeConfig
238 }
239 return envvars
240 }
241
242
243 func (s *EnvSettings) Namespace() string {
244 if ns, _, err := s.config.ToRawKubeConfigLoader().Namespace(); err == nil {
245 return ns
246 }
247 if s.namespace != "" {
248 return s.namespace
249 }
250 return "default"
251 }
252
253
254 func (s *EnvSettings) SetNamespace(namespace string) {
255 s.namespace = namespace
256 }
257
258
259 func (s *EnvSettings) RESTClientGetter() genericclioptions.RESTClientGetter {
260 return s.config
261 }
262
View as plain text