k8s.io/client-go@v0.22.2/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  	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
    62  type 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
    69  type 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
    80  type 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.
    92  func (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
    98  func (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
   107  func (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
   116  func (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
   129  func (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  
   143  const (
   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
   164  func 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
   176  func 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
   189  func 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
   199  func 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
   208  func 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
   217  func 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
   228  func 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
   236  func 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
   243  func 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  }