make kubectl config behave more expectedly

This commit is contained in:
deads2k
2015-04-08 10:32:32 -04:00
parent 2215a64567
commit b2e3f2185e
30 changed files with 688 additions and 305 deletions

View File

@@ -49,6 +49,8 @@ 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.
LocationOfOrigin string
// Server is the address of the kubernetes cluster (https://hostname:port).
Server string `json:"server"`
// APIVersion is the preferred api version for communicating with the kubernetes cluster (v1beta1, v1beta2, v1beta3, etc).
@@ -65,6 +67,8 @@ 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.
LocationOfOrigin string
// AuthPath is the path to a kubernetes auth file (~/.kubernetes_auth). If you provide an AuthPath, the other options specified are ignored
AuthPath string `json:"auth-path,omitempty"`
// ClientCertificate is the path to a client cert file for TLS.
@@ -87,6 +91,8 @@ 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.
LocationOfOrigin string
// Cluster is the name of the cluster for this context
Cluster string `json:"cluster"`
// AuthInfo is the name of the authInfo for this context

View File

@@ -88,22 +88,27 @@ func ExampleOfOptionsConfig() {
// Output:
// clusters:
// alfa:
// LocationOfOrigin: ""
// api-version: v1beta2
// certificate-authority: path/to/my/cert-ca-filename
// insecure-skip-tls-verify: true
// server: https://alfa.org:8080
// bravo:
// LocationOfOrigin: ""
// api-version: v1beta1
// server: https://bravo.org:8080
// contexts:
// alfa-as-black-mage:
// LocationOfOrigin: ""
// cluster: alfa
// namespace: zulu
// user: black-mage-via-file
// alfa-as-white-mage:
// LocationOfOrigin: ""
// cluster: alfa
// user: white-mage-via-cert
// bravo-as-black-mage:
// LocationOfOrigin: ""
// cluster: bravo
// namespace: yankee
// user: black-mage-via-file
@@ -112,10 +117,13 @@ func ExampleOfOptionsConfig() {
// colors: true
// users:
// black-mage-via-file:
// LocationOfOrigin: ""
// auth-path: path/to/my/.kubernetes_auth
// red-mage-via-token:
// LocationOfOrigin: ""
// token: my-secret-token
// white-mage-via-cert:
// LocationOfOrigin: ""
// client-certificate: path/to/my/client-cert-filename
// client-key: path/to/my/client-key-filename
}

View File

@@ -26,6 +26,31 @@ import (
func init() {
err := newer.Scheme.AddConversionFuncs(
func(in *Cluster, out *newer.Cluster, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *newer.Cluster, out *Cluster, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Preferences, out *newer.Preferences, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *newer.Preferences, out *Preferences, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *AuthInfo, out *newer.AuthInfo, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *newer.AuthInfo, out *AuthInfo, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Context, out *newer.Context, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *newer.Context, out *Context, s conversion.Scope) error {
return s.DefaultConvert(in, out, conversion.IgnoreMissingFields)
},
func(in *Config, out *newer.Config, s conversion.Scope) error {
out.CurrentContext = in.CurrentContext
if err := s.Convert(&in.Preferences, &out.Preferences, 0); err != nil {

View File

@@ -48,6 +48,10 @@ const (
type ClientConfigLoadingRules struct {
ExplicitPath string
Precedence []string
// DoNotResolvePaths indicates whether or not to resolve paths with respect to the originating files. This is phrased as a negative so
// that a default object that doesn't set this will usually get the behavior it wants.
DoNotResolvePaths bool
}
// NewDefaultClientConfigLoadingRules returns a ClientConfigLoadingRules object with default fields filled in. You are not required to
@@ -71,7 +75,6 @@ func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder
// and only absolute file paths are returned.
func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
errlist := []error{}
// Make sure a file we were explicitly told to use exists
@@ -90,8 +93,10 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
if err := mergeConfigWithFile(mapConfig, file); err != nil {
errlist = append(errlist, err)
}
if err := ResolveLocalPaths(file, mapConfig); err != nil {
errlist = append(errlist, err)
if rules.ResolvePaths() {
if err := ResolveLocalPaths(file, mapConfig); err != nil {
errlist = append(errlist, err)
}
}
}
@@ -101,7 +106,9 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
for i := len(kubeConfigFiles) - 1; i >= 0; i-- {
file := kubeConfigFiles[i]
mergeConfigWithFile(nonMapConfig, file)
ResolveLocalPaths(file, nonMapConfig)
if rules.ResolvePaths() {
ResolveLocalPaths(file, nonMapConfig)
}
}
// since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and
@@ -182,7 +189,26 @@ func LoadFromFile(filename string) (*clientcmdapi.Config, error) {
if err != nil {
return nil, err
}
return Load(kubeconfigBytes)
config, err := Load(kubeconfigBytes)
if err != nil {
return nil, err
}
// set LocationOfOrigin on every Cluster, User, and Context
for key, obj := range config.AuthInfos {
obj.LocationOfOrigin = filename
config.AuthInfos[key] = obj
}
for key, obj := range config.Clusters {
obj.LocationOfOrigin = filename
config.Clusters[key] = obj
}
for key, obj := range config.Contexts {
obj.LocationOfOrigin = filename
config.Contexts[key] = obj
}
return config, nil
}
// Load takes a byte slice and deserializes the contents into Config object.
@@ -226,3 +252,7 @@ func Write(config clientcmdapi.Config) ([]byte, error) {
}
return content, nil
}
func (rules ClientConfigLoadingRules) ResolvePaths() bool {
return !rules.DoNotResolvePaths
}