2 Copyright 2014 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
24 "github.com/golang/glog"
26 "k8s.io/kubernetes/pkg/client/restclient"
27 clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
30 // DeferredLoadingClientConfig is a ClientConfig interface that is backed by a client config loader.
31 // It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that
32 // the most recent rules are used. This is useful in cases where you bind flags to loading rule parameters before
33 // the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid
34 // passing extraneous information down a call stack
35 type DeferredLoadingClientConfig struct {
36 loader ClientConfigLoader
37 overrides *ConfigOverrides
38 fallbackReader io.Reader
40 clientConfig ClientConfig
41 loadingLock sync.Mutex
44 // NewNonInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name
45 func NewNonInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides) ClientConfig {
46 return &DeferredLoadingClientConfig{loader: loader, overrides: overrides}
49 // NewInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name and the fallback auth reader
50 func NewInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides, fallbackReader io.Reader) ClientConfig {
51 return &DeferredLoadingClientConfig{loader: loader, overrides: overrides, fallbackReader: fallbackReader}
54 func (config *DeferredLoadingClientConfig) createClientConfig() (ClientConfig, error) {
55 if config.clientConfig == nil {
56 config.loadingLock.Lock()
57 defer config.loadingLock.Unlock()
59 if config.clientConfig == nil {
60 mergedConfig, err := config.loader.Load()
65 var mergedClientConfig ClientConfig
66 if config.fallbackReader != nil {
67 mergedClientConfig = NewInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.fallbackReader, config.loader)
69 mergedClientConfig = NewNonInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.loader)
72 config.clientConfig = mergedClientConfig
76 return config.clientConfig, nil
79 func (config *DeferredLoadingClientConfig) RawConfig() (clientcmdapi.Config, error) {
80 mergedConfig, err := config.createClientConfig()
82 return clientcmdapi.Config{}, err
85 return mergedConfig.RawConfig()
88 // ClientConfig implements ClientConfig
89 func (config *DeferredLoadingClientConfig) ClientConfig() (*restclient.Config, error) {
90 mergedClientConfig, err := config.createClientConfig()
95 mergedConfig, err := mergedClientConfig.ClientConfig()
99 // Are we running in a cluster and were no other configs found? If so, use the in-cluster-config.
100 icc := inClusterClientConfig{}
101 defaultConfig, err := DefaultClientConfig.ClientConfig()
102 if icc.Possible() && err == nil && reflect.DeepEqual(mergedConfig, defaultConfig) {
103 glog.V(2).Info("No kubeconfig could be created, falling back to service account.")
104 return icc.ClientConfig()
106 return mergedConfig, nil
109 // Namespace implements KubeConfig
110 func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) {
111 mergedKubeConfig, err := config.createClientConfig()
113 return "", false, err
116 return mergedKubeConfig.Namespace()
119 // ConfigAccess implements ClientConfig
120 func (config *DeferredLoadingClientConfig) ConfigAccess() ConfigAccess {