blob: bfca032847beec8fbc9bb801f178041e348d500a [file] [log] [blame]
Kent Hagermane566c2e2019-06-03 17:56:42 -04001/*
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}
75
76// FlagInfo contains information about how to register a flag. This struct is useful if you want to provide a way for an extender to
77// get back a set of recommended flag names, descriptions, and defaults, but allow for customization by an extender. This makes for
78// coherent extension, without full prescription
79type FlagInfo struct {
80 // LongName is the long string for a flag. If this is empty, then the flag will not be bound
81 LongName string
82 // ShortName is the single character for a flag. If this is empty, then there will be no short flag
83 ShortName string
84 // Default is the default value for the flag
85 Default string
86 // Description is the description for the flag
87 Description string
88}
89
90// AddSecretAnnotation add secret flag to Annotation.
91func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo {
92 flags.SetAnnotation(f.LongName, "classified", []string{"true"})
93 return f
94}
95
96// BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
97func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo {
98 // you can't register a flag without a long name
99 if len(f.LongName) > 0 {
100 flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description)
101 }
102 return f
103}
104
105// BindTransformingStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
106func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo {
107 // you can't register a flag without a long name
108 if len(f.LongName) > 0 {
109 flags.VarP(newTransformingStringValue(f.Default, target, transformer), f.LongName, f.ShortName, f.Description)
110 }
111 return f
112}
113
114// BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered
115func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo {
116 // you can't register a flag without a long name
117 if len(f.LongName) > 0 {
118 sliceVal := []string{}
119 if len(f.Default) > 0 {
120 sliceVal = []string{f.Default}
121 }
122 flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description)
123 }
124 return f
125}
126
127// BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered
128func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
129 // you can't register a flag without a long name
130 if len(f.LongName) > 0 {
131 // try to parse Default as a bool. If it fails, assume false
132 boolVal, err := strconv.ParseBool(f.Default)
133 if err != nil {
134 boolVal = false
135 }
136
137 flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description)
138 }
139 return f
140}
141
142const (
143 FlagClusterName = "cluster"
144 FlagAuthInfoName = "user"
145 FlagContext = "context"
146 FlagNamespace = "namespace"
147 FlagAPIServer = "server"
148 FlagInsecure = "insecure-skip-tls-verify"
149 FlagCertFile = "client-certificate"
150 FlagKeyFile = "client-key"
151 FlagCAFile = "certificate-authority"
152 FlagEmbedCerts = "embed-certs"
153 FlagBearerToken = "token"
154 FlagImpersonate = "as"
155 FlagImpersonateGroup = "as-group"
156 FlagUsername = "username"
157 FlagPassword = "password"
158 FlagTimeout = "request-timeout"
159)
160
161// RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
162func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
163 return ConfigOverrideFlags{
164 AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
165 ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
166 ContextOverrideFlags: RecommendedContextOverrideFlags(prefix),
167
168 CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"},
169 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."},
170 }
171}
172
173// RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
174func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags {
175 return AuthOverrideFlags{
176 ClientCertificate: FlagInfo{prefix + FlagCertFile, "", "", "Path to a client certificate file for TLS"},
177 ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"},
178 Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"},
179 Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"},
180 ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group to impersonate for the operation, this flag can be repeated to specify multiple groups."},
181 Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"},
182 Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"},
183 }
184}
185
186// RecommendedClusterOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
187func RecommendedClusterOverrideFlags(prefix string) ClusterOverrideFlags {
188 return ClusterOverrideFlags{
189 APIServer: FlagInfo{prefix + FlagAPIServer, "", "", "The address and port of the Kubernetes API server"},
190 CertificateAuthority: FlagInfo{prefix + FlagCAFile, "", "", "Path to a cert file for the certificate authority"},
191 InsecureSkipTLSVerify: FlagInfo{prefix + FlagInsecure, "", "false", "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure"},
192 }
193}
194
195// RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
196func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags {
197 return ContextOverrideFlags{
198 ClusterName: FlagInfo{prefix + FlagClusterName, "", "", "The name of the kubeconfig cluster to use"},
199 AuthInfoName: FlagInfo{prefix + FlagAuthInfoName, "", "", "The name of the kubeconfig user to use"},
200 Namespace: FlagInfo{prefix + FlagNamespace, "n", "", "If present, the namespace scope for this CLI request"},
201 }
202}
203
204// BindOverrideFlags is a convenience method to bind the specified flags to their associated variables
205func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) {
206 BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags)
207 BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags)
208 BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
209 flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext)
210 flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout)
211}
212
213// BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables
214func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) {
215 flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags)
216 flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags)
217 flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags)
218 flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags)
219 flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags)
220 flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags)
221 flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags)
222}
223
224// BindClusterFlags is a convenience method to bind the specified flags to their associated variables
225func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, flagNames ClusterOverrideFlags) {
226 flagNames.APIServer.BindStringFlag(flags, &clusterInfo.Server)
227 flagNames.CertificateAuthority.BindStringFlag(flags, &clusterInfo.CertificateAuthority)
228 flagNames.InsecureSkipTLSVerify.BindBoolFlag(flags, &clusterInfo.InsecureSkipTLSVerify)
229}
230
231// BindFlags is a convenience method to bind the specified flags to their associated variables
232func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) {
233 flagNames.ClusterName.BindStringFlag(flags, &contextInfo.Cluster)
234 flagNames.AuthInfoName.BindStringFlag(flags, &contextInfo.AuthInfo)
235 flagNames.Namespace.BindTransformingStringFlag(flags, &contextInfo.Namespace, RemoveNamespacesPrefix)
236}
237
238// RemoveNamespacesPrefix is a transformer that strips "ns/", "namespace/" and "namespaces/" prefixes case-insensitively
239func RemoveNamespacesPrefix(value string) (string, error) {
240 for _, prefix := range []string{"namespaces/", "namespace/", "ns/"} {
241 if len(value) > len(prefix) && strings.EqualFold(value[0:len(prefix)], prefix) {
242 value = value[len(prefix):]
243 break
244 }
245 }
246 return value, nil
247}