config_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package config
  14. import (
  15. "bytes"
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "path"
  20. "reflect"
  21. "strings"
  22. "testing"
  23. "k8s.io/kubernetes/pkg/api"
  24. "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
  25. clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
  26. "k8s.io/kubernetes/pkg/util/diff"
  27. )
  28. func newRedFederalCowHammerConfig() clientcmdapi.Config {
  29. return clientcmdapi.Config{
  30. AuthInfos: map[string]*clientcmdapi.AuthInfo{
  31. "red-user": {Token: "red-token"}},
  32. Clusters: map[string]*clientcmdapi.Cluster{
  33. "cow-cluster": {Server: "http://cow.org:8080"}},
  34. Contexts: map[string]*clientcmdapi.Context{
  35. "federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"}},
  36. CurrentContext: "federal-context",
  37. }
  38. }
  39. func Example_view() {
  40. expectedConfig := newRedFederalCowHammerConfig()
  41. test := configCommandTest{
  42. args: []string{"view"},
  43. startingConfig: newRedFederalCowHammerConfig(),
  44. expectedConfig: expectedConfig,
  45. }
  46. output := test.run(nil)
  47. fmt.Printf("%v", output)
  48. // Output:
  49. // apiVersion: v1
  50. // clusters:
  51. // - cluster:
  52. // server: http://cow.org:8080
  53. // name: cow-cluster
  54. // contexts:
  55. // - context:
  56. // cluster: cow-cluster
  57. // user: red-user
  58. // name: federal-context
  59. // current-context: federal-context
  60. // kind: Config
  61. // preferences: {}
  62. // users:
  63. // - name: red-user
  64. // user:
  65. // token: red-token
  66. }
  67. func TestCurrentContext(t *testing.T) {
  68. startingConfig := newRedFederalCowHammerConfig()
  69. test := configCommandTest{
  70. args: []string{"current-context"},
  71. startingConfig: startingConfig,
  72. expectedConfig: startingConfig,
  73. expectedOutputs: []string{startingConfig.CurrentContext},
  74. }
  75. test.run(t)
  76. }
  77. func TestSetCurrentContext(t *testing.T) {
  78. expectedConfig := newRedFederalCowHammerConfig()
  79. startingConfig := newRedFederalCowHammerConfig()
  80. newContextName := "the-new-context"
  81. startingConfig.Contexts[newContextName] = clientcmdapi.NewContext()
  82. expectedConfig.Contexts[newContextName] = clientcmdapi.NewContext()
  83. expectedConfig.CurrentContext = newContextName
  84. test := configCommandTest{
  85. args: []string{"use-context", "the-new-context"},
  86. startingConfig: startingConfig,
  87. expectedConfig: expectedConfig,
  88. }
  89. test.run(t)
  90. }
  91. func TestSetNonExistentContext(t *testing.T) {
  92. expectedConfig := newRedFederalCowHammerConfig()
  93. test := configCommandTest{
  94. args: []string{"use-context", "non-existent-config"},
  95. startingConfig: expectedConfig,
  96. expectedConfig: expectedConfig,
  97. expectedOutputs: []string{`no context exists with the name: "non-existent-config"`},
  98. }
  99. test.run(t)
  100. }
  101. func TestSetIntoExistingStruct(t *testing.T) {
  102. expectedConfig := newRedFederalCowHammerConfig()
  103. expectedConfig.AuthInfos["red-user"].Password = "new-path-value"
  104. test := configCommandTest{
  105. args: []string{"set", "users.red-user.password", "new-path-value"},
  106. startingConfig: newRedFederalCowHammerConfig(),
  107. expectedConfig: expectedConfig,
  108. }
  109. test.run(t)
  110. }
  111. func TestSetWithPathPrefixIntoExistingStruct(t *testing.T) {
  112. expectedConfig := newRedFederalCowHammerConfig()
  113. expectedConfig.Clusters["cow-cluster"].Server = "http://cow.org:8080/foo/baz"
  114. test := configCommandTest{
  115. args: []string{"set", "clusters.cow-cluster.server", "http://cow.org:8080/foo/baz"},
  116. startingConfig: newRedFederalCowHammerConfig(),
  117. expectedConfig: expectedConfig,
  118. }
  119. test.run(t)
  120. dc := clientcmd.NewDefaultClientConfig(expectedConfig, &clientcmd.ConfigOverrides{})
  121. dcc, err := dc.ClientConfig()
  122. if err != nil {
  123. t.Fatalf("unexpected error: %v", err)
  124. }
  125. expectedHost := "http://cow.org:8080/foo/baz"
  126. if expectedHost != dcc.Host {
  127. t.Fatalf("expected client.Config.Host = %q instead of %q", expectedHost, dcc.Host)
  128. }
  129. }
  130. func TestUnsetStruct(t *testing.T) {
  131. expectedConfig := newRedFederalCowHammerConfig()
  132. delete(expectedConfig.AuthInfos, "red-user")
  133. test := configCommandTest{
  134. args: []string{"unset", "users.red-user"},
  135. startingConfig: newRedFederalCowHammerConfig(),
  136. expectedConfig: expectedConfig,
  137. }
  138. test.run(t)
  139. }
  140. func TestUnsetField(t *testing.T) {
  141. expectedConfig := newRedFederalCowHammerConfig()
  142. expectedConfig.AuthInfos["red-user"] = clientcmdapi.NewAuthInfo()
  143. test := configCommandTest{
  144. args: []string{"unset", "users.red-user.token"},
  145. startingConfig: newRedFederalCowHammerConfig(),
  146. expectedConfig: expectedConfig,
  147. }
  148. test.run(t)
  149. }
  150. func TestSetIntoNewStruct(t *testing.T) {
  151. expectedConfig := newRedFederalCowHammerConfig()
  152. cluster := clientcmdapi.NewCluster()
  153. cluster.Server = "new-server-value"
  154. expectedConfig.Clusters["big-cluster"] = cluster
  155. test := configCommandTest{
  156. args: []string{"set", "clusters.big-cluster.server", "new-server-value"},
  157. startingConfig: newRedFederalCowHammerConfig(),
  158. expectedConfig: expectedConfig,
  159. }
  160. test.run(t)
  161. }
  162. func TestSetBoolean(t *testing.T) {
  163. expectedConfig := newRedFederalCowHammerConfig()
  164. cluster := clientcmdapi.NewCluster()
  165. cluster.InsecureSkipTLSVerify = true
  166. expectedConfig.Clusters["big-cluster"] = cluster
  167. test := configCommandTest{
  168. args: []string{"set", "clusters.big-cluster.insecure-skip-tls-verify", "true"},
  169. startingConfig: newRedFederalCowHammerConfig(),
  170. expectedConfig: expectedConfig,
  171. }
  172. test.run(t)
  173. }
  174. func TestSetIntoNewConfig(t *testing.T) {
  175. expectedConfig := *clientcmdapi.NewConfig()
  176. context := clientcmdapi.NewContext()
  177. context.AuthInfo = "fake-user"
  178. expectedConfig.Contexts["new-context"] = context
  179. test := configCommandTest{
  180. args: []string{"set", "contexts.new-context.user", "fake-user"},
  181. startingConfig: *clientcmdapi.NewConfig(),
  182. expectedConfig: expectedConfig,
  183. }
  184. test.run(t)
  185. }
  186. func TestNewEmptyAuth(t *testing.T) {
  187. expectedConfig := *clientcmdapi.NewConfig()
  188. expectedConfig.AuthInfos["the-user-name"] = clientcmdapi.NewAuthInfo()
  189. test := configCommandTest{
  190. args: []string{"set-credentials", "the-user-name"},
  191. startingConfig: *clientcmdapi.NewConfig(),
  192. expectedConfig: expectedConfig,
  193. }
  194. test.run(t)
  195. }
  196. func TestAdditionalAuth(t *testing.T) {
  197. expectedConfig := newRedFederalCowHammerConfig()
  198. authInfo := clientcmdapi.NewAuthInfo()
  199. authInfo.Token = "token"
  200. expectedConfig.AuthInfos["another-user"] = authInfo
  201. test := configCommandTest{
  202. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"},
  203. startingConfig: newRedFederalCowHammerConfig(),
  204. expectedConfig: expectedConfig,
  205. }
  206. test.run(t)
  207. }
  208. func TestEmbedClientCert(t *testing.T) {
  209. fakeCertFile, _ := ioutil.TempFile("", "")
  210. defer os.Remove(fakeCertFile.Name())
  211. fakeData := []byte("fake-data")
  212. ioutil.WriteFile(fakeCertFile.Name(), fakeData, 0600)
  213. expectedConfig := newRedFederalCowHammerConfig()
  214. authInfo := clientcmdapi.NewAuthInfo()
  215. authInfo.ClientCertificateData = fakeData
  216. expectedConfig.AuthInfos["another-user"] = authInfo
  217. test := configCommandTest{
  218. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"},
  219. startingConfig: newRedFederalCowHammerConfig(),
  220. expectedConfig: expectedConfig,
  221. }
  222. test.run(t)
  223. }
  224. func TestEmbedClientKey(t *testing.T) {
  225. fakeKeyFile, _ := ioutil.TempFile("", "")
  226. defer os.Remove(fakeKeyFile.Name())
  227. fakeData := []byte("fake-data")
  228. ioutil.WriteFile(fakeKeyFile.Name(), fakeData, 0600)
  229. expectedConfig := newRedFederalCowHammerConfig()
  230. authInfo := clientcmdapi.NewAuthInfo()
  231. authInfo.ClientKeyData = fakeData
  232. expectedConfig.AuthInfos["another-user"] = authInfo
  233. test := configCommandTest{
  234. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagKeyFile + "=" + fakeKeyFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"},
  235. startingConfig: newRedFederalCowHammerConfig(),
  236. expectedConfig: expectedConfig,
  237. }
  238. test.run(t)
  239. }
  240. func TestEmbedNoKeyOrCertDisallowed(t *testing.T) {
  241. expectedConfig := newRedFederalCowHammerConfig()
  242. test := configCommandTest{
  243. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagEmbedCerts + "=true"},
  244. startingConfig: newRedFederalCowHammerConfig(),
  245. expectedConfig: expectedConfig,
  246. expectedOutputs: []string{"--client-certificate", "--client-key", "embed"},
  247. }
  248. test.run(t)
  249. }
  250. func TestEmptyTokenAndCertAllowed(t *testing.T) {
  251. fakeCertFile, _ := ioutil.TempFile("", "cert-file")
  252. expectedConfig := newRedFederalCowHammerConfig()
  253. authInfo := clientcmdapi.NewAuthInfo()
  254. authInfo.ClientCertificate = path.Base(fakeCertFile.Name())
  255. expectedConfig.AuthInfos["another-user"] = authInfo
  256. test := configCommandTest{
  257. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagBearerToken + "="},
  258. startingConfig: newRedFederalCowHammerConfig(),
  259. expectedConfig: expectedConfig,
  260. }
  261. test.run(t)
  262. }
  263. func TestTokenAndCertAllowed(t *testing.T) {
  264. expectedConfig := newRedFederalCowHammerConfig()
  265. authInfo := clientcmdapi.NewAuthInfo()
  266. authInfo.Token = "token"
  267. authInfo.ClientCertificate = "/cert-file"
  268. expectedConfig.AuthInfos["another-user"] = authInfo
  269. test := configCommandTest{
  270. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert-file", "--" + clientcmd.FlagBearerToken + "=token"},
  271. startingConfig: newRedFederalCowHammerConfig(),
  272. expectedConfig: expectedConfig,
  273. }
  274. test.run(t)
  275. }
  276. func TestTokenAndBasicDisallowed(t *testing.T) {
  277. expectedConfig := newRedFederalCowHammerConfig()
  278. test := configCommandTest{
  279. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagBearerToken + "=token"},
  280. startingConfig: newRedFederalCowHammerConfig(),
  281. expectedConfig: expectedConfig,
  282. expectedOutputs: []string{"--token", "--username"},
  283. }
  284. test.run(t)
  285. }
  286. func TestBasicClearsToken(t *testing.T) {
  287. authInfoWithToken := clientcmdapi.NewAuthInfo()
  288. authInfoWithToken.Token = "token"
  289. authInfoWithBasic := clientcmdapi.NewAuthInfo()
  290. authInfoWithBasic.Username = "myuser"
  291. authInfoWithBasic.Password = "mypass"
  292. startingConfig := newRedFederalCowHammerConfig()
  293. startingConfig.AuthInfos["another-user"] = authInfoWithToken
  294. expectedConfig := newRedFederalCowHammerConfig()
  295. expectedConfig.AuthInfos["another-user"] = authInfoWithBasic
  296. test := configCommandTest{
  297. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagPassword + "=mypass"},
  298. startingConfig: startingConfig,
  299. expectedConfig: expectedConfig,
  300. }
  301. test.run(t)
  302. }
  303. func TestTokenClearsBasic(t *testing.T) {
  304. authInfoWithBasic := clientcmdapi.NewAuthInfo()
  305. authInfoWithBasic.Username = "myuser"
  306. authInfoWithBasic.Password = "mypass"
  307. authInfoWithToken := clientcmdapi.NewAuthInfo()
  308. authInfoWithToken.Token = "token"
  309. startingConfig := newRedFederalCowHammerConfig()
  310. startingConfig.AuthInfos["another-user"] = authInfoWithBasic
  311. expectedConfig := newRedFederalCowHammerConfig()
  312. expectedConfig.AuthInfos["another-user"] = authInfoWithToken
  313. test := configCommandTest{
  314. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"},
  315. startingConfig: startingConfig,
  316. expectedConfig: expectedConfig,
  317. }
  318. test.run(t)
  319. }
  320. func TestTokenLeavesCert(t *testing.T) {
  321. authInfoWithCerts := clientcmdapi.NewAuthInfo()
  322. authInfoWithCerts.ClientCertificate = "cert"
  323. authInfoWithCerts.ClientCertificateData = []byte("certdata")
  324. authInfoWithCerts.ClientKey = "key"
  325. authInfoWithCerts.ClientKeyData = []byte("keydata")
  326. authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo()
  327. authInfoWithTokenAndCerts.Token = "token"
  328. authInfoWithTokenAndCerts.ClientCertificate = "cert"
  329. authInfoWithTokenAndCerts.ClientCertificateData = []byte("certdata")
  330. authInfoWithTokenAndCerts.ClientKey = "key"
  331. authInfoWithTokenAndCerts.ClientKeyData = []byte("keydata")
  332. startingConfig := newRedFederalCowHammerConfig()
  333. startingConfig.AuthInfos["another-user"] = authInfoWithCerts
  334. expectedConfig := newRedFederalCowHammerConfig()
  335. expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts
  336. test := configCommandTest{
  337. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"},
  338. startingConfig: startingConfig,
  339. expectedConfig: expectedConfig,
  340. }
  341. test.run(t)
  342. }
  343. func TestCertLeavesToken(t *testing.T) {
  344. authInfoWithToken := clientcmdapi.NewAuthInfo()
  345. authInfoWithToken.Token = "token"
  346. authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo()
  347. authInfoWithTokenAndCerts.Token = "token"
  348. authInfoWithTokenAndCerts.ClientCertificate = "/cert"
  349. authInfoWithTokenAndCerts.ClientKey = "/key"
  350. startingConfig := newRedFederalCowHammerConfig()
  351. startingConfig.AuthInfos["another-user"] = authInfoWithToken
  352. expectedConfig := newRedFederalCowHammerConfig()
  353. expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts
  354. test := configCommandTest{
  355. args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert", "--" + clientcmd.FlagKeyFile + "=/key"},
  356. startingConfig: startingConfig,
  357. expectedConfig: expectedConfig,
  358. }
  359. test.run(t)
  360. }
  361. func TestSetBytesBad(t *testing.T) {
  362. startingConfig := newRedFederalCowHammerConfig()
  363. startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster()
  364. test := configCommandTest{
  365. args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata"},
  366. startingConfig: startingConfig,
  367. expectedConfig: startingConfig,
  368. }
  369. test.run(t)
  370. }
  371. func TestSetBytes(t *testing.T) {
  372. clusterInfoWithCAData := clientcmdapi.NewCluster()
  373. clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata")
  374. startingConfig := newRedFederalCowHammerConfig()
  375. startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster()
  376. expectedConfig := newRedFederalCowHammerConfig()
  377. expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData
  378. test := configCommandTest{
  379. args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata", "--set-raw-bytes"},
  380. startingConfig: startingConfig,
  381. expectedConfig: expectedConfig,
  382. }
  383. test.run(t)
  384. }
  385. func TestSetBase64Bytes(t *testing.T) {
  386. clusterInfoWithCAData := clientcmdapi.NewCluster()
  387. clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata")
  388. startingConfig := newRedFederalCowHammerConfig()
  389. startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster()
  390. expectedConfig := newRedFederalCowHammerConfig()
  391. expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData
  392. test := configCommandTest{
  393. args: []string{"set", "clusters.another-cluster.certificate-authority-data", "Y2FkYXRh"},
  394. startingConfig: startingConfig,
  395. expectedConfig: expectedConfig,
  396. }
  397. test.run(t)
  398. }
  399. func TestUnsetBytes(t *testing.T) {
  400. clusterInfoWithCAData := clientcmdapi.NewCluster()
  401. clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata")
  402. startingConfig := newRedFederalCowHammerConfig()
  403. startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData
  404. expectedConfig := newRedFederalCowHammerConfig()
  405. expectedConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster()
  406. test := configCommandTest{
  407. args: []string{"unset", "clusters.another-cluster.certificate-authority-data"},
  408. startingConfig: startingConfig,
  409. expectedConfig: expectedConfig,
  410. }
  411. test.run(t)
  412. }
  413. func TestCAClearsInsecure(t *testing.T) {
  414. fakeCAFile, _ := ioutil.TempFile("", "ca-file")
  415. clusterInfoWithInsecure := clientcmdapi.NewCluster()
  416. clusterInfoWithInsecure.InsecureSkipTLSVerify = true
  417. clusterInfoWithCA := clientcmdapi.NewCluster()
  418. clusterInfoWithCA.CertificateAuthority = path.Base(fakeCAFile.Name())
  419. startingConfig := newRedFederalCowHammerConfig()
  420. startingConfig.Clusters["another-cluster"] = clusterInfoWithInsecure
  421. expectedConfig := newRedFederalCowHammerConfig()
  422. expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA
  423. test := configCommandTest{
  424. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name()},
  425. startingConfig: startingConfig,
  426. expectedConfig: expectedConfig,
  427. }
  428. test.run(t)
  429. }
  430. func TestCAClearsCAData(t *testing.T) {
  431. clusterInfoWithCAData := clientcmdapi.NewCluster()
  432. clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata")
  433. clusterInfoWithCA := clientcmdapi.NewCluster()
  434. clusterInfoWithCA.CertificateAuthority = "/cafile"
  435. startingConfig := newRedFederalCowHammerConfig()
  436. startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData
  437. expectedConfig := newRedFederalCowHammerConfig()
  438. expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA
  439. test := configCommandTest{
  440. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=/cafile", "--" + clientcmd.FlagInsecure + "=false"},
  441. startingConfig: startingConfig,
  442. expectedConfig: expectedConfig,
  443. }
  444. test.run(t)
  445. }
  446. func TestInsecureClearsCA(t *testing.T) {
  447. clusterInfoWithInsecure := clientcmdapi.NewCluster()
  448. clusterInfoWithInsecure.InsecureSkipTLSVerify = true
  449. clusterInfoWithCA := clientcmdapi.NewCluster()
  450. clusterInfoWithCA.CertificateAuthority = "cafile"
  451. clusterInfoWithCA.CertificateAuthorityData = []byte("cadata")
  452. startingConfig := newRedFederalCowHammerConfig()
  453. startingConfig.Clusters["another-cluster"] = clusterInfoWithCA
  454. expectedConfig := newRedFederalCowHammerConfig()
  455. expectedConfig.Clusters["another-cluster"] = clusterInfoWithInsecure
  456. test := configCommandTest{
  457. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagInsecure + "=true"},
  458. startingConfig: startingConfig,
  459. expectedConfig: expectedConfig,
  460. }
  461. test.run(t)
  462. }
  463. func TestCADataClearsCA(t *testing.T) {
  464. fakeCAFile, _ := ioutil.TempFile("", "")
  465. defer os.Remove(fakeCAFile.Name())
  466. fakeData := []byte("cadata")
  467. ioutil.WriteFile(fakeCAFile.Name(), fakeData, 0600)
  468. clusterInfoWithCAData := clientcmdapi.NewCluster()
  469. clusterInfoWithCAData.CertificateAuthorityData = fakeData
  470. clusterInfoWithCA := clientcmdapi.NewCluster()
  471. clusterInfoWithCA.CertificateAuthority = "cafile"
  472. startingConfig := newRedFederalCowHammerConfig()
  473. startingConfig.Clusters["another-cluster"] = clusterInfoWithCA
  474. expectedConfig := newRedFederalCowHammerConfig()
  475. expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData
  476. test := configCommandTest{
  477. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"},
  478. startingConfig: startingConfig,
  479. expectedConfig: expectedConfig,
  480. }
  481. test.run(t)
  482. }
  483. func TestEmbedNoCADisallowed(t *testing.T) {
  484. expectedConfig := newRedFederalCowHammerConfig()
  485. test := configCommandTest{
  486. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagEmbedCerts + "=true"},
  487. startingConfig: newRedFederalCowHammerConfig(),
  488. expectedConfig: expectedConfig,
  489. expectedOutputs: []string{"--certificate-authority", "embed"},
  490. }
  491. test.run(t)
  492. }
  493. func TestCAAndInsecureDisallowed(t *testing.T) {
  494. test := configCommandTest{
  495. args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=cafile", "--" + clientcmd.FlagInsecure + "=true"},
  496. startingConfig: newRedFederalCowHammerConfig(),
  497. expectedConfig: newRedFederalCowHammerConfig(),
  498. expectedOutputs: []string{"certificate", "insecure"},
  499. }
  500. test.run(t)
  501. }
  502. func TestMergeExistingAuth(t *testing.T) {
  503. expectedConfig := newRedFederalCowHammerConfig()
  504. authInfo := expectedConfig.AuthInfos["red-user"]
  505. authInfo.ClientKey = "/key"
  506. expectedConfig.AuthInfos["red-user"] = authInfo
  507. test := configCommandTest{
  508. args: []string{"set-credentials", "red-user", "--" + clientcmd.FlagKeyFile + "=/key"},
  509. startingConfig: newRedFederalCowHammerConfig(),
  510. expectedConfig: expectedConfig,
  511. }
  512. test.run(t)
  513. }
  514. func TestNewEmptyCluster(t *testing.T) {
  515. expectedConfig := *clientcmdapi.NewConfig()
  516. expectedConfig.Clusters["new-cluster"] = clientcmdapi.NewCluster()
  517. test := configCommandTest{
  518. args: []string{"set-cluster", "new-cluster"},
  519. startingConfig: *clientcmdapi.NewConfig(),
  520. expectedConfig: expectedConfig,
  521. }
  522. test.run(t)
  523. }
  524. func TestAdditionalCluster(t *testing.T) {
  525. expectedConfig := newRedFederalCowHammerConfig()
  526. cluster := clientcmdapi.NewCluster()
  527. cluster.CertificateAuthority = "/ca-location"
  528. cluster.InsecureSkipTLSVerify = false
  529. cluster.Server = "serverlocation"
  530. expectedConfig.Clusters["different-cluster"] = cluster
  531. test := configCommandTest{
  532. args: []string{"set-cluster", "different-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation", "--" + clientcmd.FlagInsecure + "=false", "--" + clientcmd.FlagCAFile + "=/ca-location"},
  533. startingConfig: newRedFederalCowHammerConfig(),
  534. expectedConfig: expectedConfig,
  535. }
  536. test.run(t)
  537. }
  538. func TestOverwriteExistingCluster(t *testing.T) {
  539. expectedConfig := newRedFederalCowHammerConfig()
  540. cluster := clientcmdapi.NewCluster()
  541. cluster.Server = "serverlocation"
  542. expectedConfig.Clusters["cow-cluster"] = cluster
  543. test := configCommandTest{
  544. args: []string{"set-cluster", "cow-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation"},
  545. startingConfig: newRedFederalCowHammerConfig(),
  546. expectedConfig: expectedConfig,
  547. }
  548. test.run(t)
  549. }
  550. func TestNewEmptyContext(t *testing.T) {
  551. expectedConfig := *clientcmdapi.NewConfig()
  552. expectedConfig.Contexts["new-context"] = clientcmdapi.NewContext()
  553. test := configCommandTest{
  554. args: []string{"set-context", "new-context"},
  555. startingConfig: *clientcmdapi.NewConfig(),
  556. expectedConfig: expectedConfig,
  557. }
  558. test.run(t)
  559. }
  560. func TestAdditionalContext(t *testing.T) {
  561. expectedConfig := newRedFederalCowHammerConfig()
  562. context := clientcmdapi.NewContext()
  563. context.Cluster = "some-cluster"
  564. context.AuthInfo = "some-user"
  565. context.Namespace = "different-namespace"
  566. expectedConfig.Contexts["different-context"] = context
  567. test := configCommandTest{
  568. args: []string{"set-context", "different-context", "--" + clientcmd.FlagClusterName + "=some-cluster", "--" + clientcmd.FlagAuthInfoName + "=some-user", "--" + clientcmd.FlagNamespace + "=different-namespace"},
  569. startingConfig: newRedFederalCowHammerConfig(),
  570. expectedConfig: expectedConfig,
  571. }
  572. test.run(t)
  573. }
  574. func TestMergeExistingContext(t *testing.T) {
  575. expectedConfig := newRedFederalCowHammerConfig()
  576. context := expectedConfig.Contexts["federal-context"]
  577. context.Namespace = "hammer"
  578. expectedConfig.Contexts["federal-context"] = context
  579. test := configCommandTest{
  580. args: []string{"set-context", "federal-context", "--" + clientcmd.FlagNamespace + "=hammer"},
  581. startingConfig: newRedFederalCowHammerConfig(),
  582. expectedConfig: expectedConfig,
  583. }
  584. test.run(t)
  585. }
  586. func TestToBool(t *testing.T) {
  587. type test struct {
  588. in string
  589. out bool
  590. err string
  591. }
  592. tests := []test{
  593. {"", false, ""},
  594. {"true", true, ""},
  595. {"on", false, `strconv.ParseBool: parsing "on": invalid syntax`},
  596. }
  597. for _, curr := range tests {
  598. b, err := toBool(curr.in)
  599. if (len(curr.err) != 0) && err == nil {
  600. t.Errorf("Expected error: %v, but got nil", curr.err)
  601. }
  602. if (len(curr.err) == 0) && err != nil {
  603. t.Errorf("Unexpected error: %v", err)
  604. }
  605. if (err != nil) && (err.Error() != curr.err) {
  606. t.Errorf("Expected %v, got %v", curr.err, err)
  607. }
  608. if b != curr.out {
  609. t.Errorf("Expected %v, got %v", curr.out, b)
  610. }
  611. }
  612. }
  613. func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *testing.T) (string, clientcmdapi.Config) {
  614. fakeKubeFile, _ := ioutil.TempFile("", "")
  615. defer os.Remove(fakeKubeFile.Name())
  616. err := clientcmd.WriteToFile(startingConfig, fakeKubeFile.Name())
  617. if err != nil {
  618. t.Fatalf("unexpected error: %v", err)
  619. }
  620. argsToUse := make([]string, 0, 2+len(args))
  621. argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name())
  622. argsToUse = append(argsToUse, args...)
  623. buf := bytes.NewBuffer([]byte{})
  624. cmd := NewCmdConfig(clientcmd.NewDefaultPathOptions(), buf)
  625. cmd.SetArgs(argsToUse)
  626. cmd.Execute()
  627. // outBytes, _ := ioutil.ReadFile(fakeKubeFile.Name())
  628. config := clientcmd.GetConfigFromFileOrDie(fakeKubeFile.Name())
  629. return buf.String(), *config
  630. }
  631. type configCommandTest struct {
  632. args []string
  633. startingConfig clientcmdapi.Config
  634. expectedConfig clientcmdapi.Config
  635. expectedOutputs []string
  636. }
  637. func (test configCommandTest) run(t *testing.T) string {
  638. out, actualConfig := testConfigCommand(test.args, test.startingConfig, t)
  639. testSetNilMapsToEmpties(reflect.ValueOf(&test.expectedConfig))
  640. testSetNilMapsToEmpties(reflect.ValueOf(&actualConfig))
  641. testClearLocationOfOrigin(&actualConfig)
  642. if !api.Semantic.DeepEqual(test.expectedConfig, actualConfig) {
  643. t.Errorf("diff: %v", diff.ObjectDiff(test.expectedConfig, actualConfig))
  644. t.Errorf("expected: %#v\n actual: %#v", test.expectedConfig, actualConfig)
  645. }
  646. for _, expectedOutput := range test.expectedOutputs {
  647. if !strings.Contains(out, expectedOutput) {
  648. t.Errorf("expected '%s' in output, got '%s'", expectedOutput, out)
  649. }
  650. }
  651. return out
  652. }
  653. func testClearLocationOfOrigin(config *clientcmdapi.Config) {
  654. for key, obj := range config.AuthInfos {
  655. obj.LocationOfOrigin = ""
  656. config.AuthInfos[key] = obj
  657. }
  658. for key, obj := range config.Clusters {
  659. obj.LocationOfOrigin = ""
  660. config.Clusters[key] = obj
  661. }
  662. for key, obj := range config.Contexts {
  663. obj.LocationOfOrigin = ""
  664. config.Contexts[key] = obj
  665. }
  666. }
  667. func testSetNilMapsToEmpties(curr reflect.Value) {
  668. actualCurrValue := curr
  669. if curr.Kind() == reflect.Ptr {
  670. actualCurrValue = curr.Elem()
  671. }
  672. switch actualCurrValue.Kind() {
  673. case reflect.Map:
  674. for _, mapKey := range actualCurrValue.MapKeys() {
  675. currMapValue := actualCurrValue.MapIndex(mapKey)
  676. testSetNilMapsToEmpties(currMapValue)
  677. }
  678. case reflect.Struct:
  679. for fieldIndex := 0; fieldIndex < actualCurrValue.NumField(); fieldIndex++ {
  680. currFieldValue := actualCurrValue.Field(fieldIndex)
  681. if currFieldValue.Kind() == reflect.Map && currFieldValue.IsNil() {
  682. newValue := reflect.MakeMap(currFieldValue.Type())
  683. currFieldValue.Set(newValue)
  684. } else {
  685. testSetNilMapsToEmpties(currFieldValue.Addr())
  686. }
  687. }
  688. }
  689. }