config_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. if err == nil || err.Error() != expectedError {
  115. t.Fatalf("Should have failed, got: %q, %q", config, err)
  116. }
  117. }
  118. }
  119. func TestOldValidAuth(t *testing.T) {
  120. tmpHome, err := ioutil.TempDir("", "config-test")
  121. if err != nil {
  122. t.Fatal(err)
  123. }
  124. if err != nil {
  125. t.Fatal(err)
  126. }
  127. defer os.RemoveAll(tmpHome)
  128. homeKey := homedir.Key()
  129. homeVal := homedir.Get()
  130. defer func() { os.Setenv(homeKey, homeVal) }()
  131. os.Setenv(homeKey, tmpHome)
  132. fn := filepath.Join(tmpHome, oldConfigfile)
  133. js := `username = am9lam9lOmhlbGxv
  134. email = user@example.com`
  135. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  136. t.Fatal(err)
  137. }
  138. config, err := Load(tmpHome)
  139. if err != nil {
  140. t.Fatal(err)
  141. }
  142. // defaultIndexserver is https://index.docker.io/v1/
  143. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  144. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  145. t.Fatalf("Missing data from parsing:\n%q", config)
  146. }
  147. // Now save it and make sure it shows up in new form
  148. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  149. if !strings.Contains(configStr, "user@example.com") {
  150. t.Fatalf("Should have save in new form: %s", configStr)
  151. }
  152. }
  153. func TestOldJsonInvalid(t *testing.T) {
  154. tmpHome, err := ioutil.TempDir("", "config-test")
  155. if err != nil {
  156. t.Fatal(err)
  157. }
  158. defer os.RemoveAll(tmpHome)
  159. homeKey := homedir.Key()
  160. homeVal := homedir.Get()
  161. defer func() { os.Setenv(homeKey, homeVal) }()
  162. os.Setenv(homeKey, tmpHome)
  163. fn := filepath.Join(tmpHome, oldConfigfile)
  164. js := `{"https://index.docker.io/v1/":{"auth":"test","email":"user@example.com"}}`
  165. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  166. t.Fatal(err)
  167. }
  168. config, err := Load(tmpHome)
  169. if err == nil || err.Error() != "Invalid auth configuration file" {
  170. t.Fatalf("Expected an error got : %v, %v", config, err)
  171. }
  172. }
  173. func TestOldJson(t *testing.T) {
  174. tmpHome, err := ioutil.TempDir("", "config-test")
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. defer os.RemoveAll(tmpHome)
  179. homeKey := homedir.Key()
  180. homeVal := homedir.Get()
  181. defer func() { os.Setenv(homeKey, homeVal) }()
  182. os.Setenv(homeKey, tmpHome)
  183. fn := filepath.Join(tmpHome, oldConfigfile)
  184. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  185. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  186. t.Fatal(err)
  187. }
  188. config, err := Load(tmpHome)
  189. if err != nil {
  190. t.Fatalf("Failed loading on empty json file: %q", err)
  191. }
  192. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  193. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  194. t.Fatalf("Missing data from parsing:\n%q", config)
  195. }
  196. // Now save it and make sure it shows up in new form
  197. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  198. if !strings.Contains(configStr, "user@example.com") {
  199. t.Fatalf("Should have save in new form: %s", configStr)
  200. }
  201. }
  202. func TestNewJson(t *testing.T) {
  203. tmpHome, err := ioutil.TempDir("", "config-test")
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. defer os.RemoveAll(tmpHome)
  208. fn := filepath.Join(tmpHome, ConfigFileName)
  209. js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
  210. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  211. t.Fatal(err)
  212. }
  213. config, err := Load(tmpHome)
  214. if err != nil {
  215. t.Fatalf("Failed loading on empty json file: %q", err)
  216. }
  217. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  218. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  219. t.Fatalf("Missing data from parsing:\n%q", config)
  220. }
  221. // Now save it and make sure it shows up in new form
  222. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  223. if !strings.Contains(configStr, "user@example.com") {
  224. t.Fatalf("Should have save in new form: %s", configStr)
  225. }
  226. }
  227. func TestJsonWithPsFormat(t *testing.T) {
  228. tmpHome, err := ioutil.TempDir("", "config-test")
  229. if err != nil {
  230. t.Fatal(err)
  231. }
  232. defer os.RemoveAll(tmpHome)
  233. fn := filepath.Join(tmpHome, ConfigFileName)
  234. js := `{
  235. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  236. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  237. }`
  238. if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
  239. t.Fatal(err)
  240. }
  241. config, err := Load(tmpHome)
  242. if err != nil {
  243. t.Fatalf("Failed loading on empty json file: %q", err)
  244. }
  245. if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` {
  246. t.Fatalf("Unknown ps format: %s\n", config.PsFormat)
  247. }
  248. // Now save it and make sure it shows up in new form
  249. configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
  250. if !strings.Contains(configStr, `"psFormat":`) ||
  251. !strings.Contains(configStr, "{{.ID}}") {
  252. t.Fatalf("Should have save in new form: %s", configStr)
  253. }
  254. }
  255. // Save it and make sure it shows up in new form
  256. func saveConfigAndValidateNewFormat(t *testing.T, config *ConfigFile, homeFolder string) string {
  257. err := config.Save()
  258. if err != nil {
  259. t.Fatalf("Failed to save: %q", err)
  260. }
  261. buf, err := ioutil.ReadFile(filepath.Join(homeFolder, ConfigFileName))
  262. if !strings.Contains(string(buf), `"auths":`) {
  263. t.Fatalf("Should have save in new form: %s", string(buf))
  264. }
  265. return string(buf)
  266. }
  267. func TestConfigDir(t *testing.T) {
  268. tmpHome, err := ioutil.TempDir("", "config-test")
  269. if err != nil {
  270. t.Fatal(err)
  271. }
  272. defer os.RemoveAll(tmpHome)
  273. if ConfigDir() == tmpHome {
  274. t.Fatalf("Expected ConfigDir to be different than %s by default, but was the same", tmpHome)
  275. }
  276. // Update configDir
  277. SetConfigDir(tmpHome)
  278. if ConfigDir() != tmpHome {
  279. t.Fatalf("Expected ConfigDir to %s, but was %s", tmpHome, ConfigDir())
  280. }
  281. }
  282. func TestConfigFile(t *testing.T) {
  283. configFilename := "configFilename"
  284. configFile := NewConfigFile(configFilename)
  285. if configFile.Filename() != configFilename {
  286. t.Fatalf("Expected %s, got %s", configFilename, configFile.Filename())
  287. }
  288. }
  289. func TestJsonReaderNoFile(t *testing.T) {
  290. js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
  291. config, err := LoadFromReader(strings.NewReader(js))
  292. if err != nil {
  293. t.Fatalf("Failed loading on empty json file: %q", err)
  294. }
  295. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  296. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  297. t.Fatalf("Missing data from parsing:\n%q", config)
  298. }
  299. }
  300. func TestOldJsonReaderNoFile(t *testing.T) {
  301. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  302. config, err := LegacyLoadFromReader(strings.NewReader(js))
  303. if err != nil {
  304. t.Fatalf("Failed loading on empty json file: %q", err)
  305. }
  306. ac := config.AuthConfigs["https://index.docker.io/v1/"]
  307. if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
  308. t.Fatalf("Missing data from parsing:\n%q", config)
  309. }
  310. }
  311. func TestJsonWithPsFormatNoFile(t *testing.T) {
  312. js := `{
  313. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  314. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  315. }`
  316. config, err := LoadFromReader(strings.NewReader(js))
  317. if err != nil {
  318. t.Fatalf("Failed loading on empty json file: %q", err)
  319. }
  320. if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` {
  321. t.Fatalf("Unknown ps format: %s\n", config.PsFormat)
  322. }
  323. }
  324. func TestJsonSaveWithNoFile(t *testing.T) {
  325. js := `{
  326. "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
  327. "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
  328. }`
  329. config, err := LoadFromReader(strings.NewReader(js))
  330. err = config.Save()
  331. if err == nil {
  332. t.Fatalf("Expected error. File should not have been able to save with no file name.")
  333. }
  334. tmpHome, err := ioutil.TempDir("", "config-test")
  335. if err != nil {
  336. t.Fatalf("Failed to create a temp dir: %q", err)
  337. }
  338. defer os.RemoveAll(tmpHome)
  339. fn := filepath.Join(tmpHome, ConfigFileName)
  340. f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
  341. err = config.SaveToWriter(f)
  342. if err != nil {
  343. t.Fatalf("Failed saving to file: %q", err)
  344. }
  345. buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
  346. if !strings.Contains(string(buf), `"auths":`) ||
  347. !strings.Contains(string(buf), "user@example.com") {
  348. t.Fatalf("Should have save in new form: %s", string(buf))
  349. }
  350. }
  351. func TestLegacyJsonSaveWithNoFile(t *testing.T) {
  352. js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
  353. config, err := LegacyLoadFromReader(strings.NewReader(js))
  354. err = config.Save()
  355. if err == nil {
  356. t.Fatalf("Expected error. File should not have been able to save with no file name.")
  357. }
  358. tmpHome, err := ioutil.TempDir("", "config-test")
  359. if err != nil {
  360. t.Fatalf("Failed to create a temp dir: %q", err)
  361. }
  362. defer os.RemoveAll(tmpHome)
  363. fn := filepath.Join(tmpHome, ConfigFileName)
  364. f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
  365. err = config.SaveToWriter(f)
  366. if err != nil {
  367. t.Fatalf("Failed saving to file: %q", err)
  368. }
  369. buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
  370. if !strings.Contains(string(buf), `"auths":`) ||
  371. !strings.Contains(string(buf), "user@example.com") {
  372. t.Fatalf("Should have save in new form: %s", string(buf))
  373. }
  374. }
  375. func TestEncodeAuth(t *testing.T) {
  376. newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
  377. authStr := encodeAuth(newAuthConfig)
  378. decAuthConfig := &types.AuthConfig{}
  379. var err error
  380. decAuthConfig.Username, decAuthConfig.Password, err = decodeAuth(authStr)
  381. if err != nil {
  382. t.Fatal(err)
  383. }
  384. if newAuthConfig.Username != decAuthConfig.Username {
  385. t.Fatal("Encode Username doesn't match decoded Username")
  386. }
  387. if newAuthConfig.Password != decAuthConfig.Password {
  388. t.Fatal("Encode Password doesn't match decoded Password")
  389. }
  390. if authStr != "a2VuOnRlc3Q=" {
  391. t.Fatal("AuthString encoding isn't correct.")
  392. }
  393. }