go.mod: bump client-go and api machinerie

I had to run `make generate`.
Some API functions got additional parameters `Options` and `Context`.
I used empty options and `context.TODO()` for now.

Signed-off-by: leonnicolas <leonloechner@gmx.de>
This commit is contained in:
leonnicolas
2021-05-15 12:08:31 +02:00
parent f2c37b9de6
commit a3bf13711c
2386 changed files with 419055 additions and 183398 deletions

View File

@@ -98,6 +98,9 @@ func ShortenConfig(config *Config) {
if len(authInfo.ClientCertificateData) > 0 {
authInfo.ClientCertificateData = redactedBytes
}
if len(authInfo.Token) > 0 {
authInfo.Token = "REDACTED"
}
config.AuthInfos[key] = authInfo
}
for key, cluster := range config.Clusters {

View File

@@ -31,10 +31,12 @@ import (
type Config struct {
// Legacy field from pkg/api/types.go TypeMeta.
// TODO(jlowdermilk): remove this after eliminating downstream dependencies.
// +k8s:conversion-gen=false
// +optional
Kind string `json:"kind,omitempty"`
// Legacy field from pkg/api/types.go TypeMeta.
// TODO(jlowdermilk): remove this after eliminating downstream dependencies.
// +k8s:conversion-gen=false
// +optional
APIVersion string `json:"apiVersion,omitempty"`
// Preferences holds general information to be use for cli interactions
@@ -64,9 +66,13 @@ type Preferences struct {
// Cluster contains information about how to communicate with a kubernetes cluster
type Cluster struct {
// LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized.
// +k8s:conversion-gen=false
LocationOfOrigin string
// Server is the address of the kubernetes cluster (https://hostname:port).
Server string `json:"server"`
// TLSServerName is used to check server certificate. If TLSServerName is empty, the hostname used to contact the server is used.
// +optional
TLSServerName string `json:"tls-server-name,omitempty"`
// InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure.
// +optional
InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"`
@@ -76,6 +82,17 @@ type Cluster struct {
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
// +optional
CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"`
// ProxyURL is the URL to the proxy to be used for all requests made by this
// client. URLs with "http", "https", and "socks5" schemes are supported. If
// this configuration is not provided or the empty string, the client
// attempts to construct a proxy configuration from http_proxy and
// https_proxy environment variables. If these environment variables are not
// set, the client does not attempt to proxy requests.
//
// socks5 proxying does not currently support spdy streaming endpoints (exec,
// attach, port forward).
// +optional
ProxyURL string `json:"proxy-url,omitempty"`
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
// +optional
Extensions map[string]runtime.Object `json:"extensions,omitempty"`
@@ -84,6 +101,7 @@ type Cluster struct {
// AuthInfo contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
type AuthInfo struct {
// LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized.
// +k8s:conversion-gen=false
LocationOfOrigin string
// ClientCertificate is the path to a client cert file for TLS.
// +optional
@@ -96,10 +114,10 @@ type AuthInfo struct {
ClientKey string `json:"client-key,omitempty"`
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
// +optional
ClientKeyData []byte `json:"client-key-data,omitempty"`
ClientKeyData []byte `json:"client-key-data,omitempty" datapolicy:"security-key"`
// Token is the bearer token for authentication to the kubernetes cluster.
// +optional
Token string `json:"token,omitempty"`
Token string `json:"token,omitempty" datapolicy:"token"`
// TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence.
// +optional
TokenFile string `json:"tokenFile,omitempty"`
@@ -117,7 +135,7 @@ type AuthInfo struct {
Username string `json:"username,omitempty"`
// Password is the password for basic authentication to the kubernetes cluster.
// +optional
Password string `json:"password,omitempty"`
Password string `json:"password,omitempty" datapolicy:"password"`
// AuthProvider specifies a custom authentication plugin for the kubernetes cluster.
// +optional
AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty"`
@@ -132,6 +150,7 @@ type AuthInfo struct {
// Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with)
type Context struct {
// LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized.
// +k8s:conversion-gen=false
LocationOfOrigin string
// Cluster is the name of the cluster for this context
Cluster string `json:"cluster"`
@@ -174,7 +193,7 @@ func (c AuthProviderConfig) String() string {
// ExecConfig specifies a command to provide client credentials. The command is exec'd
// and outputs structured stdout holding credentials.
//
// See the client.authentiction.k8s.io API group for specifications of the exact input
// See the client.authentication.k8s.io API group for specifications of the exact input
// and output format
type ExecConfig struct {
// Command to execute.
@@ -191,6 +210,41 @@ type ExecConfig struct {
// Preferred input version of the ExecInfo. The returned ExecCredentials MUST use
// the same encoding version as the input.
APIVersion string `json:"apiVersion,omitempty"`
// This text is shown to the user when the executable doesn't seem to be
// present. For example, `brew install foo-cli` might be a good InstallHint for
// foo-cli on Mac OS systems.
InstallHint string `json:"installHint,omitempty"`
// ProvideClusterInfo determines whether or not to provide cluster information,
// which could potentially contain very large CA data, to this exec plugin as a
// part of the KUBERNETES_EXEC_INFO environment variable. By default, it is set
// to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
// reading this environment variable.
ProvideClusterInfo bool `json:"provideClusterInfo"`
// Config holds additional config data that is specific to the exec
// plugin with regards to the cluster being authenticated to.
//
// This data is sourced from the clientcmd Cluster object's extensions[exec] field:
//
// clusters:
// - name: my-cluster
// cluster:
// ...
// extensions:
// - name: client.authentication.k8s.io/exec # reserved extension name for per cluster exec config
// extension:
// audience: 06e3fbd18de8 # arbitrary config
//
// In some environments, the user config may be exactly the same across many clusters
// (i.e. call this exec plugin) minus some details that are specific to each cluster
// such as the audience. This field allows the per cluster config to be directly
// specified with the cluster info. Using this field to store secret data is not
// recommended as one of the prime benefits of exec plugins is that no secrets need
// to be stored directly in the kubeconfig.
// +k8s:conversion-gen=false
Config runtime.Object
}
var _ fmt.Stringer = new(ExecConfig)
@@ -213,7 +267,11 @@ func (c ExecConfig) String() string {
if len(c.Env) > 0 {
env = "[]ExecEnvVar{--- REDACTED ---}"
}
return fmt.Sprintf("api.AuthProviderConfig{Command: %q, Args: %#v, Env: %s, APIVersion: %q}", c.Command, args, env, c.APIVersion)
config := "runtime.Object(nil)"
if c.Config != nil {
config = "runtime.Object(--- REDACTED ---)"
}
return fmt.Sprintf("api.ExecConfig{Command: %q, Args: %#v, Env: %s, APIVersion: %q, ProvideClusterInfo: %t, Config: %s}", c.Command, args, env, c.APIVersion, c.ProvideClusterInfo, config)
}
// ExecEnvVar is used for setting environment variables when executing an exec-based

View File

@@ -25,220 +25,150 @@ import (
"k8s.io/client-go/tools/clientcmd/api"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
return scheme.AddConversionFuncs(
func(in *Cluster, out *api.Cluster, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *api.Cluster, out *Cluster, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Preferences, out *api.Preferences, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *api.Preferences, out *Preferences, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *AuthInfo, out *api.AuthInfo, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *api.AuthInfo, out *AuthInfo, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Context, out *api.Context, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *api.Context, out *Context, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Config, out *api.Config, s conversion.Scope) error {
out.CurrentContext = in.CurrentContext
if err := s.Convert(&in.Preferences, &out.Preferences, 0); err != nil {
return err
}
out.Clusters = make(map[string]*api.Cluster)
if err := s.Convert(&in.Clusters, &out.Clusters, 0); err != nil {
return err
}
out.AuthInfos = make(map[string]*api.AuthInfo)
if err := s.Convert(&in.AuthInfos, &out.AuthInfos, 0); err != nil {
return err
}
out.Contexts = make(map[string]*api.Context)
if err := s.Convert(&in.Contexts, &out.Contexts, 0); err != nil {
return err
}
out.Extensions = make(map[string]runtime.Object)
if err := s.Convert(&in.Extensions, &out.Extensions, 0); err != nil {
return err
}
return nil
},
func(in *api.Config, out *Config, s conversion.Scope) error {
out.CurrentContext = in.CurrentContext
if err := s.Convert(&in.Preferences, &out.Preferences, 0); err != nil {
return err
}
out.Clusters = make([]NamedCluster, 0, 0)
if err := s.Convert(&in.Clusters, &out.Clusters, 0); err != nil {
return err
}
out.AuthInfos = make([]NamedAuthInfo, 0, 0)
if err := s.Convert(&in.AuthInfos, &out.AuthInfos, 0); err != nil {
return err
}
out.Contexts = make([]NamedContext, 0, 0)
if err := s.Convert(&in.Contexts, &out.Contexts, 0); err != nil {
return err
}
out.Extensions = make([]NamedExtension, 0, 0)
if err := s.Convert(&in.Extensions, &out.Extensions, 0); err != nil {
return err
}
return nil
},
func(in *[]NamedCluster, out *map[string]*api.Cluster, s conversion.Scope) error {
for _, curr := range *in {
newCluster := api.NewCluster()
if err := s.Convert(&curr.Cluster, newCluster, 0); err != nil {
return err
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newCluster
} else {
return fmt.Errorf("error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
},
func(in *map[string]*api.Cluster, out *[]NamedCluster, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newCluster := (*in)[key]
oldCluster := &Cluster{}
if err := s.Convert(newCluster, oldCluster, 0); err != nil {
return err
}
namedCluster := NamedCluster{key, *oldCluster}
*out = append(*out, namedCluster)
}
return nil
},
func(in *[]NamedAuthInfo, out *map[string]*api.AuthInfo, s conversion.Scope) error {
for _, curr := range *in {
newAuthInfo := api.NewAuthInfo()
if err := s.Convert(&curr.AuthInfo, newAuthInfo, 0); err != nil {
return err
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newAuthInfo
} else {
return fmt.Errorf("error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
},
func(in *map[string]*api.AuthInfo, out *[]NamedAuthInfo, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newAuthInfo := (*in)[key]
oldAuthInfo := &AuthInfo{}
if err := s.Convert(newAuthInfo, oldAuthInfo, 0); err != nil {
return err
}
namedAuthInfo := NamedAuthInfo{key, *oldAuthInfo}
*out = append(*out, namedAuthInfo)
}
return nil
},
func(in *[]NamedContext, out *map[string]*api.Context, s conversion.Scope) error {
for _, curr := range *in {
newContext := api.NewContext()
if err := s.Convert(&curr.Context, newContext, 0); err != nil {
return err
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newContext
} else {
return fmt.Errorf("error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
},
func(in *map[string]*api.Context, out *[]NamedContext, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newContext := (*in)[key]
oldContext := &Context{}
if err := s.Convert(newContext, oldContext, 0); err != nil {
return err
}
namedContext := NamedContext{key, *oldContext}
*out = append(*out, namedContext)
}
return nil
},
func(in *[]NamedExtension, out *map[string]runtime.Object, s conversion.Scope) error {
for _, curr := range *in {
var newExtension runtime.Object
if err := s.Convert(&curr.Extension, &newExtension, 0); err != nil {
return err
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newExtension
} else {
return fmt.Errorf("error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
},
func(in *map[string]runtime.Object, out *[]NamedExtension, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newExtension := (*in)[key]
oldExtension := &runtime.RawExtension{}
if err := s.Convert(newExtension, oldExtension, 0); err != nil {
return err
}
namedExtension := NamedExtension{key, *oldExtension}
*out = append(*out, namedExtension)
}
return nil
},
)
func Convert_Slice_v1_NamedCluster_To_Map_string_To_Pointer_api_Cluster(in *[]NamedCluster, out *map[string]*api.Cluster, s conversion.Scope) error {
for _, curr := range *in {
newCluster := api.NewCluster()
if err := Convert_v1_Cluster_To_api_Cluster(&curr.Cluster, newCluster, s); err != nil {
return err
}
if *out == nil {
*out = make(map[string]*api.Cluster)
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newCluster
} else {
return fmt.Errorf("error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
}
func Convert_Map_string_To_Pointer_api_Cluster_To_Slice_v1_NamedCluster(in *map[string]*api.Cluster, out *[]NamedCluster, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newCluster := (*in)[key]
oldCluster := Cluster{}
if err := Convert_api_Cluster_To_v1_Cluster(newCluster, &oldCluster, s); err != nil {
return err
}
namedCluster := NamedCluster{key, oldCluster}
*out = append(*out, namedCluster)
}
return nil
}
func Convert_Slice_v1_NamedAuthInfo_To_Map_string_To_Pointer_api_AuthInfo(in *[]NamedAuthInfo, out *map[string]*api.AuthInfo, s conversion.Scope) error {
for _, curr := range *in {
newAuthInfo := api.NewAuthInfo()
if err := Convert_v1_AuthInfo_To_api_AuthInfo(&curr.AuthInfo, newAuthInfo, s); err != nil {
return err
}
if *out == nil {
*out = make(map[string]*api.AuthInfo)
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newAuthInfo
} else {
return fmt.Errorf("error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
}
func Convert_Map_string_To_Pointer_api_AuthInfo_To_Slice_v1_NamedAuthInfo(in *map[string]*api.AuthInfo, out *[]NamedAuthInfo, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newAuthInfo := (*in)[key]
oldAuthInfo := AuthInfo{}
if err := Convert_api_AuthInfo_To_v1_AuthInfo(newAuthInfo, &oldAuthInfo, s); err != nil {
return err
}
namedAuthInfo := NamedAuthInfo{key, oldAuthInfo}
*out = append(*out, namedAuthInfo)
}
return nil
}
func Convert_Slice_v1_NamedContext_To_Map_string_To_Pointer_api_Context(in *[]NamedContext, out *map[string]*api.Context, s conversion.Scope) error {
for _, curr := range *in {
newContext := api.NewContext()
if err := Convert_v1_Context_To_api_Context(&curr.Context, newContext, s); err != nil {
return err
}
if *out == nil {
*out = make(map[string]*api.Context)
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newContext
} else {
return fmt.Errorf("error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
}
func Convert_Map_string_To_Pointer_api_Context_To_Slice_v1_NamedContext(in *map[string]*api.Context, out *[]NamedContext, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newContext := (*in)[key]
oldContext := Context{}
if err := Convert_api_Context_To_v1_Context(newContext, &oldContext, s); err != nil {
return err
}
namedContext := NamedContext{key, oldContext}
*out = append(*out, namedContext)
}
return nil
}
func Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(in *[]NamedExtension, out *map[string]runtime.Object, s conversion.Scope) error {
for _, curr := range *in {
var newExtension runtime.Object
if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&curr.Extension, &newExtension, s); err != nil {
return err
}
if *out == nil {
*out = make(map[string]runtime.Object)
}
if (*out)[curr.Name] == nil {
(*out)[curr.Name] = newExtension
} else {
return fmt.Errorf("error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"%v\" in list: %v", curr.Name, *in)
}
}
return nil
}
func Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(in *map[string]runtime.Object, out *[]NamedExtension, s conversion.Scope) error {
allKeys := make([]string, 0, len(*in))
for key := range *in {
allKeys = append(allKeys, key)
}
sort.Strings(allKeys)
for _, key := range allKeys {
newExtension := (*in)[key]
oldExtension := runtime.RawExtension{}
if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&newExtension, &oldExtension, s); err != nil {
return nil
}
namedExtension := NamedExtension{key, oldExtension}
*out = append(*out, namedExtension)
}
return nil
}

View File

@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:conversion-gen=k8s.io/client-go/tools/clientcmd/api
// +k8s:deepcopy-gen=package
package v1

View File

@@ -37,7 +37,7 @@ func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes, addConversionFuncs)
localSchemeBuilder.Register(addKnownTypes)
}
func addKnownTypes(scheme *runtime.Scheme) error {

View File

@@ -28,10 +28,12 @@ import (
type Config struct {
// Legacy field from pkg/api/types.go TypeMeta.
// TODO(jlowdermilk): remove this after eliminating downstream dependencies.
// +k8s:conversion-gen=false
// +optional
Kind string `json:"kind,omitempty"`
// Legacy field from pkg/api/types.go TypeMeta.
// TODO(jlowdermilk): remove this after eliminating downstream dependencies.
// +k8s:conversion-gen=false
// +optional
APIVersion string `json:"apiVersion,omitempty"`
// Preferences holds general information to be use for cli interactions
@@ -61,6 +63,9 @@ type Preferences struct {
type Cluster struct {
// Server is the address of the kubernetes cluster (https://hostname:port).
Server string `json:"server"`
// TLSServerName is used to check server certificate. If TLSServerName is empty, the hostname used to contact the server is used.
// +optional
TLSServerName string `json:"tls-server-name,omitempty"`
// InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure.
// +optional
InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"`
@@ -70,6 +75,17 @@ type Cluster struct {
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
// +optional
CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"`
// ProxyURL is the URL to the proxy to be used for all requests made by this
// client. URLs with "http", "https", and "socks5" schemes are supported. If
// this configuration is not provided or the empty string, the client
// attempts to construct a proxy configuration from http_proxy and
// https_proxy environment variables. If these environment variables are not
// set, the client does not attempt to proxy requests.
//
// socks5 proxying does not currently support spdy streaming endpoints (exec,
// attach, port forward).
// +optional
ProxyURL string `json:"proxy-url,omitempty"`
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
// +optional
Extensions []NamedExtension `json:"extensions,omitempty"`
@@ -88,10 +104,10 @@ type AuthInfo struct {
ClientKey string `json:"client-key,omitempty"`
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
// +optional
ClientKeyData []byte `json:"client-key-data,omitempty"`
ClientKeyData []byte `json:"client-key-data,omitempty" datapolicy:"security-key"`
// Token is the bearer token for authentication to the kubernetes cluster.
// +optional
Token string `json:"token,omitempty"`
Token string `json:"token,omitempty" datapolicy:"token"`
// TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence.
// +optional
TokenFile string `json:"tokenFile,omitempty"`
@@ -109,7 +125,7 @@ type AuthInfo struct {
Username string `json:"username,omitempty"`
// Password is the password for basic authentication to the kubernetes cluster.
// +optional
Password string `json:"password,omitempty"`
Password string `json:"password,omitempty" datapolicy:"password"`
// AuthProvider specifies a custom authentication plugin for the kubernetes cluster.
// +optional
AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty"`
@@ -176,7 +192,7 @@ type AuthProviderConfig struct {
// ExecConfig specifies a command to provide client credentials. The command is exec'd
// and outputs structured stdout holding credentials.
//
// See the client.authentiction.k8s.io API group for specifications of the exact input
// See the client.authentication.k8s.io API group for specifications of the exact input
// and output format
type ExecConfig struct {
// Command to execute.
@@ -193,6 +209,18 @@ type ExecConfig struct {
// Preferred input version of the ExecInfo. The returned ExecCredentials MUST use
// the same encoding version as the input.
APIVersion string `json:"apiVersion,omitempty"`
// This text is shown to the user when the executable doesn't seem to be
// present. For example, `brew install foo-cli` might be a good InstallHint for
// foo-cli on Mac OS systems.
InstallHint string `json:"installHint,omitempty"`
// ProvideClusterInfo determines whether or not to provide cluster information,
// which could potentially contain very large CA data, to this exec plugin as a
// part of the KUBERNETES_EXEC_INFO environment variable. By default, it is set
// to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
// reading this environment variable.
ProvideClusterInfo bool `json:"provideClusterInfo"`
}
// ExecEnvVar is used for setting environment variables when executing an exec-based

View File

@@ -0,0 +1,449 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1
import (
unsafe "unsafe"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
api "k8s.io/client-go/tools/clientcmd/api"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*AuthInfo)(nil), (*api.AuthInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AuthInfo_To_api_AuthInfo(a.(*AuthInfo), b.(*api.AuthInfo), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.AuthInfo)(nil), (*AuthInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_AuthInfo_To_v1_AuthInfo(a.(*api.AuthInfo), b.(*AuthInfo), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthProviderConfig)(nil), (*api.AuthProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_AuthProviderConfig_To_api_AuthProviderConfig(a.(*AuthProviderConfig), b.(*api.AuthProviderConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.AuthProviderConfig)(nil), (*AuthProviderConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_AuthProviderConfig_To_v1_AuthProviderConfig(a.(*api.AuthProviderConfig), b.(*AuthProviderConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Cluster)(nil), (*api.Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Cluster_To_api_Cluster(a.(*Cluster), b.(*api.Cluster), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.Cluster)(nil), (*Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_Cluster_To_v1_Cluster(a.(*api.Cluster), b.(*Cluster), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Config)(nil), (*api.Config)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Config_To_api_Config(a.(*Config), b.(*api.Config), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.Config)(nil), (*Config)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_Config_To_v1_Config(a.(*api.Config), b.(*Config), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Context)(nil), (*api.Context)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Context_To_api_Context(a.(*Context), b.(*api.Context), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.Context)(nil), (*Context)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_Context_To_v1_Context(a.(*api.Context), b.(*Context), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExecConfig)(nil), (*api.ExecConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ExecConfig_To_api_ExecConfig(a.(*ExecConfig), b.(*api.ExecConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.ExecConfig)(nil), (*ExecConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_ExecConfig_To_v1_ExecConfig(a.(*api.ExecConfig), b.(*ExecConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExecEnvVar)(nil), (*api.ExecEnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ExecEnvVar_To_api_ExecEnvVar(a.(*ExecEnvVar), b.(*api.ExecEnvVar), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.ExecEnvVar)(nil), (*ExecEnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_ExecEnvVar_To_v1_ExecEnvVar(a.(*api.ExecEnvVar), b.(*ExecEnvVar), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Preferences)(nil), (*api.Preferences)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Preferences_To_api_Preferences(a.(*Preferences), b.(*api.Preferences), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*api.Preferences)(nil), (*Preferences)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_api_Preferences_To_v1_Preferences(a.(*api.Preferences), b.(*Preferences), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*map[string]*api.AuthInfo)(nil), (*[]NamedAuthInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Map_string_To_Pointer_api_AuthInfo_To_Slice_v1_NamedAuthInfo(a.(*map[string]*api.AuthInfo), b.(*[]NamedAuthInfo), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*map[string]*api.Cluster)(nil), (*[]NamedCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Map_string_To_Pointer_api_Cluster_To_Slice_v1_NamedCluster(a.(*map[string]*api.Cluster), b.(*[]NamedCluster), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*map[string]*api.Context)(nil), (*[]NamedContext)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Map_string_To_Pointer_api_Context_To_Slice_v1_NamedContext(a.(*map[string]*api.Context), b.(*[]NamedContext), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*map[string]runtime.Object)(nil), (*[]NamedExtension)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(a.(*map[string]runtime.Object), b.(*[]NamedExtension), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*[]NamedAuthInfo)(nil), (*map[string]*api.AuthInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Slice_v1_NamedAuthInfo_To_Map_string_To_Pointer_api_AuthInfo(a.(*[]NamedAuthInfo), b.(*map[string]*api.AuthInfo), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*[]NamedCluster)(nil), (*map[string]*api.Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Slice_v1_NamedCluster_To_Map_string_To_Pointer_api_Cluster(a.(*[]NamedCluster), b.(*map[string]*api.Cluster), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*[]NamedContext)(nil), (*map[string]*api.Context)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Slice_v1_NamedContext_To_Map_string_To_Pointer_api_Context(a.(*[]NamedContext), b.(*map[string]*api.Context), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*[]NamedExtension)(nil), (*map[string]runtime.Object)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(a.(*[]NamedExtension), b.(*map[string]runtime.Object), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1_AuthInfo_To_api_AuthInfo(in *AuthInfo, out *api.AuthInfo, s conversion.Scope) error {
out.ClientCertificate = in.ClientCertificate
out.ClientCertificateData = *(*[]byte)(unsafe.Pointer(&in.ClientCertificateData))
out.ClientKey = in.ClientKey
out.ClientKeyData = *(*[]byte)(unsafe.Pointer(&in.ClientKeyData))
out.Token = in.Token
out.TokenFile = in.TokenFile
out.Impersonate = in.Impersonate
out.ImpersonateGroups = *(*[]string)(unsafe.Pointer(&in.ImpersonateGroups))
out.ImpersonateUserExtra = *(*map[string][]string)(unsafe.Pointer(&in.ImpersonateUserExtra))
out.Username = in.Username
out.Password = in.Password
out.AuthProvider = (*api.AuthProviderConfig)(unsafe.Pointer(in.AuthProvider))
if in.Exec != nil {
in, out := &in.Exec, &out.Exec
*out = new(api.ExecConfig)
if err := Convert_v1_ExecConfig_To_api_ExecConfig(*in, *out, s); err != nil {
return err
}
} else {
out.Exec = nil
}
if err := Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_v1_AuthInfo_To_api_AuthInfo is an autogenerated conversion function.
func Convert_v1_AuthInfo_To_api_AuthInfo(in *AuthInfo, out *api.AuthInfo, s conversion.Scope) error {
return autoConvert_v1_AuthInfo_To_api_AuthInfo(in, out, s)
}
func autoConvert_api_AuthInfo_To_v1_AuthInfo(in *api.AuthInfo, out *AuthInfo, s conversion.Scope) error {
// INFO: in.LocationOfOrigin opted out of conversion generation
out.ClientCertificate = in.ClientCertificate
out.ClientCertificateData = *(*[]byte)(unsafe.Pointer(&in.ClientCertificateData))
out.ClientKey = in.ClientKey
out.ClientKeyData = *(*[]byte)(unsafe.Pointer(&in.ClientKeyData))
out.Token = in.Token
out.TokenFile = in.TokenFile
out.Impersonate = in.Impersonate
out.ImpersonateGroups = *(*[]string)(unsafe.Pointer(&in.ImpersonateGroups))
out.ImpersonateUserExtra = *(*map[string][]string)(unsafe.Pointer(&in.ImpersonateUserExtra))
out.Username = in.Username
out.Password = in.Password
out.AuthProvider = (*AuthProviderConfig)(unsafe.Pointer(in.AuthProvider))
if in.Exec != nil {
in, out := &in.Exec, &out.Exec
*out = new(ExecConfig)
if err := Convert_api_ExecConfig_To_v1_ExecConfig(*in, *out, s); err != nil {
return err
}
} else {
out.Exec = nil
}
if err := Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_api_AuthInfo_To_v1_AuthInfo is an autogenerated conversion function.
func Convert_api_AuthInfo_To_v1_AuthInfo(in *api.AuthInfo, out *AuthInfo, s conversion.Scope) error {
return autoConvert_api_AuthInfo_To_v1_AuthInfo(in, out, s)
}
func autoConvert_v1_AuthProviderConfig_To_api_AuthProviderConfig(in *AuthProviderConfig, out *api.AuthProviderConfig, s conversion.Scope) error {
out.Name = in.Name
out.Config = *(*map[string]string)(unsafe.Pointer(&in.Config))
return nil
}
// Convert_v1_AuthProviderConfig_To_api_AuthProviderConfig is an autogenerated conversion function.
func Convert_v1_AuthProviderConfig_To_api_AuthProviderConfig(in *AuthProviderConfig, out *api.AuthProviderConfig, s conversion.Scope) error {
return autoConvert_v1_AuthProviderConfig_To_api_AuthProviderConfig(in, out, s)
}
func autoConvert_api_AuthProviderConfig_To_v1_AuthProviderConfig(in *api.AuthProviderConfig, out *AuthProviderConfig, s conversion.Scope) error {
out.Name = in.Name
out.Config = *(*map[string]string)(unsafe.Pointer(&in.Config))
return nil
}
// Convert_api_AuthProviderConfig_To_v1_AuthProviderConfig is an autogenerated conversion function.
func Convert_api_AuthProviderConfig_To_v1_AuthProviderConfig(in *api.AuthProviderConfig, out *AuthProviderConfig, s conversion.Scope) error {
return autoConvert_api_AuthProviderConfig_To_v1_AuthProviderConfig(in, out, s)
}
func autoConvert_v1_Cluster_To_api_Cluster(in *Cluster, out *api.Cluster, s conversion.Scope) error {
out.Server = in.Server
out.TLSServerName = in.TLSServerName
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
out.CertificateAuthority = in.CertificateAuthority
out.CertificateAuthorityData = *(*[]byte)(unsafe.Pointer(&in.CertificateAuthorityData))
out.ProxyURL = in.ProxyURL
if err := Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_v1_Cluster_To_api_Cluster is an autogenerated conversion function.
func Convert_v1_Cluster_To_api_Cluster(in *Cluster, out *api.Cluster, s conversion.Scope) error {
return autoConvert_v1_Cluster_To_api_Cluster(in, out, s)
}
func autoConvert_api_Cluster_To_v1_Cluster(in *api.Cluster, out *Cluster, s conversion.Scope) error {
// INFO: in.LocationOfOrigin opted out of conversion generation
out.Server = in.Server
out.TLSServerName = in.TLSServerName
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
out.CertificateAuthority = in.CertificateAuthority
out.CertificateAuthorityData = *(*[]byte)(unsafe.Pointer(&in.CertificateAuthorityData))
out.ProxyURL = in.ProxyURL
if err := Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_api_Cluster_To_v1_Cluster is an autogenerated conversion function.
func Convert_api_Cluster_To_v1_Cluster(in *api.Cluster, out *Cluster, s conversion.Scope) error {
return autoConvert_api_Cluster_To_v1_Cluster(in, out, s)
}
func autoConvert_v1_Config_To_api_Config(in *Config, out *api.Config, s conversion.Scope) error {
// INFO: in.Kind opted out of conversion generation
// INFO: in.APIVersion opted out of conversion generation
if err := Convert_v1_Preferences_To_api_Preferences(&in.Preferences, &out.Preferences, s); err != nil {
return err
}
if err := Convert_Slice_v1_NamedCluster_To_Map_string_To_Pointer_api_Cluster(&in.Clusters, &out.Clusters, s); err != nil {
return err
}
if err := Convert_Slice_v1_NamedAuthInfo_To_Map_string_To_Pointer_api_AuthInfo(&in.AuthInfos, &out.AuthInfos, s); err != nil {
return err
}
if err := Convert_Slice_v1_NamedContext_To_Map_string_To_Pointer_api_Context(&in.Contexts, &out.Contexts, s); err != nil {
return err
}
out.CurrentContext = in.CurrentContext
if err := Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_v1_Config_To_api_Config is an autogenerated conversion function.
func Convert_v1_Config_To_api_Config(in *Config, out *api.Config, s conversion.Scope) error {
return autoConvert_v1_Config_To_api_Config(in, out, s)
}
func autoConvert_api_Config_To_v1_Config(in *api.Config, out *Config, s conversion.Scope) error {
// INFO: in.Kind opted out of conversion generation
// INFO: in.APIVersion opted out of conversion generation
if err := Convert_api_Preferences_To_v1_Preferences(&in.Preferences, &out.Preferences, s); err != nil {
return err
}
if err := Convert_Map_string_To_Pointer_api_Cluster_To_Slice_v1_NamedCluster(&in.Clusters, &out.Clusters, s); err != nil {
return err
}
if err := Convert_Map_string_To_Pointer_api_AuthInfo_To_Slice_v1_NamedAuthInfo(&in.AuthInfos, &out.AuthInfos, s); err != nil {
return err
}
if err := Convert_Map_string_To_Pointer_api_Context_To_Slice_v1_NamedContext(&in.Contexts, &out.Contexts, s); err != nil {
return err
}
out.CurrentContext = in.CurrentContext
if err := Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_api_Config_To_v1_Config is an autogenerated conversion function.
func Convert_api_Config_To_v1_Config(in *api.Config, out *Config, s conversion.Scope) error {
return autoConvert_api_Config_To_v1_Config(in, out, s)
}
func autoConvert_v1_Context_To_api_Context(in *Context, out *api.Context, s conversion.Scope) error {
out.Cluster = in.Cluster
out.AuthInfo = in.AuthInfo
out.Namespace = in.Namespace
if err := Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_v1_Context_To_api_Context is an autogenerated conversion function.
func Convert_v1_Context_To_api_Context(in *Context, out *api.Context, s conversion.Scope) error {
return autoConvert_v1_Context_To_api_Context(in, out, s)
}
func autoConvert_api_Context_To_v1_Context(in *api.Context, out *Context, s conversion.Scope) error {
// INFO: in.LocationOfOrigin opted out of conversion generation
out.Cluster = in.Cluster
out.AuthInfo = in.AuthInfo
out.Namespace = in.Namespace
if err := Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_api_Context_To_v1_Context is an autogenerated conversion function.
func Convert_api_Context_To_v1_Context(in *api.Context, out *Context, s conversion.Scope) error {
return autoConvert_api_Context_To_v1_Context(in, out, s)
}
func autoConvert_v1_ExecConfig_To_api_ExecConfig(in *ExecConfig, out *api.ExecConfig, s conversion.Scope) error {
out.Command = in.Command
out.Args = *(*[]string)(unsafe.Pointer(&in.Args))
out.Env = *(*[]api.ExecEnvVar)(unsafe.Pointer(&in.Env))
out.APIVersion = in.APIVersion
out.InstallHint = in.InstallHint
out.ProvideClusterInfo = in.ProvideClusterInfo
return nil
}
// Convert_v1_ExecConfig_To_api_ExecConfig is an autogenerated conversion function.
func Convert_v1_ExecConfig_To_api_ExecConfig(in *ExecConfig, out *api.ExecConfig, s conversion.Scope) error {
return autoConvert_v1_ExecConfig_To_api_ExecConfig(in, out, s)
}
func autoConvert_api_ExecConfig_To_v1_ExecConfig(in *api.ExecConfig, out *ExecConfig, s conversion.Scope) error {
out.Command = in.Command
out.Args = *(*[]string)(unsafe.Pointer(&in.Args))
out.Env = *(*[]ExecEnvVar)(unsafe.Pointer(&in.Env))
out.APIVersion = in.APIVersion
out.InstallHint = in.InstallHint
out.ProvideClusterInfo = in.ProvideClusterInfo
// INFO: in.Config opted out of conversion generation
return nil
}
// Convert_api_ExecConfig_To_v1_ExecConfig is an autogenerated conversion function.
func Convert_api_ExecConfig_To_v1_ExecConfig(in *api.ExecConfig, out *ExecConfig, s conversion.Scope) error {
return autoConvert_api_ExecConfig_To_v1_ExecConfig(in, out, s)
}
func autoConvert_v1_ExecEnvVar_To_api_ExecEnvVar(in *ExecEnvVar, out *api.ExecEnvVar, s conversion.Scope) error {
out.Name = in.Name
out.Value = in.Value
return nil
}
// Convert_v1_ExecEnvVar_To_api_ExecEnvVar is an autogenerated conversion function.
func Convert_v1_ExecEnvVar_To_api_ExecEnvVar(in *ExecEnvVar, out *api.ExecEnvVar, s conversion.Scope) error {
return autoConvert_v1_ExecEnvVar_To_api_ExecEnvVar(in, out, s)
}
func autoConvert_api_ExecEnvVar_To_v1_ExecEnvVar(in *api.ExecEnvVar, out *ExecEnvVar, s conversion.Scope) error {
out.Name = in.Name
out.Value = in.Value
return nil
}
// Convert_api_ExecEnvVar_To_v1_ExecEnvVar is an autogenerated conversion function.
func Convert_api_ExecEnvVar_To_v1_ExecEnvVar(in *api.ExecEnvVar, out *ExecEnvVar, s conversion.Scope) error {
return autoConvert_api_ExecEnvVar_To_v1_ExecEnvVar(in, out, s)
}
func autoConvert_v1_Preferences_To_api_Preferences(in *Preferences, out *api.Preferences, s conversion.Scope) error {
out.Colors = in.Colors
if err := Convert_Slice_v1_NamedExtension_To_Map_string_To_runtime_Object(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_v1_Preferences_To_api_Preferences is an autogenerated conversion function.
func Convert_v1_Preferences_To_api_Preferences(in *Preferences, out *api.Preferences, s conversion.Scope) error {
return autoConvert_v1_Preferences_To_api_Preferences(in, out, s)
}
func autoConvert_api_Preferences_To_v1_Preferences(in *api.Preferences, out *Preferences, s conversion.Scope) error {
out.Colors = in.Colors
if err := Convert_Map_string_To_runtime_Object_To_Slice_v1_NamedExtension(&in.Extensions, &out.Extensions, s); err != nil {
return err
}
return nil
}
// Convert_api_Preferences_To_v1_Preferences is an autogenerated conversion function.
func Convert_api_Preferences_To_v1_Preferences(in *api.Preferences, out *Preferences, s conversion.Scope) error {
return autoConvert_api_Preferences_To_v1_Preferences(in, out, s)
}

View File

@@ -267,6 +267,9 @@ func (in *ExecConfig) DeepCopyInto(out *ExecConfig) {
*out = make([]ExecEnvVar, len(*in))
copy(*out, *in)
}
if in.Config != nil {
out.Config = in.Config.DeepCopyObject()
}
return
}

View File

@@ -23,7 +23,7 @@ import (
"io/ioutil"
"os"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
clientauth "k8s.io/client-go/tools/auth"
)
@@ -90,8 +90,8 @@ func promptForString(field string, r io.Reader, show bool) (result string, err e
_, err = fmt.Fscan(r, &result)
} else {
var data []byte
if terminal.IsTerminal(int(os.Stdin.Fd())) {
data, err = terminal.ReadPassword(int(os.Stdin.Fd()))
if term.IsTerminal(int(os.Stdin.Fd())) {
data, err = term.ReadPassword(int(os.Stdin.Fd()))
result = string(data)
} else {
return "", fmt.Errorf("error reading input for %s", field)

View File

@@ -20,16 +20,23 @@ import (
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"github.com/imdario/mergo"
"k8s.io/klog"
"unicode"
restclient "k8s.io/client-go/rest"
clientauth "k8s.io/client-go/tools/auth"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/klog/v2"
"github.com/imdario/mergo"
)
const (
// clusterExtensionKey is reserved in the cluster extensions list for exec plugin config.
clusterExtensionKey = "client.authentication.k8s.io/exec"
)
var (
@@ -70,7 +77,7 @@ type PersistAuthProviderConfigForUser func(user string) restclient.AuthProviderC
type promptedCredentials struct {
username string
password string
password string `datapolicy:"password"`
}
// DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information
@@ -150,8 +157,15 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
clientConfig := &restclient.Config{}
clientConfig.Host = configClusterInfo.Server
if configClusterInfo.ProxyURL != "" {
u, err := parseProxyURL(configClusterInfo.ProxyURL)
if err != nil {
return nil, err
}
clientConfig.Proxy = http.ProxyURL(u)
}
if len(config.overrides.Timeout) > 0 {
if config.overrides != nil && len(config.overrides.Timeout) > 0 {
timeout, err := ParseTimeout(config.overrides.Timeout)
if err != nil {
return nil, err
@@ -180,17 +194,17 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
authInfoName, _ := config.getAuthInfoName()
persister = PersisterForUser(config.configAccess, authInfoName)
}
userAuthPartialConfig, err := config.getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister)
userAuthPartialConfig, err := config.getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister, configClusterInfo)
if err != nil {
return nil, err
}
mergo.MergeWithOverwrite(clientConfig, userAuthPartialConfig)
mergo.Merge(clientConfig, userAuthPartialConfig, mergo.WithOverride)
serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo)
if err != nil {
return nil, err
}
mergo.MergeWithOverwrite(clientConfig, serverAuthPartialConfig)
mergo.Merge(clientConfig, serverAuthPartialConfig, mergo.WithOverride)
}
return clientConfig, nil
@@ -210,7 +224,8 @@ func getServerIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo,
configClientConfig.CAFile = configClusterInfo.CertificateAuthority
configClientConfig.CAData = configClusterInfo.CertificateAuthorityData
configClientConfig.Insecure = configClusterInfo.InsecureSkipTLSVerify
mergo.MergeWithOverwrite(mergedConfig, configClientConfig)
configClientConfig.ServerName = configClusterInfo.TLSServerName
mergo.Merge(mergedConfig, configClientConfig, mergo.WithOverride)
return mergedConfig, nil
}
@@ -222,12 +237,13 @@ func getServerIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo,
// 2. configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority)
// 3. if there is not enough information to identify the user, load try the ~/.kubernetes_auth file
// 4. if there is not enough information to identify the user, prompt if possible
func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig restclient.AuthProviderConfigPersister) (*restclient.Config, error) {
func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig restclient.AuthProviderConfigPersister, configClusterInfo clientcmdapi.Cluster) (*restclient.Config, error) {
mergedConfig := &restclient.Config{}
// blindly overwrite existing values based on precedence
if len(configAuthInfo.Token) > 0 {
mergedConfig.BearerToken = configAuthInfo.Token
mergedConfig.BearerTokenFile = configAuthInfo.TokenFile
} else if len(configAuthInfo.TokenFile) > 0 {
tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile)
if err != nil {
@@ -259,6 +275,8 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
}
if configAuthInfo.Exec != nil {
mergedConfig.ExecProvider = configAuthInfo.Exec
mergedConfig.ExecProvider.InstallHint = cleanANSIEscapeCodes(mergedConfig.ExecProvider.InstallHint)
mergedConfig.ExecProvider.Config = configClusterInfo.Extensions[clusterExtensionKey]
}
// if there still isn't enough information to authenticate the user, try prompting
@@ -276,8 +294,8 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo)
previouslyMergedConfig := mergedConfig
mergedConfig = &restclient.Config{}
mergo.MergeWithOverwrite(mergedConfig, promptedConfig)
mergo.MergeWithOverwrite(mergedConfig, previouslyMergedConfig)
mergo.Merge(mergedConfig, promptedConfig, mergo.WithOverride)
mergo.Merge(mergedConfig, previouslyMergedConfig, mergo.WithOverride)
config.promptedCredentials.username = mergedConfig.Username
config.promptedCredentials.password = mergedConfig.Password
}
@@ -296,16 +314,6 @@ func makeUserIdentificationConfig(info clientauth.Info) *restclient.Config {
return config
}
// makeUserIdentificationFieldsConfig returns a client.Config capable of being merged using mergo for only server identification information
func makeServerIdentificationConfig(info clientauth.Info) restclient.Config {
config := restclient.Config{}
config.CAFile = info.CAFile
if info.Insecure != nil {
config.Insecure = *info.Insecure
}
return config
}
func canIdentifyUser(config restclient.Config) bool {
return len(config.Username) > 0 ||
(len(config.CertFile) > 0 || len(config.CertData) > 0) ||
@@ -314,6 +322,41 @@ func canIdentifyUser(config restclient.Config) bool {
config.ExecProvider != nil
}
// cleanANSIEscapeCodes takes an arbitrary string and ensures that there are no
// ANSI escape sequences that could put the terminal in a weird state (e.g.,
// "\e[1m" bolds text)
func cleanANSIEscapeCodes(s string) string {
// spaceControlCharacters includes tab, new line, vertical tab, new page, and
// carriage return. These are in the unicode.Cc category, but that category also
// contains ESC (U+001B) which we don't want.
spaceControlCharacters := unicode.RangeTable{
R16: []unicode.Range16{
{Lo: 0x0009, Hi: 0x000D, Stride: 1},
},
}
// Why not make this deny-only (instead of allow-only)? Because unicode.C
// contains newline and tab characters that we want.
allowedRanges := []*unicode.RangeTable{
unicode.L,
unicode.M,
unicode.N,
unicode.P,
unicode.S,
unicode.Z,
&spaceControlCharacters,
}
builder := strings.Builder{}
for _, roon := range s {
if unicode.IsOneOf(allowedRanges, roon) {
builder.WriteRune(roon) // returns nil error, per go doc
} else {
fmt.Fprintf(&builder, "%U", roon)
}
}
return builder.String()
}
// Namespace implements ClientConfig
func (config *DirectClientConfig) Namespace() (string, bool, error) {
if config.overrides != nil && config.overrides.Context.Namespace != "" {
@@ -381,7 +424,7 @@ func (config *DirectClientConfig) ConfirmUsable() error {
// getContextName returns the default, or user-set context name, and a boolean that indicates
// whether the default context name has been overwritten by a user-set flag, or left as its default value
func (config *DirectClientConfig) getContextName() (string, bool) {
if len(config.overrides.CurrentContext) != 0 {
if config.overrides != nil && len(config.overrides.CurrentContext) != 0 {
return config.overrides.CurrentContext, true
}
if len(config.contextName) != 0 {
@@ -395,7 +438,7 @@ func (config *DirectClientConfig) getContextName() (string, bool) {
// and a boolean indicating whether the default authInfo name is overwritten by a user-set flag, or
// left as its default value
func (config *DirectClientConfig) getAuthInfoName() (string, bool) {
if len(config.overrides.Context.AuthInfo) != 0 {
if config.overrides != nil && len(config.overrides.Context.AuthInfo) != 0 {
return config.overrides.Context.AuthInfo, true
}
context, _ := config.getContext()
@@ -406,7 +449,7 @@ func (config *DirectClientConfig) getAuthInfoName() (string, bool) {
// indicating whether the default clusterName has been overwritten by a user-set flag, or left as
// its default value
func (config *DirectClientConfig) getClusterName() (string, bool) {
if len(config.overrides.Context.Cluster) != 0 {
if config.overrides != nil && len(config.overrides.Context.Cluster) != 0 {
return config.overrides.Context.Cluster, true
}
context, _ := config.getContext()
@@ -420,11 +463,13 @@ func (config *DirectClientConfig) getContext() (clientcmdapi.Context, error) {
mergedContext := clientcmdapi.NewContext()
if configContext, exists := contexts[contextName]; exists {
mergo.MergeWithOverwrite(mergedContext, configContext)
mergo.Merge(mergedContext, configContext, mergo.WithOverride)
} else if required {
return clientcmdapi.Context{}, fmt.Errorf("context %q does not exist", contextName)
}
mergo.MergeWithOverwrite(mergedContext, config.overrides.Context)
if config.overrides != nil {
mergo.Merge(mergedContext, config.overrides.Context, mergo.WithOverride)
}
return *mergedContext, nil
}
@@ -436,11 +481,13 @@ func (config *DirectClientConfig) getAuthInfo() (clientcmdapi.AuthInfo, error) {
mergedAuthInfo := clientcmdapi.NewAuthInfo()
if configAuthInfo, exists := authInfos[authInfoName]; exists {
mergo.MergeWithOverwrite(mergedAuthInfo, configAuthInfo)
mergo.Merge(mergedAuthInfo, configAuthInfo, mergo.WithOverride)
} else if required {
return clientcmdapi.AuthInfo{}, fmt.Errorf("auth info %q does not exist", authInfoName)
}
mergo.MergeWithOverwrite(mergedAuthInfo, config.overrides.AuthInfo)
if config.overrides != nil {
mergo.Merge(mergedAuthInfo, config.overrides.AuthInfo, mergo.WithOverride)
}
return *mergedAuthInfo, nil
}
@@ -451,20 +498,37 @@ func (config *DirectClientConfig) getCluster() (clientcmdapi.Cluster, error) {
clusterInfoName, required := config.getClusterName()
mergedClusterInfo := clientcmdapi.NewCluster()
mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterDefaults)
if config.overrides != nil {
mergo.Merge(mergedClusterInfo, config.overrides.ClusterDefaults, mergo.WithOverride)
}
if configClusterInfo, exists := clusterInfos[clusterInfoName]; exists {
mergo.MergeWithOverwrite(mergedClusterInfo, configClusterInfo)
mergo.Merge(mergedClusterInfo, configClusterInfo, mergo.WithOverride)
} else if required {
return clientcmdapi.Cluster{}, fmt.Errorf("cluster %q does not exist", clusterInfoName)
}
mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterInfo)
// An override of --insecure-skip-tls-verify=true and no accompanying CA/CA data should clear already-set CA/CA data
// otherwise, a kubeconfig containing a CA reference would return an error that "CA and insecure-skip-tls-verify couldn't both be set"
caLen := len(config.overrides.ClusterInfo.CertificateAuthority)
caDataLen := len(config.overrides.ClusterInfo.CertificateAuthorityData)
if config.overrides.ClusterInfo.InsecureSkipTLSVerify && caLen == 0 && caDataLen == 0 {
mergedClusterInfo.CertificateAuthority = ""
mergedClusterInfo.CertificateAuthorityData = nil
if config.overrides != nil {
mergo.Merge(mergedClusterInfo, config.overrides.ClusterInfo, mergo.WithOverride)
}
// * An override of --insecure-skip-tls-verify=true and no accompanying CA/CA data should clear already-set CA/CA data
// otherwise, a kubeconfig containing a CA reference would return an error that "CA and insecure-skip-tls-verify couldn't both be set".
// * An override of --certificate-authority should also override TLS skip settings and CA data, otherwise existing CA data will take precedence.
if config.overrides != nil {
caLen := len(config.overrides.ClusterInfo.CertificateAuthority)
caDataLen := len(config.overrides.ClusterInfo.CertificateAuthorityData)
if config.overrides.ClusterInfo.InsecureSkipTLSVerify || caLen > 0 || caDataLen > 0 {
mergedClusterInfo.InsecureSkipTLSVerify = config.overrides.ClusterInfo.InsecureSkipTLSVerify
mergedClusterInfo.CertificateAuthority = config.overrides.ClusterInfo.CertificateAuthority
mergedClusterInfo.CertificateAuthorityData = config.overrides.ClusterInfo.CertificateAuthorityData
}
// if the --tls-server-name has been set in overrides, use that value.
// if the --server has been set in overrides, then use the value of --tls-server-name specified on the CLI too. This gives the property
// that setting a --server will effectively clear the KUBECONFIG value of tls-server-name if it is specified on the command line which is
// usually correct.
if config.overrides.ClusterInfo.TLSServerName != "" || config.overrides.ClusterInfo.Server != "" {
mergedClusterInfo.TLSServerName = config.overrides.ClusterInfo.TLSServerName
}
}
return *mergedClusterInfo, nil
@@ -484,11 +548,12 @@ func (config *inClusterClientConfig) RawConfig() (clientcmdapi.Config, error) {
}
func (config *inClusterClientConfig) ClientConfig() (*restclient.Config, error) {
if config.inClusterConfigProvider == nil {
config.inClusterConfigProvider = restclient.InClusterConfig
inClusterConfigProvider := config.inClusterConfigProvider
if inClusterConfigProvider == nil {
inClusterConfigProvider = restclient.InClusterConfig
}
icc, err := config.inClusterConfigProvider()
icc, err := inClusterConfigProvider()
if err != nil {
return nil, err
}
@@ -499,15 +564,16 @@ func (config *inClusterClientConfig) ClientConfig() (*restclient.Config, error)
if server := config.overrides.ClusterInfo.Server; len(server) > 0 {
icc.Host = server
}
if token := config.overrides.AuthInfo.Token; len(token) > 0 {
icc.BearerToken = token
if len(config.overrides.AuthInfo.Token) > 0 || len(config.overrides.AuthInfo.TokenFile) > 0 {
icc.BearerToken = config.overrides.AuthInfo.Token
icc.BearerTokenFile = config.overrides.AuthInfo.TokenFile
}
if certificateAuthorityFile := config.overrides.ClusterInfo.CertificateAuthority; len(certificateAuthorityFile) > 0 {
icc.TLSClientConfig.CAFile = certificateAuthorityFile
}
}
return icc, err
return icc, nil
}
func (config *inClusterClientConfig) Namespace() (string, bool, error) {
@@ -546,7 +612,7 @@ func (config *inClusterClientConfig) Possible() bool {
// to the default config.
func BuildConfigFromFlags(masterUrl, kubeconfigPath string) (*restclient.Config, error) {
if kubeconfigPath == "" && masterUrl == "" {
klog.Warningf("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.")
klog.Warning("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.")
kubeconfig, err := restclient.InClusterConfig()
if err == nil {
return kubeconfig, nil

View File

@@ -24,7 +24,7 @@ import (
"reflect"
"sort"
"k8s.io/klog"
"k8s.io/klog/v2"
restclient "k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
@@ -58,6 +58,15 @@ type PathOptions struct {
LoadingRules *ClientConfigLoadingRules
}
var (
// UseModifyConfigLock ensures that access to kubeconfig file using ModifyConfig method
// is being guarded by a lock file.
// This variable is intentionaly made public so other consumers of this library
// can modify its default behavior, but be caution when disabling it since
// this will make your code not threadsafe.
UseModifyConfigLock = true
)
func (o *PathOptions) GetEnvVarFiles() []string {
if len(o.EnvVar) == 0 {
return []string{}
@@ -74,10 +83,13 @@ func (o *PathOptions) GetEnvVarFiles() []string {
}
func (o *PathOptions) GetLoadingPrecedence() []string {
if o.IsExplicitFile() {
return []string{o.GetExplicitFile()}
}
if envVarFiles := o.GetEnvVarFiles(); len(envVarFiles) > 0 {
return envVarFiles
}
return []string{o.GlobalFile}
}
@@ -156,15 +168,17 @@ func NewDefaultPathOptions() *PathOptions {
// that means that this code will only write into a single file. If you want to relativizePaths, you must provide a fully qualified path in any
// modified element.
func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool) error {
possibleSources := configAccess.GetLoadingPrecedence()
// sort the possible kubeconfig files so we always "lock" in the same order
// to avoid deadlock (note: this can fail w/ symlinks, but... come on).
sort.Strings(possibleSources)
for _, filename := range possibleSources {
if err := lockFile(filename); err != nil {
return err
if UseModifyConfigLock {
possibleSources := configAccess.GetLoadingPrecedence()
// sort the possible kubeconfig files so we always "lock" in the same order
// to avoid deadlock (note: this can fail w/ symlinks, but... come on).
sort.Strings(possibleSources)
for _, filename := range possibleSources {
if err := lockFile(filename); err != nil {
return err
}
defer unlockFile(filename)
}
defer unlockFile(filename)
}
startingConfig, err := configAccess.GetStartingConfig()
@@ -360,7 +374,7 @@ func (p *persister) Persist(config map[string]string) error {
authInfo, ok := newConfig.AuthInfos[p.user]
if ok && authInfo.AuthProvider != nil {
authInfo.AuthProvider.Config = config
ModifyConfig(p.configAccess, *newConfig, false)
return ModifyConfig(p.configAccess, *newConfig, false)
}
return nil
}

View File

@@ -18,6 +18,7 @@ package clientcmd
import (
"fmt"
"net/url"
"strconv"
"time"
)
@@ -33,3 +34,17 @@ func ParseTimeout(duration string) (time.Duration, error) {
}
return 0, fmt.Errorf("Invalid timeout value. Timeout must be a single integer in seconds, or an integer followed by a corresponding time unit (e.g. 1s | 2m | 3h)")
}
func parseProxyURL(proxyURL string) (*url.URL, error) {
u, err := url.Parse(proxyURL)
if err != nil {
return nil, fmt.Errorf("could not parse: %v", proxyURL)
}
switch u.Scheme {
case "http", "https", "socks5":
default:
return nil, fmt.Errorf("unsupported scheme %q, must be http, https, or socks5", u.Scheme)
}
return u, nil
}

View File

@@ -18,17 +18,15 @@ package clientcmd
import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
goruntime "runtime"
"strings"
"github.com/imdario/mergo"
"k8s.io/klog"
"k8s.io/klog/v2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -48,24 +46,24 @@ const (
)
var (
RecommendedConfigDir = path.Join(homedir.HomeDir(), RecommendedHomeDir)
RecommendedHomeFile = path.Join(RecommendedConfigDir, RecommendedFileName)
RecommendedSchemaFile = path.Join(RecommendedConfigDir, RecommendedSchemaName)
RecommendedConfigDir = filepath.Join(homedir.HomeDir(), RecommendedHomeDir)
RecommendedHomeFile = filepath.Join(RecommendedConfigDir, RecommendedFileName)
RecommendedSchemaFile = filepath.Join(RecommendedConfigDir, RecommendedSchemaName)
)
// currentMigrationRules returns a map that holds the history of recommended home directories used in previous versions.
// Any future changes to RecommendedHomeFile and related are expected to add a migration rule here, in order to make
// sure existing config files are migrated to their new locations properly.
func currentMigrationRules() map[string]string {
oldRecommendedHomeFile := path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig")
oldRecommendedWindowsHomeFile := path.Join(os.Getenv("HOME"), RecommendedHomeDir, RecommendedFileName)
migrationRules := map[string]string{}
migrationRules[RecommendedHomeFile] = oldRecommendedHomeFile
var oldRecommendedHomeFileName string
if goruntime.GOOS == "windows" {
migrationRules[RecommendedHomeFile] = oldRecommendedWindowsHomeFile
oldRecommendedHomeFileName = RecommendedFileName
} else {
oldRecommendedHomeFileName = ".kubeconfig"
}
return map[string]string{
RecommendedHomeFile: filepath.Join(os.Getenv("HOME"), RecommendedHomeDir, oldRecommendedHomeFileName),
}
return migrationRules
}
type ClientConfigLoader interface {
@@ -127,6 +125,10 @@ type ClientConfigLoadingRules struct {
// DefaultClientConfig is an optional field indicating what rules to use to calculate a default configuration.
// This should match the overrides passed in to ClientConfig loader.
DefaultClientConfig ClientConfig
// WarnIfAllMissing indicates whether the configuration files pointed by KUBECONFIG environment variable are present or not.
// In case of missing files, it warns the user about the missing files.
WarnIfAllMissing bool
}
// ClientConfigLoadingRules implements the ClientConfigLoader interface.
@@ -136,20 +138,23 @@ var _ ClientConfigLoader = &ClientConfigLoadingRules{}
// use this constructor
func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
chain := []string{}
warnIfAllMissing := false
envVarFiles := os.Getenv(RecommendedConfigPathEnvVar)
if len(envVarFiles) != 0 {
fileList := filepath.SplitList(envVarFiles)
// prevent the same path load multiple times
chain = append(chain, deduplicate(fileList)...)
warnIfAllMissing = true
} else {
chain = append(chain, RecommendedHomeFile)
}
return &ClientConfigLoadingRules{
Precedence: chain,
MigrationRules: currentMigrationRules(),
Precedence: chain,
MigrationRules: currentMigrationRules(),
WarnIfAllMissing: warnIfAllMissing,
}
}
@@ -172,6 +177,7 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
}
errlist := []error{}
missingList := []string{}
kubeConfigFiles := []string{}
@@ -195,23 +201,31 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
}
config, err := LoadFromFile(filename)
if os.IsNotExist(err) {
// skip missing files
// Add to the missing list to produce a warning
missingList = append(missingList, filename)
continue
}
if err != nil {
errlist = append(errlist, fmt.Errorf("Error loading config file \"%s\": %v", filename, err))
errlist = append(errlist, fmt.Errorf("error loading config file \"%s\": %v", filename, err))
continue
}
kubeconfigs = append(kubeconfigs, config)
}
if rules.WarnIfAllMissing && len(missingList) > 0 && len(kubeconfigs) == 0 {
klog.Warningf("Config not found: %s", strings.Join(missingList, ", "))
}
// first merge all of our maps
mapConfig := clientcmdapi.NewConfig()
for _, kubeconfig := range kubeconfigs {
mergo.MergeWithOverwrite(mapConfig, kubeconfig)
mergo.Merge(mapConfig, kubeconfig, mergo.WithOverride)
}
// merge all of the struct values in the reverse order so that priority is given correctly
@@ -219,14 +233,14 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
nonMapConfig := clientcmdapi.NewConfig()
for i := len(kubeconfigs) - 1; i >= 0; i-- {
kubeconfig := kubeconfigs[i]
mergo.MergeWithOverwrite(nonMapConfig, kubeconfig)
mergo.Merge(nonMapConfig, kubeconfig, mergo.WithOverride)
}
// since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and
// get the values we expect.
config := clientcmdapi.NewConfig()
mergo.MergeWithOverwrite(config, mapConfig)
mergo.MergeWithOverwrite(config, nonMapConfig)
mergo.Merge(config, mapConfig, mergo.WithOverride)
mergo.Merge(config, nonMapConfig, mergo.WithOverride)
if rules.ResolvePaths() {
if err := ResolveLocalPaths(config); err != nil {
@@ -267,20 +281,15 @@ func (rules *ClientConfigLoadingRules) Migrate() error {
return fmt.Errorf("cannot migrate %v to %v because it is a directory", source, destination)
}
in, err := os.Open(source)
data, err := ioutil.ReadFile(source)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(destination)
// destination is created with mode 0666 before umask
err = ioutil.WriteFile(destination, data, 0666)
if err != nil {
return err
}
defer out.Close()
if _, err = io.Copy(out, in); err != nil {
return err
}
}
return nil
@@ -288,6 +297,10 @@ func (rules *ClientConfigLoadingRules) Migrate() error {
// GetLoadingPrecedence implements ConfigAccess
func (rules *ClientConfigLoadingRules) GetLoadingPrecedence() []string {
if len(rules.ExplicitPath) > 0 {
return []string{rules.ExplicitPath}
}
return rules.Precedence
}
@@ -356,7 +369,7 @@ func LoadFromFile(filename string) (*clientcmdapi.Config, error) {
if err != nil {
return nil, err
}
klog.V(6).Infoln("Config loaded from file", filename)
klog.V(6).Infoln("Config loaded from file: ", filename)
// set LocationOfOrigin on every Cluster, User, and Context
for key, obj := range config.AuthInfos {
@@ -467,7 +480,7 @@ func ResolveLocalPaths(config *clientcmdapi.Config) error {
}
base, err := filepath.Abs(filepath.Dir(cluster.LocationOfOrigin))
if err != nil {
return fmt.Errorf("Could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err)
return fmt.Errorf("could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err)
}
if err := ResolvePaths(GetClusterFileReferences(cluster), base); err != nil {
@@ -480,7 +493,7 @@ func ResolveLocalPaths(config *clientcmdapi.Config) error {
}
base, err := filepath.Abs(filepath.Dir(authInfo.LocationOfOrigin))
if err != nil {
return fmt.Errorf("Could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err)
return fmt.Errorf("could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err)
}
if err := ResolvePaths(GetAuthInfoFileReferences(authInfo), base); err != nil {

View File

@@ -20,7 +20,7 @@ import (
"io"
"sync"
"k8s.io/klog"
"k8s.io/klog/v2"
restclient "k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
@@ -60,27 +60,26 @@ func NewInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overri
}
func (config *DeferredLoadingClientConfig) createClientConfig() (ClientConfig, error) {
if config.clientConfig == nil {
config.loadingLock.Lock()
defer config.loadingLock.Unlock()
config.loadingLock.Lock()
defer config.loadingLock.Unlock()
if config.clientConfig == nil {
mergedConfig, err := config.loader.Load()
if err != nil {
return nil, err
}
var mergedClientConfig ClientConfig
if config.fallbackReader != nil {
mergedClientConfig = NewInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.fallbackReader, config.loader)
} else {
mergedClientConfig = NewNonInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.loader)
}
config.clientConfig = mergedClientConfig
}
if config.clientConfig != nil {
return config.clientConfig, nil
}
mergedConfig, err := config.loader.Load()
if err != nil {
return nil, err
}
var currentContext string
if config.overrides != nil {
currentContext = config.overrides.CurrentContext
}
if config.fallbackReader != nil {
config.clientConfig = NewInteractiveClientConfig(*mergedConfig, currentContext, config.overrides, config.fallbackReader, config.loader)
} else {
config.clientConfig = NewNonInteractiveClientConfig(*mergedConfig, currentContext, config.overrides, config.loader)
}
return config.clientConfig, nil
}

View File

@@ -71,6 +71,7 @@ type ClusterOverrideFlags struct {
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
@@ -145,6 +146,7 @@ const (
FlagContext = "context"
FlagNamespace = "namespace"
FlagAPIServer = "server"
FlagTLSServerName = "tls-server-name"
FlagInsecure = "insecure-skip-tls-verify"
FlagCertFile = "client-certificate"
FlagKeyFile = "client-key"
@@ -189,6 +191,7 @@ func RecommendedClusterOverrideFlags(prefix string) 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."},
}
}
@@ -226,6 +229,7 @@ func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, f
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

View File

@@ -30,11 +30,24 @@ import (
var (
ErrNoContext = errors.New("no context chosen")
ErrEmptyConfig = errors.New("no configuration has been provided")
ErrEmptyConfig = NewEmptyConfigError("no configuration has been provided, try setting KUBERNETES_MASTER environment variable")
// message is for consistency with old behavior
ErrEmptyCluster = errors.New("cluster has no server defined")
)
// NewEmptyConfigError returns an error wrapping the given message which IsEmptyConfig() will recognize as an empty config error
func NewEmptyConfigError(message string) error {
return &errEmptyConfig{message}
}
type errEmptyConfig struct {
message string
}
func (e *errEmptyConfig) Error() string {
return e.message
}
type errContextNotFound struct {
ContextName string
}
@@ -60,9 +73,14 @@ func IsContextNotFound(err error) bool {
func IsEmptyConfig(err error) bool {
switch t := err.(type) {
case errConfigurationInvalid:
return len(t) == 1 && t[0] == ErrEmptyConfig
if len(t) != 1 {
return false
}
_, ok := t[0].(*errEmptyConfig)
return ok
}
return err == ErrEmptyConfig
_, ok := err.(*errEmptyConfig)
return ok
}
// errConfigurationInvalid is a set of errors indicating the configuration is invalid.
@@ -86,11 +104,41 @@ func (e errConfigurationInvalid) Error() string {
return fmt.Sprintf("invalid configuration: %v", utilerrors.NewAggregate(e).Error())
}
// Errors implements the AggregateError interface
// Errors implements the utilerrors.Aggregate interface
func (e errConfigurationInvalid) Errors() []error {
return e
}
// Is implements the utilerrors.Aggregate interface
func (e errConfigurationInvalid) Is(target error) bool {
return e.visit(func(err error) bool {
return errors.Is(err, target)
})
}
func (e errConfigurationInvalid) visit(f func(err error) bool) bool {
for _, err := range e {
switch err := err.(type) {
case errConfigurationInvalid:
if match := err.visit(f); match {
return match
}
case utilerrors.Aggregate:
for _, nestedErr := range err.Errors() {
if match := f(nestedErr); match {
return match
}
}
default:
if match := f(err); match {
return match
}
}
}
return false
}
// IsConfigurationInvalid returns true if the provided error indicates the configuration is invalid.
func IsConfigurationInvalid(err error) bool {
switch err.(type) {
@@ -179,15 +227,21 @@ func validateClusterInfo(clusterName string, clusterInfo clientcmdapi.Cluster) [
validationErrors = append(validationErrors, fmt.Errorf("no server found for cluster %q", clusterName))
}
}
if proxyURL := clusterInfo.ProxyURL; proxyURL != "" {
if _, err := parseProxyURL(proxyURL); err != nil {
validationErrors = append(validationErrors, fmt.Errorf("invalid 'proxy-url' %q for cluster %q: %v", proxyURL, clusterName, err))
}
}
// Make sure CA data and CA file aren't both specified
if len(clusterInfo.CertificateAuthority) != 0 && len(clusterInfo.CertificateAuthorityData) != 0 {
validationErrors = append(validationErrors, fmt.Errorf("certificate-authority-data and certificate-authority are both specified for %v. certificate-authority-data will override.", clusterName))
}
if len(clusterInfo.CertificateAuthority) != 0 {
clientCertCA, err := os.Open(clusterInfo.CertificateAuthority)
defer clientCertCA.Close()
if err != nil {
validationErrors = append(validationErrors, fmt.Errorf("unable to read certificate-authority %v for %v due to %v", clusterInfo.CertificateAuthority, clusterName, err))
} else {
defer clientCertCA.Close()
}
}
@@ -223,16 +277,18 @@ func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []err
if len(authInfo.ClientCertificate) != 0 {
clientCertFile, err := os.Open(authInfo.ClientCertificate)
defer clientCertFile.Close()
if err != nil {
validationErrors = append(validationErrors, fmt.Errorf("unable to read client-cert %v for %v due to %v", authInfo.ClientCertificate, authInfoName, err))
} else {
defer clientCertFile.Close()
}
}
if len(authInfo.ClientKey) != 0 {
clientKeyFile, err := os.Open(authInfo.ClientKey)
defer clientKeyFile.Close()
if err != nil {
validationErrors = append(validationErrors, fmt.Errorf("unable to read client-key %v for %v due to %v", authInfo.ClientKey, authInfoName, err))
} else {
defer clientKeyFile.Close()
}
}
}
@@ -250,8 +306,6 @@ func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []err
for _, v := range authInfo.Exec.Env {
if len(v.Name) == 0 {
validationErrors = append(validationErrors, fmt.Errorf("env variable name must be specified for %v to use exec authentication plugin", authInfoName))
} else if len(v.Value) == 0 {
validationErrors = append(validationErrors, fmt.Errorf("env variable %s value must be specified for %v to use exec authentication plugin", v.Name, authInfoName))
}
}
}