1
16
17 package clientcmd
18
19 import (
20 "strconv"
21 "strings"
22
23 "github.com/spf13/pflag"
24
25 clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
26 )
27
28
29
30 type ConfigOverrides struct {
31 AuthInfo clientcmdapi.AuthInfo
32
33 ClusterDefaults clientcmdapi.Cluster
34 ClusterInfo clientcmdapi.Cluster
35 Context clientcmdapi.Context
36 CurrentContext string
37 Timeout string
38 }
39
40
41
42 type ConfigOverrideFlags struct {
43 AuthOverrideFlags AuthOverrideFlags
44 ClusterOverrideFlags ClusterOverrideFlags
45 ContextOverrideFlags ContextOverrideFlags
46 CurrentContext FlagInfo
47 Timeout FlagInfo
48 }
49
50
51 type AuthOverrideFlags struct {
52 ClientCertificate FlagInfo
53 ClientKey FlagInfo
54 Token FlagInfo
55 Impersonate FlagInfo
56 ImpersonateUID FlagInfo
57 ImpersonateGroups FlagInfo
58 Username FlagInfo
59 Password FlagInfo
60 }
61
62
63 type ContextOverrideFlags struct {
64 ClusterName FlagInfo
65 AuthInfoName FlagInfo
66 Namespace FlagInfo
67 }
68
69
70 type ClusterOverrideFlags struct {
71 APIServer FlagInfo
72 APIVersion FlagInfo
73 CertificateAuthority FlagInfo
74 InsecureSkipTLSVerify FlagInfo
75 TLSServerName FlagInfo
76 ProxyURL FlagInfo
77 DisableCompression FlagInfo
78 }
79
80
81
82
83 type FlagInfo struct {
84
85 LongName string
86
87 ShortName string
88
89 Default string
90
91 Description string
92 }
93
94
95 func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo {
96 flags.SetAnnotation(f.LongName, "classified", []string{"true"})
97 return f
98 }
99
100
101 func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo {
102
103 if len(f.LongName) > 0 {
104 flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description)
105 }
106 return f
107 }
108
109
110 func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo {
111
112 if len(f.LongName) > 0 {
113 flags.VarP(newTransformingStringValue(f.Default, target, transformer), f.LongName, f.ShortName, f.Description)
114 }
115 return f
116 }
117
118
119 func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo {
120
121 if len(f.LongName) > 0 {
122 sliceVal := []string{}
123 if len(f.Default) > 0 {
124 sliceVal = []string{f.Default}
125 }
126 flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description)
127 }
128 return f
129 }
130
131
132 func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
133
134 if len(f.LongName) > 0 {
135
136 boolVal, err := strconv.ParseBool(f.Default)
137 if err != nil {
138 boolVal = false
139 }
140
141 flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description)
142 }
143 return f
144 }
145
146 const (
147 FlagClusterName = "cluster"
148 FlagAuthInfoName = "user"
149 FlagContext = "context"
150 FlagNamespace = "namespace"
151 FlagAPIServer = "server"
152 FlagTLSServerName = "tls-server-name"
153 FlagInsecure = "insecure-skip-tls-verify"
154 FlagCertFile = "client-certificate"
155 FlagKeyFile = "client-key"
156 FlagCAFile = "certificate-authority"
157 FlagEmbedCerts = "embed-certs"
158 FlagBearerToken = "token"
159 FlagImpersonate = "as"
160 FlagImpersonateUID = "as-uid"
161 FlagImpersonateGroup = "as-group"
162 FlagUsername = "username"
163 FlagPassword = "password"
164 FlagTimeout = "request-timeout"
165 FlagProxyURL = "proxy-url"
166 FlagDisableCompression = "disable-compression"
167 )
168
169
170 func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
171 return ConfigOverrideFlags{
172 AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
173 ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
174 ContextOverrideFlags: RecommendedContextOverrideFlags(prefix),
175
176 CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"},
177 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."},
178 }
179 }
180
181
182 func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags {
183 return AuthOverrideFlags{
184 ClientCertificate: FlagInfo{prefix + FlagCertFile, "", "", "Path to a client certificate file for TLS"},
185 ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"},
186 Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"},
187 Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"},
188 ImpersonateUID: FlagInfo{prefix + FlagImpersonateUID, "", "", "UID to impersonate for the operation"},
189 ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group to impersonate for the operation, this flag can be repeated to specify multiple groups."},
190 Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"},
191 Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"},
192 }
193 }
194
195
196 func RecommendedClusterOverrideFlags(prefix string) ClusterOverrideFlags {
197 return ClusterOverrideFlags{
198 APIServer: FlagInfo{prefix + FlagAPIServer, "", "", "The address and port of the Kubernetes API server"},
199 CertificateAuthority: FlagInfo{prefix + FlagCAFile, "", "", "Path to a cert file for the certificate authority"},
200 InsecureSkipTLSVerify: FlagInfo{prefix + FlagInsecure, "", "false", "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure"},
201 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."},
202 ProxyURL: FlagInfo{prefix + FlagProxyURL, "", "", "If provided, this URL will be used to connect via proxy"},
203 DisableCompression: FlagInfo{prefix + FlagDisableCompression, "", "", "If true, opt-out of response compression for all requests to the server"},
204 }
205 }
206
207
208 func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags {
209 return ContextOverrideFlags{
210 ClusterName: FlagInfo{prefix + FlagClusterName, "", "", "The name of the kubeconfig cluster to use"},
211 AuthInfoName: FlagInfo{prefix + FlagAuthInfoName, "", "", "The name of the kubeconfig user to use"},
212 Namespace: FlagInfo{prefix + FlagNamespace, "n", "", "If present, the namespace scope for this CLI request"},
213 }
214 }
215
216
217 func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) {
218 BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags)
219 BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags)
220 BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
221 flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext)
222 flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout)
223 }
224
225
226 func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) {
227 flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags)
228 flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags)
229 flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags)
230 flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags)
231 flagNames.ImpersonateUID.BindStringFlag(flags, &authInfo.ImpersonateUID).AddSecretAnnotation(flags)
232 flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags)
233 flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags)
234 flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags)
235 }
236
237
238 func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, flagNames ClusterOverrideFlags) {
239 flagNames.APIServer.BindStringFlag(flags, &clusterInfo.Server)
240 flagNames.CertificateAuthority.BindStringFlag(flags, &clusterInfo.CertificateAuthority)
241 flagNames.InsecureSkipTLSVerify.BindBoolFlag(flags, &clusterInfo.InsecureSkipTLSVerify)
242 flagNames.TLSServerName.BindStringFlag(flags, &clusterInfo.TLSServerName)
243 flagNames.ProxyURL.BindStringFlag(flags, &clusterInfo.ProxyURL)
244 flagNames.DisableCompression.BindBoolFlag(flags, &clusterInfo.DisableCompression)
245 }
246
247
248 func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) {
249 flagNames.ClusterName.BindStringFlag(flags, &contextInfo.Cluster)
250 flagNames.AuthInfoName.BindStringFlag(flags, &contextInfo.AuthInfo)
251 flagNames.Namespace.BindTransformingStringFlag(flags, &contextInfo.Namespace, RemoveNamespacesPrefix)
252 }
253
254
255 func RemoveNamespacesPrefix(value string) (string, error) {
256 for _, prefix := range []string{"namespaces/", "namespace/", "ns/"} {
257 if len(value) > len(prefix) && strings.EqualFold(value[0:len(prefix)], prefix) {
258 value = value[len(prefix):]
259 break
260 }
261 }
262 return value, nil
263 }
264
View as plain text