123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /*
- Copyright 2014 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package clientcmd
- import (
- "strconv"
- "strings"
- "github.com/spf13/pflag"
- clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
- )
- // ConfigOverrides holds values that should override whatever information is pulled from the actual Config object. You can't
- // simply use an actual Config object, because Configs hold maps, but overrides are restricted to "at most one"
- type ConfigOverrides struct {
- AuthInfo clientcmdapi.AuthInfo
- // ClusterDefaults are applied before the configured cluster info is loaded.
- ClusterDefaults clientcmdapi.Cluster
- ClusterInfo clientcmdapi.Cluster
- Context clientcmdapi.Context
- CurrentContext string
- Timeout string
- }
- // ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
- // corresponds to ConfigOverrides
- type ConfigOverrideFlags struct {
- AuthOverrideFlags AuthOverrideFlags
- ClusterOverrideFlags ClusterOverrideFlags
- ContextOverrideFlags ContextOverrideFlags
- CurrentContext FlagInfo
- Timeout FlagInfo
- }
- // AuthOverrideFlags holds the flag names to be used for binding command line flags for AuthInfo objects
- type AuthOverrideFlags struct {
- ClientCertificate FlagInfo
- ClientKey FlagInfo
- Token FlagInfo
- Impersonate FlagInfo
- ImpersonateGroups FlagInfo
- Username FlagInfo
- Password FlagInfo
- }
- // ContextOverrideFlags holds the flag names to be used for binding command line flags for Cluster objects
- type ContextOverrideFlags struct {
- ClusterName FlagInfo
- AuthInfoName FlagInfo
- Namespace FlagInfo
- }
- // ClusterOverride holds the flag names to be used for binding command line flags for Cluster objects
- type ClusterOverrideFlags struct {
- APIServer FlagInfo
- APIVersion FlagInfo
- CertificateAuthority FlagInfo
- InsecureSkipTLSVerify FlagInfo
- TLSServerName FlagInfo
- }
- // FlagInfo contains information about how to register a flag. This struct is useful if you want to provide a way for an extender to
- // get back a set of recommended flag names, descriptions, and defaults, but allow for customization by an extender. This makes for
- // coherent extension, without full prescription
- type FlagInfo struct {
- // LongName is the long string for a flag. If this is empty, then the flag will not be bound
- LongName string
- // ShortName is the single character for a flag. If this is empty, then there will be no short flag
- ShortName string
- // Default is the default value for the flag
- Default string
- // Description is the description for the flag
- Description string
- }
- // AddSecretAnnotation add secret flag to Annotation.
- func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo {
- flags.SetAnnotation(f.LongName, "classified", []string{"true"})
- return f
- }
- // BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
- func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo {
- // you can't register a flag without a long name
- if len(f.LongName) > 0 {
- flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description)
- }
- return f
- }
- // BindTransformingStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered
- func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo {
- // you can't register a flag without a long name
- if len(f.LongName) > 0 {
- flags.VarP(newTransformingStringValue(f.Default, target, transformer), f.LongName, f.ShortName, f.Description)
- }
- return f
- }
- // BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered
- func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo {
- // you can't register a flag without a long name
- if len(f.LongName) > 0 {
- sliceVal := []string{}
- if len(f.Default) > 0 {
- sliceVal = []string{f.Default}
- }
- flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description)
- }
- return f
- }
- // BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered
- func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
- // you can't register a flag without a long name
- if len(f.LongName) > 0 {
- // try to parse Default as a bool. If it fails, assume false
- boolVal, err := strconv.ParseBool(f.Default)
- if err != nil {
- boolVal = false
- }
- flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description)
- }
- return f
- }
- const (
- FlagClusterName = "cluster"
- FlagAuthInfoName = "user"
- FlagContext = "context"
- FlagNamespace = "namespace"
- FlagAPIServer = "server"
- FlagTLSServerName = "tls-server-name"
- FlagInsecure = "insecure-skip-tls-verify"
- FlagCertFile = "client-certificate"
- FlagKeyFile = "client-key"
- FlagCAFile = "certificate-authority"
- FlagEmbedCerts = "embed-certs"
- FlagBearerToken = "token"
- FlagImpersonate = "as"
- FlagImpersonateGroup = "as-group"
- FlagUsername = "username"
- FlagPassword = "password"
- FlagTimeout = "request-timeout"
- )
- // RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
- func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
- return ConfigOverrideFlags{
- AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
- ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
- ContextOverrideFlags: RecommendedContextOverrideFlags(prefix),
- CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"},
- 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."},
- }
- }
- // RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
- func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags {
- return AuthOverrideFlags{
- ClientCertificate: FlagInfo{prefix + FlagCertFile, "", "", "Path to a client certificate file for TLS"},
- ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"},
- Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"},
- Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"},
- ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group to impersonate for the operation, this flag can be repeated to specify multiple groups."},
- Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"},
- Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"},
- }
- }
- // RecommendedClusterOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
- func RecommendedClusterOverrideFlags(prefix string) ClusterOverrideFlags {
- return ClusterOverrideFlags{
- APIServer: FlagInfo{prefix + FlagAPIServer, "", "", "The address and port of the Kubernetes API server"},
- CertificateAuthority: FlagInfo{prefix + FlagCAFile, "", "", "Path to a cert file for the certificate authority"},
- InsecureSkipTLSVerify: FlagInfo{prefix + FlagInsecure, "", "false", "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure"},
- 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."},
- }
- }
- // RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
- func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags {
- return ContextOverrideFlags{
- ClusterName: FlagInfo{prefix + FlagClusterName, "", "", "The name of the kubeconfig cluster to use"},
- AuthInfoName: FlagInfo{prefix + FlagAuthInfoName, "", "", "The name of the kubeconfig user to use"},
- Namespace: FlagInfo{prefix + FlagNamespace, "n", "", "If present, the namespace scope for this CLI request"},
- }
- }
- // BindOverrideFlags is a convenience method to bind the specified flags to their associated variables
- func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) {
- BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags)
- BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags)
- BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
- flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext)
- flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout)
- }
- // BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables
- func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) {
- flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags)
- flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags)
- flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags)
- flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags)
- flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags)
- flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags)
- flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags)
- }
- // BindClusterFlags is a convenience method to bind the specified flags to their associated variables
- func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, flagNames ClusterOverrideFlags) {
- flagNames.APIServer.BindStringFlag(flags, &clusterInfo.Server)
- flagNames.CertificateAuthority.BindStringFlag(flags, &clusterInfo.CertificateAuthority)
- flagNames.InsecureSkipTLSVerify.BindBoolFlag(flags, &clusterInfo.InsecureSkipTLSVerify)
- flagNames.TLSServerName.BindStringFlag(flags, &clusterInfo.TLSServerName)
- }
- // BindFlags is a convenience method to bind the specified flags to their associated variables
- func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) {
- flagNames.ClusterName.BindStringFlag(flags, &contextInfo.Cluster)
- flagNames.AuthInfoName.BindStringFlag(flags, &contextInfo.AuthInfo)
- flagNames.Namespace.BindTransformingStringFlag(flags, &contextInfo.Namespace, RemoveNamespacesPrefix)
- }
- // RemoveNamespacesPrefix is a transformer that strips "ns/", "namespace/" and "namespaces/" prefixes case-insensitively
- func RemoveNamespacesPrefix(value string) (string, error) {
- for _, prefix := range []string{"namespaces/", "namespace/", "ns/"} {
- if len(value) > len(prefix) && strings.EqualFold(value[0:len(prefix)], prefix) {
- value = value[len(prefix):]
- break
- }
- }
- return value, nil
- }
|