k8s.io/client-go@v0.31.1/tools/clientcmd/overrides.go (about) 1 /* 2 Copyright 2014 The Kubernetes 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 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 // 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" 30 type 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 42 type 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 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 // ContextOverrideFlags holds the flag names to be used for binding command line flags for Cluster objects 63 type ContextOverrideFlags struct { 64 ClusterName FlagInfo 65 AuthInfoName FlagInfo 66 Namespace FlagInfo 67 } 68 69 // ClusterOverride holds the flag names to be used for binding command line flags for Cluster objects 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 // FlagInfo contains information about how to register a flag. This struct is useful if you want to provide a way for an extender to 81 // get back a set of recommended flag names, descriptions, and defaults, but allow for customization by an extender. This makes for 82 // coherent extension, without full prescription 83 type FlagInfo struct { 84 // LongName is the long string for a flag. If this is empty, then the flag will not be bound 85 LongName string 86 // ShortName is the single character for a flag. If this is empty, then there will be no short flag 87 ShortName string 88 // Default is the default value for the flag 89 Default string 90 // Description is the description for the flag 91 Description string 92 } 93 94 // AddSecretAnnotation add secret flag to Annotation. 95 func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo { 96 flags.SetAnnotation(f.LongName, "classified", []string{"true"}) 97 return f 98 } 99 100 // BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered 101 func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo { 102 // you can't register a flag without a long name 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 // BindTransformingStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered 110 func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo { 111 // you can't register a flag without a long name 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 // BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered 119 func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo { 120 // you can't register a flag without a long name 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 // BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered 132 func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo { 133 // you can't register a flag without a long name 134 if len(f.LongName) > 0 { 135 // try to parse Default as a bool. If it fails, assume false 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 // RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing 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 // RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing 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 // RecommendedClusterOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing 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 // RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing 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 // BindOverrideFlags is a convenience method to bind the specified flags to their associated variables 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 // BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables 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 // BindClusterFlags is a convenience method to bind the specified flags to their associated variables 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 // BindFlags is a convenience method to bind the specified flags to their associated variables 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 // RemoveNamespacesPrefix is a transformer that strips "ns/", "namespace/" and "namespaces/" prefixes case-insensitively 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 }