blob: 95cba0fac27f526c31603256b8bfbd14540c4b06 [file] [log] [blame]
Matteo Scandoloa4285862020-12-01 18:10:10 -08001/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package clientcmd
18
19import (
20 "strconv"
21 "strings"
22
23 "github.com/spf13/pflag"
24
25 clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
26)
27
28// ConfigOverrides holds values that should override whatever information is pulled from the actual Config object. You can't
29// simply use an actual Config object, because Configs hold maps, but overrides are restricted to "at most one"
30type ConfigOverrides struct {
31 AuthInfo clientcmdapi.AuthInfo
32 // ClusterDefaults are applied before the configured cluster info is loaded.
33 ClusterDefaults clientcmdapi.Cluster
34 ClusterInfo clientcmdapi.Cluster
35 Context clientcmdapi.Context
36 CurrentContext string
37 Timeout string
38}
39
40// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
41// corresponds to ConfigOverrides
42type ConfigOverrideFlags struct {
43 AuthOverrideFlags AuthOverrideFlags
44 ClusterOverrideFlags ClusterOverrideFlags
45 ContextOverrideFlags ContextOverrideFlags
46 CurrentContext FlagInfo
47 Timeout FlagInfo
48}
49
50// AuthOverrideFlags holds the flag names to be used for binding command line flags for AuthInfo objects
51type AuthOverrideFlags struct {
52 ClientCertificate FlagInfo
53 ClientKey FlagInfo
54 Token FlagInfo
55 Impersonate FlagInfo
56 ImpersonateGroups FlagInfo
57 Username FlagInfo
58 Password FlagInfo
59}
60
61// ContextOverrideFlags holds the flag names to be used for binding command line flags for Cluster objects
62type ContextOverrideFlags struct {
63 ClusterName FlagInfo
64 AuthInfoName FlagInfo
65 Namespace FlagInfo
66}
67
68// ClusterOverride holds the flag names to be used for binding command line flags for Cluster objects
69type ClusterOverrideFlags struct {
70 APIServer FlagInfo
71 APIVersion FlagInfo
72 CertificateAuthority FlagInfo
73 InsecureSkipTLSVerify FlagInfo
74 TLSServerName FlagInfo
75}
76
77// FlagInfo contains information about how to register a flag. This struct is useful if you want to provide a way for an extender to
78// get back a set of recommended flag names, descriptions, and defaults, but allow for customization by an extender. This makes for
79// coherent extension, without full prescription
80type FlagInfo struct {
81 // LongName is the long string for a flag. If this is empty, then the flag will not be bound
82 LongName string
83 // ShortName is the single character for a flag. If this is empty, then there will be no short flag
84 ShortName string
85 // Default is the default value for the flag
86 Default string
87 // Description is the description for the flag
88 Description string
89}
90
91// AddSecretAnnotation add secret flag to Annotation.
92func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo {
93 flags.SetAnnotation(f.LongName, "classified", []string{"true"})
94 return f
95}
96
97// BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
98func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo {
99 // you can't register a flag without a long name
100 if len(f.LongName) > 0 {
101 flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description)
102 }
103 return f
104}
105
106// BindTransformingStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
107func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo {
108 // you can't register a flag without a long name
109 if len(f.LongName) > 0 {
110 flags.VarP(newTransformingStringValue(f.Default, target, transformer), f.LongName, f.ShortName, f.Description)
111 }
112 return f
113}
114
115// BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered
116func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo {
117 // you can't register a flag without a long name
118 if len(f.LongName) > 0 {
119 sliceVal := []string{}
120 if len(f.Default) > 0 {
121 sliceVal = []string{f.Default}
122 }
123 flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description)
124 }
125 return f
126}
127
128// BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered
129func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
130 // you can't register a flag without a long name
131 if len(f.LongName) > 0 {
132 // try to parse Default as a bool. If it fails, assume false
133 boolVal, err := strconv.ParseBool(f.Default)
134 if err != nil {
135 boolVal = false
136 }
137
138 flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description)
139 }
140 return f
141}
142
143const (
144 FlagClusterName = "cluster"
145 FlagAuthInfoName = "user"
146 FlagContext = "context"
147 FlagNamespace = "namespace"
148 FlagAPIServer = "server"
149 FlagTLSServerName = "tls-server-name"
150 FlagInsecure = "insecure-skip-tls-verify"
151 FlagCertFile = "client-certificate"
152 FlagKeyFile = "client-key"
153 FlagCAFile = "certificate-authority"
154 FlagEmbedCerts = "embed-certs"
155 FlagBearerToken = "token"
156 FlagImpersonate = "as"
157 FlagImpersonateGroup = "as-group"
158 FlagUsername = "username"
159 FlagPassword = "password"
160 FlagTimeout = "request-timeout"
161)
162
163// RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
164func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
165 return ConfigOverrideFlags{
166 AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
167 ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
168 ContextOverrideFlags: RecommendedContextOverrideFlags(prefix),
169
170 CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"},
171 Timeout: FlagInfo{prefix + FlagTimeout, "", "0", "The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests."},
172 }
173}
174
175// RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
176func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags {
177 return AuthOverrideFlags{
178 ClientCertificate: FlagInfo{prefix + FlagCertFile, "", "", "Path to a client certificate file for TLS"},
179 ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"},
180 Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"},
181 Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"},
182 ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group to impersonate for the operation, this flag can be repeated to specify multiple groups."},
183 Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"},
184 Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"},
185 }
186}
187
188// RecommendedClusterOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
189func RecommendedClusterOverrideFlags(prefix string) ClusterOverrideFlags {
190 return ClusterOverrideFlags{
191 APIServer: FlagInfo{prefix + FlagAPIServer, "", "", "The address and port of the Kubernetes API server"},
192 CertificateAuthority: FlagInfo{prefix + FlagCAFile, "", "", "Path to a cert file for the certificate authority"},
193 InsecureSkipTLSVerify: FlagInfo{prefix + FlagInsecure, "", "false", "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure"},
194 TLSServerName: FlagInfo{prefix + FlagTLSServerName, "", "", "If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used."},
195 }
196}
197
198// RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
199func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags {
200 return ContextOverrideFlags{
201 ClusterName: FlagInfo{prefix + FlagClusterName, "", "", "The name of the kubeconfig cluster to use"},
202 AuthInfoName: FlagInfo{prefix + FlagAuthInfoName, "", "", "The name of the kubeconfig user to use"},
203 Namespace: FlagInfo{prefix + FlagNamespace, "n", "", "If present, the namespace scope for this CLI request"},
204 }
205}
206
207// BindOverrideFlags is a convenience method to bind the specified flags to their associated variables
208func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) {
209 BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags)
210 BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags)
211 BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
212 flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext)
213 flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout)
214}
215
216// BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables
217func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) {
218 flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags)
219 flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags)
220 flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags)
221 flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags)
222 flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags)
223 flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags)
224 flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags)
225}
226
227// BindClusterFlags is a convenience method to bind the specified flags to their associated variables
228func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, flagNames ClusterOverrideFlags) {
229 flagNames.APIServer.BindStringFlag(flags, &clusterInfo.Server)
230 flagNames.CertificateAuthority.BindStringFlag(flags, &clusterInfo.CertificateAuthority)
231 flagNames.InsecureSkipTLSVerify.BindBoolFlag(flags, &clusterInfo.InsecureSkipTLSVerify)
232 flagNames.TLSServerName.BindStringFlag(flags, &clusterInfo.TLSServerName)
233}
234
235// BindFlags is a convenience method to bind the specified flags to their associated variables
236func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) {
237 flagNames.ClusterName.BindStringFlag(flags, &contextInfo.Cluster)
238 flagNames.AuthInfoName.BindStringFlag(flags, &contextInfo.AuthInfo)
239 flagNames.Namespace.BindTransformingStringFlag(flags, &contextInfo.Namespace, RemoveNamespacesPrefix)
240}
241
242// RemoveNamespacesPrefix is a transformer that strips "ns/", "namespace/" and "namespaces/" prefixes case-insensitively
243func RemoveNamespacesPrefix(value string) (string, error) {
244 for _, prefix := range []string{"namespaces/", "namespace/", "ns/"} {
245 if len(value) > len(prefix) && strings.EqualFold(value[0:len(prefix)], prefix) {
246 value = value[len(prefix):]
247 break
248 }
249 }
250 return value, nil
251}