Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / client-go / tools / clientcmd / merged_client_builder.go
1 /*
2 Copyright 2014 The Kubernetes Authors.
3
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
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
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.
15 */
16
17 package clientcmd
18
19 import (
20         "io"
21         "sync"
22
23         "k8s.io/klog"
24
25         restclient "k8s.io/client-go/rest"
26         clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
27 )
28
29 // DeferredLoadingClientConfig is a ClientConfig interface that is backed by a client config loader.
30 // It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that
31 // the most recent rules are used.  This is useful in cases where you bind flags to loading rule parameters before
32 // the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid
33 // passing extraneous information down a call stack
34 type DeferredLoadingClientConfig struct {
35         loader         ClientConfigLoader
36         overrides      *ConfigOverrides
37         fallbackReader io.Reader
38
39         clientConfig ClientConfig
40         loadingLock  sync.Mutex
41
42         // provided for testing
43         icc InClusterConfig
44 }
45
46 // InClusterConfig abstracts details of whether the client is running in a cluster for testing.
47 type InClusterConfig interface {
48         ClientConfig
49         Possible() bool
50 }
51
52 // NewNonInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name
53 func NewNonInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides) ClientConfig {
54         return &DeferredLoadingClientConfig{loader: loader, overrides: overrides, icc: &inClusterClientConfig{overrides: overrides}}
55 }
56
57 // NewInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name and the fallback auth reader
58 func NewInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides, fallbackReader io.Reader) ClientConfig {
59         return &DeferredLoadingClientConfig{loader: loader, overrides: overrides, icc: &inClusterClientConfig{overrides: overrides}, fallbackReader: fallbackReader}
60 }
61
62 func (config *DeferredLoadingClientConfig) createClientConfig() (ClientConfig, error) {
63         if config.clientConfig == nil {
64                 config.loadingLock.Lock()
65                 defer config.loadingLock.Unlock()
66
67                 if config.clientConfig == nil {
68                         mergedConfig, err := config.loader.Load()
69                         if err != nil {
70                                 return nil, err
71                         }
72
73                         var mergedClientConfig ClientConfig
74                         if config.fallbackReader != nil {
75                                 mergedClientConfig = NewInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.fallbackReader, config.loader)
76                         } else {
77                                 mergedClientConfig = NewNonInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.loader)
78                         }
79
80                         config.clientConfig = mergedClientConfig
81                 }
82         }
83
84         return config.clientConfig, nil
85 }
86
87 func (config *DeferredLoadingClientConfig) RawConfig() (clientcmdapi.Config, error) {
88         mergedConfig, err := config.createClientConfig()
89         if err != nil {
90                 return clientcmdapi.Config{}, err
91         }
92
93         return mergedConfig.RawConfig()
94 }
95
96 // ClientConfig implements ClientConfig
97 func (config *DeferredLoadingClientConfig) ClientConfig() (*restclient.Config, error) {
98         mergedClientConfig, err := config.createClientConfig()
99         if err != nil {
100                 return nil, err
101         }
102
103         // load the configuration and return on non-empty errors and if the
104         // content differs from the default config
105         mergedConfig, err := mergedClientConfig.ClientConfig()
106         switch {
107         case err != nil:
108                 if !IsEmptyConfig(err) {
109                         // return on any error except empty config
110                         return nil, err
111                 }
112         case mergedConfig != nil:
113                 // the configuration is valid, but if this is equal to the defaults we should try
114                 // in-cluster configuration
115                 if !config.loader.IsDefaultConfig(mergedConfig) {
116                         return mergedConfig, nil
117                 }
118         }
119
120         // check for in-cluster configuration and use it
121         if config.icc.Possible() {
122                 klog.V(4).Infof("Using in-cluster configuration")
123                 return config.icc.ClientConfig()
124         }
125
126         // return the result of the merged client config
127         return mergedConfig, err
128 }
129
130 // Namespace implements KubeConfig
131 func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) {
132         mergedKubeConfig, err := config.createClientConfig()
133         if err != nil {
134                 return "", false, err
135         }
136
137         ns, overridden, err := mergedKubeConfig.Namespace()
138         // if we get an error and it is not empty config, or if the merged config defined an explicit namespace, or
139         // if in-cluster config is not possible, return immediately
140         if (err != nil && !IsEmptyConfig(err)) || overridden || !config.icc.Possible() {
141                 // return on any error except empty config
142                 return ns, overridden, err
143         }
144
145         if len(ns) > 0 {
146                 // if we got a non-default namespace from the kubeconfig, use it
147                 if ns != "default" {
148                         return ns, false, nil
149                 }
150
151                 // if we got a default namespace, determine whether it was explicit or implicit
152                 if raw, err := mergedKubeConfig.RawConfig(); err == nil {
153                         if context := raw.Contexts[raw.CurrentContext]; context != nil && len(context.Namespace) > 0 {
154                                 return ns, false, nil
155                         }
156                 }
157         }
158
159         klog.V(4).Infof("Using in-cluster namespace")
160
161         // allow the namespace from the service account token directory to be used.
162         return config.icc.Namespace()
163 }
164
165 // ConfigAccess implements ClientConfig
166 func (config *DeferredLoadingClientConfig) ConfigAccess() ConfigAccess {
167         return config.loader
168 }