add namespace to kubeconfig file

This commit is contained in:
deads2k
2015-01-02 13:08:37 -05:00
parent 6ff26d924c
commit dd01137138
24 changed files with 300 additions and 177 deletions

View File

@@ -83,6 +83,8 @@ type Context struct {
AuthInfo string `json:"user"`
// Namespace is the default namespace to use on unspecified requests
Namespace string `json:"namespace,omitempty"`
// NamespacePath is the path to a kubernetes ns file (~/.kubernetes_ns)
NamespacePath string `json:"namespace-path,omitempty"`
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
Extensions map[string]runtime.EmbeddedObject `json:"extensions,omitempty"`
}

View File

@@ -83,6 +83,8 @@ type Context struct {
AuthInfo string `json:"user"`
// Namespace is the default namespace to use on unspecified requests
Namespace string `json:"namespace,omitempty"`
// NamespacePath is the path to a kubernetes ns file (~/.kubernetes_ns)
NamespacePath string `json:"namespace-path,omitempty"`
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
Extensions []NamedExtension `json:"extensions,omitempty"`
}

View File

@@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/clientauth"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
)
@@ -36,9 +37,12 @@ var (
// ClientConfig is used to make it easy to get an api server client
type ClientConfig interface {
// RawConfig returns the merged result of all overrides
RawConfig() (clientcmdapi.Config, error)
// ClientConfig returns a complete client config
ClientConfig() (*client.Config, error)
// Namespace returns the namespace resulting from the merged result of all overrides
Namespace() (string, error)
}
// DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information
@@ -226,6 +230,35 @@ func canIdentifyUser(config client.Config) bool {
}
// Namespace implements KubeConfig
func (config DirectClientConfig) Namespace() (string, error) {
if err := config.ConfirmUsable(); err != nil {
return "", err
}
configContext := config.getContext()
if len(configContext.Namespace) != 0 {
return configContext.Namespace, nil
}
if len(configContext.NamespacePath) != 0 {
nsInfo, err := kubectl.LoadNamespaceInfo(configContext.NamespacePath)
if err != nil {
return "", err
}
return nsInfo.Namespace, nil
}
// if nothing was specified, try the default file
nsInfo, err := kubectl.LoadNamespaceInfo(os.Getenv("HOME") + "/.kubernetes_ns")
if err != nil {
return "", err
}
return nsInfo.Namespace, nil
}
// ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config,
// but no errors in the sections requested or referenced. It does not return early so that it can find as many errors as possible.
func (config DirectClientConfig) ConfirmUsable() error {
@@ -248,21 +281,30 @@ func (config DirectClientConfig) getContextName() string {
}
func (config DirectClientConfig) getAuthInfoName() string {
if len(config.overrides.AuthInfoName) != 0 {
return config.overrides.AuthInfoName
if len(config.overrides.Context.AuthInfo) != 0 {
return config.overrides.Context.AuthInfo
}
return config.getContext().AuthInfo
}
func (config DirectClientConfig) getClusterName() string {
if len(config.overrides.ClusterName) != 0 {
return config.overrides.ClusterName
if len(config.overrides.Context.Cluster) != 0 {
return config.overrides.Context.Cluster
}
return config.getContext().Cluster
}
func (config DirectClientConfig) getContext() clientcmdapi.Context {
return config.config.Contexts[config.getContextName()]
contexts := config.config.Contexts
contextName := config.getContextName()
var mergedContext clientcmdapi.Context
if configContext, exists := contexts[contextName]; exists {
mergo.Merge(&mergedContext, configContext)
}
mergo.Merge(&mergedContext, config.overrides.Context)
return mergedContext
}
func (config DirectClientConfig) getAuthInfo() clientcmdapi.AuthInfo {

View File

@@ -48,6 +48,24 @@ func createValidTestConfig() *clientcmdapi.Config {
return config
}
func TestMergeContext(t *testing.T) {
const namespace = "overriden-namespace"
config := createValidTestConfig()
clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
Context: clientcmdapi.Context{
Namespace: namespace,
},
})
actual, err := clientBuilder.Namespace()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
matchStringArg(namespace, actual, t)
}
func TestCreateClean(t *testing.T) {
config := createValidTestConfig()
clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{})

View File

@@ -78,3 +78,13 @@ func (config DeferredLoadingClientConfig) ClientConfig() (*client.Config, error)
return mergedClientConfig.ClientConfig()
}
// Namespace implements KubeConfig
func (config DeferredLoadingClientConfig) Namespace() (string, error) {
mergedKubeConfig, err := config.createClientConfig()
if err != nil {
return "", err
}
return mergedKubeConfig.Namespace()
}

View File

@@ -27,10 +27,8 @@ import (
type ConfigOverrides struct {
AuthInfo clientcmdapi.AuthInfo
ClusterInfo clientcmdapi.Cluster
Namespace string
Context clientcmdapi.Context
CurrentContext string
ClusterName string
AuthInfoName string
}
// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
@@ -38,10 +36,8 @@ type ConfigOverrides struct {
type ConfigOverrideFlags struct {
AuthOverrideFlags AuthOverrideFlags
ClusterOverrideFlags ClusterOverrideFlags
Namespace string
ContextOverrideFlags ContextOverrideFlags
CurrentContext string
ClusterName string
AuthInfoName string
}
// AuthOverrideFlags holds the flag names to be used for binding command line flags for AuthInfo objects
@@ -52,6 +48,14 @@ type AuthOverrideFlags struct {
Token string
}
// ContextOverrideFlags holds the flag names to be used for binding command line flags for Cluster objects
type ContextOverrideFlags struct {
ClusterName string
AuthInfoName string
Namespace string
NamespacePath string
}
// ClusterOverride holds the flag names to be used for binding command line flags for Cluster objects
type ClusterOverrideFlags struct {
APIServer string
@@ -61,18 +65,19 @@ type ClusterOverrideFlags struct {
}
const (
FlagClusterName = "cluster"
FlagAuthInfoName = "user"
FlagContext = "context"
FlagNamespace = "namespace"
FlagAPIServer = "server"
FlagAPIVersion = "api-version"
FlagAuthPath = "auth-path"
FlagInsecure = "insecure-skip-tls-verify"
FlagCertFile = "client-certificate"
FlagKeyFile = "client-key"
FlagCAFile = "certificate-authority"
FlagBearerToken = "token"
FlagClusterName = "cluster"
FlagAuthInfoName = "user"
FlagContext = "context"
FlagNamespace = "namespace"
FlagNamespacePath = "ns-path"
FlagAPIServer = "server"
FlagAPIVersion = "api-version"
FlagAuthPath = "auth-path"
FlagInsecure = "insecure-skip-tls-verify"
FlagCertFile = "client-certificate"
FlagKeyFile = "client-key"
FlagCAFile = "certificate-authority"
FlagBearerToken = "token"
)
// RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
@@ -100,10 +105,18 @@ func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
return ConfigOverrideFlags{
AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
Namespace: prefix + FlagNamespace,
ContextOverrideFlags: RecommendedContextOverrideFlags(prefix),
CurrentContext: prefix + FlagContext,
ClusterName: prefix + FlagClusterName,
AuthInfoName: prefix + FlagAuthInfoName,
}
}
// RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags {
return ContextOverrideFlags{
ClusterName: prefix + FlagClusterName,
AuthInfoName: prefix + FlagAuthInfoName,
Namespace: prefix + FlagNamespace,
NamespacePath: prefix + FlagNamespacePath,
}
}
@@ -129,9 +142,14 @@ func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, f
func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) {
BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags)
BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags)
// TODO not integrated yet
// flags.StringVar(&overrides.Namespace, flagNames.Namespace, "", "If present, the namespace scope for this CLI request.")
BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
flags.StringVar(&overrides.CurrentContext, flagNames.CurrentContext, "", "The name of the kubeconfig context to use")
flags.StringVar(&overrides.ClusterName, flagNames.ClusterName, "", "The name of the kubeconfig cluster to use")
flags.StringVar(&overrides.AuthInfoName, flagNames.AuthInfoName, "", "The name of the kubeconfig user to use")
}
// BindFlags is a convenience method to bind the specified flags to their associated variables
func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) {
flags.StringVar(&contextInfo.Cluster, flagNames.ClusterName, "", "The name of the kubeconfig cluster to use")
flags.StringVar(&contextInfo.AuthInfo, flagNames.AuthInfoName, "", "The name of the kubeconfig user to use")
flags.StringVar(&contextInfo.Namespace, flagNames.Namespace, "", "If present, the namespace scope for this CLI request.")
flags.StringVar(&contextInfo.NamespacePath, flagNames.NamespacePath, "", "Path to the namespace info file that holds the namespace context to use for CLI requests.")
}