config_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. package cliconfig
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "testing"
  8. "github.com/docker/docker/api/types"
  9. "github.com/docker/docker/pkg/homedir"
  10. )
  11. func TestEmptyConfigDir(t *testing.T) {
  12. tmpHome, err := ioutil.TempDir("", "config-test")
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. defer os.RemoveAll(tmpHome)
  17. SetConfigDir(tmpHome)
  18. config, err := Load("")
  19. if err != nil {
  20. t.Fatalf("Failed loading on empty config dir: %q", err)
  21. }
  22. expectedConfigFilename := filepath.Join(tmpHome, ConfigFileName)
  23. if config.Filename() != expectedConfigFilename {
  24. t.Fatalf("Expected config filename %s, got %s", expectedConfigFilename, config.Filename())
  25. }
  26. // Now save it and make sure it shows up in new form
  27. saveConfigAndValidateNewFormat(t, config, tmpHome)
  28. }
  29. func TestMissingFile(t *testing.T) {
  30. tmpHome, err := ioutil.TempDir("", "config-test")
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. defer os.RemoveAll(tmpHome)
  35. config, err := Load(tmpHome)
  36. if err != nil {
  37. t.Fatalf("Failed loading on missing file: %q", err)
  38. }
  39. // Now save it and make sure it shows up in new form
  40. saveConfigAndValidateNewFormat(t, config, tmpHome)
  41. }
  42. func TestSaveFileToDirs(t *testing.T) {
  43. tmpHome, err := ioutil.TempDir("", "config-test")
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. defer os.RemoveAll(tmpHome)
  48. tmpHome += "/.docker"
  49. config, err := Load(tmpHome)
  50. if err != nil {
  51. t.Fatalf("Failed loading on missing file: %q", err)
  52. }
  53. // Now save it and make sure it shows up in new form
  54. saveConfigAndValidateNewFormat(t, config, tmpHome)
  55. }
  56. func TestEmptyFile(t *testing.T) {
  57. tmpHome, err := ioutil.TempDir("", "config-test")
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. defer os.RemoveAll(tmpHome)
  62. fn := filepath.Join(tmpHome, ConfigFileName)
  63. if err := ioutil.WriteFile(fn, []byte(""), 0600); err != nil {
  64. t.Fatal(err)
  65. }
  66. _, err = Load(tmpHome)
  67. if err == nil {
  68. t.Fatalf("Was supposed to fail")
  69. }
  70. }
  71. func TestEmptyJson(t *testing.T) {
  72. tmpHome, err := ioutil.TempDir("", "config-test")
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. defer os.RemoveAll(tmpHome)
  77. fn := filepath.Join(tmpHome, ConfigFileName)
  78. if err := ioutil.WriteFile(fn, []byte("{}"), 0600); err != nil {
  79. t.Fatal(err)
  80. }
  81. config, err := Load(tmpHome)
  82. if err != nil {
  83. t.Fatalf("Failed loading on empty json file: %q", err)
  84. }
  85. // Now save it and make sure it shows up in new form
  86. saveConfigAndValidateNewFormat(t, config, tmpHome)
  87. }
  88. func TestOldInvalidsAuth(t *testing.T) {
  89. invalids := map[string]string{
  90. `username = test`: "The Auth config file is empty",
  91. `username
  92. password
  93. email`: "Invalid Auth config file",
  94. `username = test
  95. email`: "Invalid auth configuration file",
  96. `username = am9lam9lOmhlbGxv
  97. email`: "Invalid Auth config file",
  98. }
  99. tmpHome, err := ioutil.TempDir("", "config-test")
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. defer os.RemoveAll(tmpHome)
  104. homeKey := homedir.Key()
  105. homeVal := homedir.Get()
  106. defer func() { os.Setenv(homeKey, homeVal) }()
  107. os.Setenv(homeKey, tmpHome)
  108. for content, expectedError := range invalids {
  109. fn := filepath.Join(tmpHome, oldConfigfile)
  110. if err := ioutil.WriteFile(fn, []byte(content), 0600); err != nil {
  111. t.Fatal(err)
  112. }
  113. config, err := Load(tmpHome)
  114. // Use Contains instead of == since the file name will change each time
  115. if err == nil || !strings.Contains(err.Error(), expectedError) {
  116. t.Fatalf("Should have failed\nConfig: %v\nGot: %v\nExpected: %v", config, err, expectedError)
  117. }
  118. }
  119. }
  120. func TestOldValidAuth(t *testing.T) {
  121. tmpHome, err := ioutil.TempDir("", "config-test")
  122. if err != nil {
  123. t.Fatal(err)
  124. }
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. defer os.RemoveAll(tmpHome)
  129. homeKey := homedir.Key()
  130. homeVal := homedir.Get()
  131. defer func() { os.Setenv(homeKey, homeVal) }()
  132. os.Setenv(homeKey, tmpHome)
  133. fn := filepath.Join(tmpHome, oldConfigfile)
  134. js := `username = am9lam9lOmhlbGxv
  135. email = user@example.com`
  136. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  137. t.Fatal(err)
  138. }
  139. config, err := Load(tmpHome)
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. // defaultIndexserver is https://index.docker.io/v1/
  144. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  145. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  146. t.Fatalf("Missing data from parsing:\n%q", config)
  147. }
  148. // Now save it and make sure it shows up in new form
  149. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  150. if !strings.Contains(configStr, "user@example.com") {
  151. t.Fatalf("Should have save in new form: %s", configStr)
  152. }
  153. }
  154. func TestOldJsonInvalid(t *testing.T) {
  155. tmpHome, err := ioutil.TempDir("", "config-test")
  156. if err != nil {
  157. t.Fatal(err)
  158. }
  159. defer os.RemoveAll(tmpHome)
  160. homeKey := homedir.Key()
  161. homeVal := homedir.Get()
  162. defer func() { os.Setenv(homeKey, homeVal) }()
  163. os.Setenv(homeKey, tmpHome)
  164. fn := filepath.Join(tmpHome, oldConfigfile)
  165. js := `{"https://index.docker.io/v1/":{"auth":"test","email":"user@example.com"}}`
  166. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  167. t.Fatal(err)
  168. }
  169. config, err := Load(tmpHome)
  170. // Use Contains instead of == since the file name will change each time
  171. if err == nil || !strings.Contains(err.Error(), "Invalid auth configuration file") {
  172. t.Fatalf("Expected an error got : %v, %v", config, err)
  173. }
  174. }
  175. func TestOldJson(t *testing.T) {
  176. tmpHome, err := ioutil.TempDir("", "config-test")
  177. if err != nil {
  178. t.Fatal(err)
  179. }
  180. defer os.RemoveAll(tmpHome)
  181. homeKey := homedir.Key()
  182. homeVal := homedir.Get()
  183. defer func() { os.Setenv(homeKey, homeVal) }()
  184. os.Setenv(homeKey, tmpHome)
  185. fn := filepath.Join(tmpHome, oldConfigfile)
  186. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  187. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  188. t.Fatal(err)
  189. }
  190. config, err := Load(tmpHome)
  191. if err != nil {
  192. t.Fatalf("Failed loading on empty json file: %q", err)
  193. }
  194. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  195. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  196. t.Fatalf("Missing data from parsing:\n%q", config)
  197. }
  198. // Now save it and make sure it shows up in new form
  199. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  200. if !strings.Contains(configStr, "user@example.com") {
  201. t.Fatalf("Should have save in new form: %s", configStr)
  202. }
  203. }
  204. func TestNewJson(t *testing.T) {
  205. tmpHome, err := ioutil.TempDir("", "config-test")
  206. if err != nil {
  207. t.Fatal(err)
  208. }
  209. defer os.RemoveAll(tmpHome)
  210. fn := filepath.Join(tmpHome, ConfigFileName)
  211. js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
  212. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  213. t.Fatal(err)
  214. }
  215. config, err := Load(tmpHome)
  216. if err != nil {
  217. t.Fatalf("Failed loading on empty json file: %q", err)
  218. }
  219. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  220. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  221. t.Fatalf("Missing data from parsing:\n%q", config)
  222. }
  223. // Now save it and make sure it shows up in new form
  224. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  225. if !strings.Contains(configStr, "user@example.com") {
  226. t.Fatalf("Should have save in new form: %s", configStr)
  227. }
  228. }
  229. func TestJsonWithPsFormat(t *testing.T) {
  230. tmpHome, err := ioutil.TempDir("", "config-test")
  231. if err != nil {
  232. t.Fatal(err)
  233. }
  234. defer os.RemoveAll(tmpHome)
  235. fn := filepath.Join(tmpHome, ConfigFileName)
  236. js := `{
  237. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  238. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  239. }`
  240. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  241. t.Fatal(err)
  242. }
  243. config, err := Load(tmpHome)
  244. if err != nil {
  245. t.Fatalf("Failed loading on empty json file: %q", err)
  246. }
  247. if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` {
  248. t.Fatalf("Unknown ps format: %s\n", config.PsFormat)
  249. }
  250. // Now save it and make sure it shows up in new form
  251. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  252. if !strings.Contains(configStr, `"psFormat":`) ||
  253. !strings.Contains(configStr, "{{.ID}}") {
  254. t.Fatalf("Should have save in new form: %s", configStr)
  255. }
  256. }
  257. // Save it and make sure it shows up in new form
  258. func saveConfigAndValidateNewFormat(t *testing.T, config *ConfigFile, homeFolder string) string {
  259. err := config.Save()
  260. if err != nil {
  261. t.Fatalf("Failed to save: %q", err)
  262. }
  263. buf, err := ioutil.ReadFile(filepath.Join(homeFolder, ConfigFileName))
  264. if !strings.Contains(string(buf), `"auths":`) {
  265. t.Fatalf("Should have save in new form: %s", string(buf))
  266. }
  267. return string(buf)
  268. }
  269. func TestConfigDir(t *testing.T) {
  270. tmpHome, err := ioutil.TempDir("", "config-test")
  271. if err != nil {
  272. t.Fatal(err)
  273. }
  274. defer os.RemoveAll(tmpHome)
  275. if ConfigDir() == tmpHome {
  276. t.Fatalf("Expected ConfigDir to be different than %s by default, but was the same", tmpHome)
  277. }
  278. // Update configDir
  279. SetConfigDir(tmpHome)
  280. if ConfigDir() != tmpHome {
  281. t.Fatalf("Expected ConfigDir to %s, but was %s", tmpHome, ConfigDir())
  282. }
  283. }
  284. func TestConfigFile(t *testing.T) {
  285. configFilename := "configFilename"
  286. configFile := NewConfigFile(configFilename)
  287. if configFile.Filename() != configFilename {
  288. t.Fatalf("Expected %s, got %s", configFilename, configFile.Filename())
  289. }
  290. }
  291. func TestJsonReaderNoFile(t *testing.T) {
  292. js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
  293. config, err := LoadFromReader(strings.NewReader(js))
  294. if err != nil {
  295. t.Fatalf("Failed loading on empty json file: %q", err)
  296. }
  297. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  298. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  299. t.Fatalf("Missing data from parsing:\n%q", config)
  300. }
  301. }
  302. func TestOldJsonReaderNoFile(t *testing.T) {
  303. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  304. config, err := LegacyLoadFromReader(strings.NewReader(js))
  305. if err != nil {
  306. t.Fatalf("Failed loading on empty json file: %q", err)
  307. }
  308. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  309. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  310. t.Fatalf("Missing data from parsing:\n%q", config)
  311. }
  312. }
  313. func TestJsonWithPsFormatNoFile(t *testing.T) {
  314. js := `{
  315. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  316. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  317. }`
  318. config, err := LoadFromReader(strings.NewReader(js))
  319. if err != nil {
  320. t.Fatalf("Failed loading on empty json file: %q", err)
  321. }
  322. if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` {
  323. t.Fatalf("Unknown ps format: %s\n", config.PsFormat)
  324. }
  325. }
  326. func TestJsonSaveWithNoFile(t *testing.T) {
  327. js := `{
  328. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  329. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  330. }`
  331. config, err := LoadFromReader(strings.NewReader(js))
  332. err = config.Save()
  333. if err == nil {
  334. t.Fatalf("Expected error. File should not have been able to save with no file name.")
  335. }
  336. tmpHome, err := ioutil.TempDir("", "config-test")
  337. if err != nil {
  338. t.Fatalf("Failed to create a temp dir: %q", err)
  339. }
  340. defer os.RemoveAll(tmpHome)
  341. fn := filepath.Join(tmpHome, ConfigFileName)
  342. f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
  343. err = config.SaveToWriter(f)
  344. if err != nil {
  345. t.Fatalf("Failed saving to file: %q", err)
  346. }
  347. buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
  348. if !strings.Contains(string(buf), `"auths":`) ||
  349. !strings.Contains(string(buf), "user@example.com") {
  350. t.Fatalf("Should have save in new form: %s", string(buf))
  351. }
  352. }
  353. func TestLegacyJsonSaveWithNoFile(t *testing.T) {
  354. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  355. config, err := LegacyLoadFromReader(strings.NewReader(js))
  356. err = config.Save()
  357. if err == nil {
  358. t.Fatalf("Expected error. File should not have been able to save with no file name.")
  359. }
  360. tmpHome, err := ioutil.TempDir("", "config-test")
  361. if err != nil {
  362. t.Fatalf("Failed to create a temp dir: %q", err)
  363. }
  364. defer os.RemoveAll(tmpHome)
  365. fn := filepath.Join(tmpHome, ConfigFileName)
  366. f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
  367. err = config.SaveToWriter(f)
  368. if err != nil {
  369. t.Fatalf("Failed saving to file: %q", err)
  370. }
  371. buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
  372. if !strings.Contains(string(buf), `"auths":`) ||
  373. !strings.Contains(string(buf), "user@example.com") {
  374. t.Fatalf("Should have save in new form: %s", string(buf))
  375. }
  376. }
  377. func TestEncodeAuth(t *testing.T) {
  378. newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
  379. authStr := encodeAuth(newAuthConfig)
  380. decAuthConfig := &types.AuthConfig{}
  381. var err error
  382. decAuthConfig.Username, decAuthConfig.Password, err = decodeAuth(authStr)
  383. if err != nil {
  384. t.Fatal(err)
  385. }
  386. if newAuthConfig.Username != decAuthConfig.Username {
  387. t.Fatal("Encode Username doesn't match decoded Username")
  388. }
  389. if newAuthConfig.Password != decAuthConfig.Password {
  390. t.Fatal("Encode Password doesn't match decoded Password")
  391. }
  392. if authStr != "a2VuOnRlc3Q=" {
  393. t.Fatal("AuthString encoding isn't correct.")
  394. }
  395. }