func BuildConfigFromFlags(masterUrl, kubeconfigPath string) (*rest.Config, error) {
	if kubeconfigPath == "" && masterUrl == "" {
		glog.Warningf("Neither --kubeconfig nor --master was specified.  Using the inClusterConfig.  This might not work.")
		kubeconfig, err := rest.InClusterConfig()
		if err == nil {
			return kubeconfig, nil
		}
		glog.Warning("error creating inClusterConfig, falling back to default config: ", err)
	}
	return NewNonInteractiveDeferredLoadingClientConfig(
		&ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
		&ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterUrl}}).ClientConfig()
}
BuildConfigFromFlags is a helper function that builds configs from a master
url or a kubeconfig filepath. These are passed in as command line flags for cluster
components. Warnings should reflect this usage. If neither masterUrl or kubeconfigPath
are passed in we fallback to inClusterConfig. If inClusterConfig fails, we fallback
to the default config.
package clientcmd
import (
	"fmt"
	"io"
	"io/ioutil"
	"net/url"
	"os"
	"strings"
	"github.com/golang/glog"
	"github.com/imdario/mergo"
	"k8s.io/client-go/1.4/pkg/api"
	"k8s.io/client-go/1.4/rest"
	clientauth "k8s.io/client-go/1.4/tools/auth"
	clientcmdapi "k8s.io/client-go/1.4/tools/clientcmd/api"
)
var (
	DefaultCluster = clientcmdapi.Cluster{Server: "http://localhost:8080"}
	EnvVarCluster = clientcmdapi.Cluster{Server: os.Getenv("KUBERNETES_MASTER")}
	DefaultClientConfig = DirectClientConfig{*clientcmdapi.NewConfig(), "", &ConfigOverrides{}, nil, NewDefaultClientConfigLoadingRules()}
)
type ClientConfig interface {
	RawConfig() (clientcmdapi.Config, error)
	ClientConfig() (*rest.Config, error)
	Namespace() (string, bool, error)
	ConfigAccess() ConfigAccess
}
type PersistAuthProviderConfigForUser func(user string) rest.AuthProviderConfigPersister
type DirectClientConfig struct {
	config         clientcmdapi.Config
	contextName    string
	overrides      *ConfigOverrides
	fallbackReader io.Reader
	configAccess   ConfigAccess
}
func NewDefaultClientConfig(config clientcmdapi.Config, overrides *ConfigOverrides) ClientConfig {
	return &DirectClientConfig{config, config.CurrentContext, overrides, nil, NewDefaultClientConfigLoadingRules()}
}
func NewNonInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, configAccess ConfigAccess) ClientConfig {
	return &DirectClientConfig{config, contextName, overrides, nil, configAccess}
}
func NewInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, fallbackReader io.Reader, configAccess ConfigAccess) ClientConfig {
	return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess}
}
func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) {
	return config.config, nil
}
func (config *DirectClientConfig) ClientConfig() (*rest.Config, error) {
	if err := config.ConfirmUsable(); err != nil {
		return nil, err
	}
	configAuthInfo := config.getAuthInfo()
	configClusterInfo := config.getCluster()
	clientConfig := &rest.Config{}
	clientConfig.Host = configClusterInfo.Server
	if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 {
		u.RawQuery = ""
		u.Fragment = ""
		clientConfig.Host = u.String()
	}
	if len(configAuthInfo.Impersonate) > 0 {
		clientConfig.Impersonate = configAuthInfo.Impersonate
	}
	if rest.IsConfigTransportTLS(*clientConfig) {
		var err error
		var persister rest.AuthProviderConfigPersister
		if config.configAccess != nil {
			persister = PersisterForUser(config.configAccess, config.getAuthInfoName())
		}
		userAuthPartialConfig, err := getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister)
		if err != nil {
			return nil, err
		}
		mergo.Merge(clientConfig, userAuthPartialConfig)
		serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo)
		if err != nil {
			return nil, err
		}
		mergo.Merge(clientConfig, serverAuthPartialConfig)
	}
	return clientConfig, nil
}
func getServerIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, configClusterInfo clientcmdapi.Cluster) (*rest.Config, error) {
	mergedConfig := &rest.Config{}
	configClientConfig := &rest.Config{}
	configClientConfig.CAFile = configClusterInfo.CertificateAuthority
	configClientConfig.CAData = configClusterInfo.CertificateAuthorityData
	configClientConfig.Insecure = configClusterInfo.InsecureSkipTLSVerify
	mergo.Merge(mergedConfig, configClientConfig)
	return mergedConfig, nil
}
func getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig rest.AuthProviderConfigPersister) (*rest.Config, error) {
	mergedConfig := &rest.Config{}
	if len(configAuthInfo.Token) > 0 {
		mergedConfig.BearerToken = configAuthInfo.Token
	} else if len(configAuthInfo.TokenFile) > 0 {
		tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile)
		if err != nil {
			return nil, err
		}
		mergedConfig.BearerToken = string(tokenBytes)
	}
	if len(configAuthInfo.Impersonate) > 0 {
		mergedConfig.Impersonate = configAuthInfo.Impersonate
	}
	if len(configAuthInfo.ClientCertificate) > 0 || len(configAuthInfo.ClientCertificateData) > 0 {
		mergedConfig.CertFile = configAuthInfo.ClientCertificate
		mergedConfig.CertData = configAuthInfo.ClientCertificateData
		mergedConfig.KeyFile = configAuthInfo.ClientKey
		mergedConfig.KeyData = configAuthInfo.ClientKeyData
	}
	if len(configAuthInfo.Username) > 0 || len(configAuthInfo.Password) > 0 {
		mergedConfig.Username = configAuthInfo.Username
		mergedConfig.Password = configAuthInfo.Password
	}
	if configAuthInfo.AuthProvider != nil {
		mergedConfig.AuthProvider = configAuthInfo.AuthProvider
		mergedConfig.AuthConfigPersister = persistAuthConfig
	}
	if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) {
		prompter := NewPromptingAuthLoader(fallbackReader)
		promptedAuthInfo := prompter.Prompt()
		promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo)
		previouslyMergedConfig := mergedConfig
		mergedConfig = &rest.Config{}
		mergo.Merge(mergedConfig, promptedConfig)
		mergo.Merge(mergedConfig, previouslyMergedConfig)
	}
	return mergedConfig, nil
}
func makeUserIdentificationConfig(info clientauth.Info) *rest.Config {
	config := &rest.Config{}
	config.Username = info.User
	config.Password = info.Password
	config.CertFile = info.CertFile
	config.KeyFile = info.KeyFile
	config.BearerToken = info.BearerToken
	return config
}
func makeServerIdentificationConfig(info clientauth.Info) rest.Config {
	config := rest.Config{}
	config.CAFile = info.CAFile
	if info.Insecure != nil {
		config.Insecure = *info.Insecure
	}
	return config
}
func canIdentifyUser(config rest.Config) bool {
	return len(config.Username) > 0 ||
		(len(config.CertFile) > 0 || len(config.CertData) > 0) ||
		len(config.BearerToken) > 0 ||
		config.AuthProvider != nil
}
func (config *DirectClientConfig) Namespace() (string, bool, error) {
	if err := config.ConfirmUsable(); err != nil {
		return "", false, err
	}
	configContext := config.getContext()
	if len(configContext.Namespace) == 0 {
		return api.NamespaceDefault, false, nil
	}
	overridden := false
	if config.overrides != nil && config.overrides.Context.Namespace != "" {
		overridden = true
	}
	return configContext.Namespace, overridden, nil
}
func (config *DirectClientConfig) ConfigAccess() ConfigAccess {
	return config.configAccess
}
func (config *DirectClientConfig) ConfirmUsable() error {
	validationErrors := make([]error, 0)
	validationErrors = append(validationErrors, validateAuthInfo(config.getAuthInfoName(), config.getAuthInfo())...)
	validationErrors = append(validationErrors, validateClusterInfo(config.getClusterName(), config.getCluster())...)
	if len(validationErrors) == 1 && validationErrors[0] == ErrEmptyCluster {
		return newErrConfigurationInvalid([]error{ErrEmptyConfig})
	}
	return newErrConfigurationInvalid(validationErrors)
}
func (config *DirectClientConfig) getContextName() string {
	if len(config.overrides.CurrentContext) != 0 {
		return config.overrides.CurrentContext
	}
	if len(config.contextName) != 0 {
		return config.contextName
	}
	return config.config.CurrentContext
}
func (config *DirectClientConfig) getAuthInfoName() string {
	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.Context.Cluster) != 0 {
		return config.overrides.Context.Cluster
	}
	return config.getContext().Cluster
}
func (config *DirectClientConfig) getContext() clientcmdapi.Context {
	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 {
	authInfos := config.config.AuthInfos
	authInfoName := config.getAuthInfoName()
	var mergedAuthInfo clientcmdapi.AuthInfo
	if configAuthInfo, exists := authInfos[authInfoName]; exists {
		mergo.Merge(&mergedAuthInfo, configAuthInfo)
	}
	mergo.Merge(&mergedAuthInfo, config.overrides.AuthInfo)
	return mergedAuthInfo
}
func (config *DirectClientConfig) getCluster() clientcmdapi.Cluster {
	clusterInfos := config.config.Clusters
	clusterInfoName := config.getClusterName()
	var mergedClusterInfo clientcmdapi.Cluster
	mergo.Merge(&mergedClusterInfo, config.overrides.ClusterDefaults)
	mergo.Merge(&mergedClusterInfo, EnvVarCluster)
	if configClusterInfo, exists := clusterInfos[clusterInfoName]; exists {
		mergo.Merge(&mergedClusterInfo, configClusterInfo)
	}
	mergo.Merge(&mergedClusterInfo, config.overrides.ClusterInfo)
	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
	}
	return mergedClusterInfo
}
type inClusterClientConfig struct{}
func (inClusterClientConfig) RawConfig() (clientcmdapi.Config, error) {
	return clientcmdapi.Config{}, fmt.Errorf("inCluster environment config doesn't support multiple clusters")
}
func (inClusterClientConfig) ClientConfig() (*rest.Config, error) {
	return rest.InClusterConfig()
}
func (inClusterClientConfig) Namespace() (string, error) {
	if ns := os.Getenv("POD_NAMESPACE"); ns != "" {
		return ns, nil
	}
	if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
		if ns := strings.TrimSpace(string(data)); len(ns) > 0 {
			return ns, nil
		}
	}
	return "default", nil
}
func (inClusterClientConfig) ConfigAccess() ConfigAccess {
	return NewDefaultClientConfigLoadingRules()
}
func (inClusterClientConfig) Possible() bool {
	fi, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/token")
	return os.Getenv("KUBERNETES_SERVICE_HOST") != "" &&
		os.Getenv("KUBERNETES_SERVICE_PORT") != "" &&
		err == nil && !fi.IsDir()
}