k8s.io/client-go@v0.31.1/tools/clientcmd/merged_client_builder_test.go (about) 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 "fmt" 21 "testing" 22 23 restclient "k8s.io/client-go/rest" 24 clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 25 ) 26 27 type testClientConfig struct { 28 rawconfig *clientcmdapi.Config 29 config *restclient.Config 30 namespace string 31 namespaceSpecified bool 32 err error 33 } 34 35 func (c *testClientConfig) RawConfig() (clientcmdapi.Config, error) { 36 if c.rawconfig == nil { 37 return clientcmdapi.Config{}, fmt.Errorf("unexpected call") 38 } 39 return *c.rawconfig, nil 40 } 41 func (c *testClientConfig) ClientConfig() (*restclient.Config, error) { 42 return c.config, c.err 43 } 44 func (c *testClientConfig) Namespace() (string, bool, error) { 45 return c.namespace, c.namespaceSpecified, c.err 46 } 47 func (c *testClientConfig) ConfigAccess() ConfigAccess { 48 return nil 49 } 50 51 type testICC struct { 52 testClientConfig 53 54 possible bool 55 called bool 56 } 57 58 func (icc *testICC) Possible() bool { 59 icc.called = true 60 return icc.possible 61 } 62 63 func TestInClusterConfig(t *testing.T) { 64 default1 := &DirectClientConfig{ 65 config: *createValidTestConfig(), 66 contextName: "clean", 67 overrides: &ConfigOverrides{}, 68 } 69 invalidDefaultConfig := clientcmdapi.NewConfig() 70 invalidDefaultConfig.Clusters["clean"] = &clientcmdapi.Cluster{ 71 Server: "http://localhost:8080", 72 } 73 invalidDefaultConfig.Contexts["other"] = &clientcmdapi.Context{ 74 Cluster: "clean", 75 } 76 invalidDefaultConfig.CurrentContext = "clean" 77 78 defaultInvalid := &DirectClientConfig{ 79 config: *invalidDefaultConfig, 80 overrides: &ConfigOverrides{}, 81 } 82 if _, err := defaultInvalid.ClientConfig(); err == nil || !IsConfigurationInvalid(err) { 83 t.Fatal(err) 84 } 85 config1, err := default1.ClientConfig() 86 if err != nil { 87 t.Fatal(err) 88 } 89 config2 := &restclient.Config{Host: "config2"} 90 err1 := fmt.Errorf("unique error") 91 92 testCases := map[string]struct { 93 clientConfig *testClientConfig 94 icc *testICC 95 defaultConfig *DirectClientConfig 96 97 checkedICC bool 98 result *restclient.Config 99 err error 100 }{ 101 "in-cluster checked on other error": { 102 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 103 icc: &testICC{}, 104 105 checkedICC: true, 106 result: nil, 107 err: ErrEmptyConfig, 108 }, 109 110 "in-cluster not checked on non-empty error": { 111 clientConfig: &testClientConfig{err: ErrEmptyCluster}, 112 icc: &testICC{}, 113 114 checkedICC: false, 115 result: nil, 116 err: ErrEmptyCluster, 117 }, 118 119 "in-cluster checked when config is default": { 120 defaultConfig: default1, 121 clientConfig: &testClientConfig{config: config1}, 122 icc: &testICC{}, 123 124 checkedICC: true, 125 result: config1, 126 err: nil, 127 }, 128 129 "in-cluster not checked when default config is invalid": { 130 defaultConfig: defaultInvalid, 131 clientConfig: &testClientConfig{config: config1}, 132 icc: &testICC{}, 133 134 checkedICC: false, 135 result: config1, 136 err: nil, 137 }, 138 139 "in-cluster not checked when config is not equal to default": { 140 defaultConfig: default1, 141 clientConfig: &testClientConfig{config: config2}, 142 icc: &testICC{}, 143 144 checkedICC: false, 145 result: config2, 146 err: nil, 147 }, 148 149 "in-cluster checked when config is not equal to default and error is empty": { 150 clientConfig: &testClientConfig{config: config2, err: ErrEmptyConfig}, 151 icc: &testICC{}, 152 153 checkedICC: true, 154 result: config2, 155 err: ErrEmptyConfig, 156 }, 157 158 "in-cluster error returned when config is empty": { 159 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 160 icc: &testICC{ 161 possible: true, 162 testClientConfig: testClientConfig{ 163 err: err1, 164 }, 165 }, 166 167 checkedICC: true, 168 result: nil, 169 err: err1, 170 }, 171 172 "in-cluster config returned when config is empty": { 173 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 174 icc: &testICC{ 175 possible: true, 176 testClientConfig: testClientConfig{ 177 config: config2, 178 }, 179 }, 180 181 checkedICC: true, 182 result: config2, 183 err: nil, 184 }, 185 186 "in-cluster not checked when standard default is invalid": { 187 defaultConfig: &DefaultClientConfig, 188 clientConfig: &testClientConfig{config: config2}, 189 icc: &testICC{}, 190 191 checkedICC: false, 192 result: config2, 193 err: nil, 194 }, 195 } 196 197 for name, test := range testCases { 198 c := &DeferredLoadingClientConfig{icc: test.icc} 199 c.loader = &ClientConfigLoadingRules{DefaultClientConfig: test.defaultConfig} 200 c.clientConfig = test.clientConfig 201 202 cfg, err := c.ClientConfig() 203 if test.icc.called != test.checkedICC { 204 t.Errorf("%s: unexpected in-cluster-config call %t", name, test.icc.called) 205 } 206 if err != test.err || cfg != test.result { 207 t.Errorf("%s: unexpected result: %v %#v", name, err, cfg) 208 } 209 } 210 } 211 212 func TestInClusterConfigNamespace(t *testing.T) { 213 err1 := fmt.Errorf("unique error") 214 215 testCases := map[string]struct { 216 clientConfig *testClientConfig 217 icc *testICC 218 overrides *ConfigOverrides 219 220 checkedICC bool 221 result string 222 overridden bool 223 err error 224 }{ 225 "in-cluster checked on empty error": { 226 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 227 icc: &testICC{}, 228 229 checkedICC: true, 230 err: ErrEmptyConfig, 231 }, 232 233 "in-cluster not checked on non-empty error": { 234 clientConfig: &testClientConfig{err: ErrEmptyCluster}, 235 icc: &testICC{}, 236 237 err: ErrEmptyCluster, 238 }, 239 240 "in-cluster checked when config is default": { 241 clientConfig: &testClientConfig{}, 242 icc: &testICC{}, 243 244 checkedICC: true, 245 }, 246 247 "in-cluster not checked when config is not equal to default": { 248 clientConfig: &testClientConfig{namespace: "test", namespaceSpecified: true}, 249 icc: &testICC{}, 250 251 result: "test", 252 overridden: true, 253 }, 254 255 "in-cluster checked when namespace is not specified, but is defaulted": { 256 clientConfig: &testClientConfig{namespace: "test", namespaceSpecified: false}, 257 icc: &testICC{}, 258 259 checkedICC: true, 260 result: "test", 261 overridden: false, 262 }, 263 264 "in-cluster error returned when config is empty": { 265 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 266 icc: &testICC{ 267 possible: true, 268 testClientConfig: testClientConfig{ 269 err: err1, 270 }, 271 }, 272 273 checkedICC: true, 274 err: err1, 275 }, 276 277 "in-cluster config returned when config is empty": { 278 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 279 icc: &testICC{ 280 possible: true, 281 testClientConfig: testClientConfig{ 282 namespace: "test", 283 namespaceSpecified: true, 284 }, 285 }, 286 287 checkedICC: true, 288 result: "test", 289 overridden: true, 290 }, 291 292 "in-cluster config returned when config is empty and namespace is defaulted but not explicitly set": { 293 clientConfig: &testClientConfig{err: ErrEmptyConfig}, 294 icc: &testICC{ 295 possible: true, 296 testClientConfig: testClientConfig{ 297 namespace: "test", 298 namespaceSpecified: false, 299 }, 300 }, 301 302 checkedICC: true, 303 result: "test", 304 overridden: false, 305 }, 306 307 "overridden context used to verify explicit namespace in config": { 308 clientConfig: &testClientConfig{ 309 namespace: "default", 310 namespaceSpecified: false, // a namespace that comes from a context is not considered overridden 311 rawconfig: &clientcmdapi.Config{Contexts: map[string]*clientcmdapi.Context{"overridden-context": {Namespace: "default"}}}, 312 }, 313 overrides: &ConfigOverrides{CurrentContext: "overridden-context"}, 314 icc: &testICC{ 315 possible: true, 316 testClientConfig: testClientConfig{ 317 namespace: "icc", 318 namespaceSpecified: false, // a namespace that comes from icc is not considered overridden 319 }, 320 }, 321 checkedICC: true, 322 result: "default", 323 overridden: false, // a namespace that comes from a context is not considered overridden 324 }, 325 } 326 327 for name, test := range testCases { 328 t.Run(name, func(t *testing.T) { 329 c := &DeferredLoadingClientConfig{icc: test.icc, overrides: test.overrides} 330 c.clientConfig = test.clientConfig 331 332 ns, overridden, err := c.Namespace() 333 if test.icc.called != test.checkedICC { 334 t.Errorf("%s: unexpected in-cluster-config call %t", name, test.icc.called) 335 } 336 if err != test.err || ns != test.result || overridden != test.overridden { 337 t.Errorf("%s: unexpected result: %v %s %t", name, err, ns, overridden) 338 } 339 }) 340 } 341 }