github.com/jen20/docker@v1.13.1/cliconfig/config_test.go (about) 1 package cliconfig 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/docker/docker/cliconfig/configfile" 11 "github.com/docker/docker/pkg/homedir" 12 ) 13 14 func TestEmptyConfigDir(t *testing.T) { 15 tmpHome, err := ioutil.TempDir("", "config-test") 16 if err != nil { 17 t.Fatal(err) 18 } 19 defer os.RemoveAll(tmpHome) 20 21 SetConfigDir(tmpHome) 22 23 config, err := Load("") 24 if err != nil { 25 t.Fatalf("Failed loading on empty config dir: %q", err) 26 } 27 28 expectedConfigFilename := filepath.Join(tmpHome, ConfigFileName) 29 if config.Filename != expectedConfigFilename { 30 t.Fatalf("Expected config filename %s, got %s", expectedConfigFilename, config.Filename) 31 } 32 33 // Now save it and make sure it shows up in new form 34 saveConfigAndValidateNewFormat(t, config, tmpHome) 35 } 36 37 func TestMissingFile(t *testing.T) { 38 tmpHome, err := ioutil.TempDir("", "config-test") 39 if err != nil { 40 t.Fatal(err) 41 } 42 defer os.RemoveAll(tmpHome) 43 44 config, err := Load(tmpHome) 45 if err != nil { 46 t.Fatalf("Failed loading on missing file: %q", err) 47 } 48 49 // Now save it and make sure it shows up in new form 50 saveConfigAndValidateNewFormat(t, config, tmpHome) 51 } 52 53 func TestSaveFileToDirs(t *testing.T) { 54 tmpHome, err := ioutil.TempDir("", "config-test") 55 if err != nil { 56 t.Fatal(err) 57 } 58 defer os.RemoveAll(tmpHome) 59 60 tmpHome += "/.docker" 61 62 config, err := Load(tmpHome) 63 if err != nil { 64 t.Fatalf("Failed loading on missing file: %q", err) 65 } 66 67 // Now save it and make sure it shows up in new form 68 saveConfigAndValidateNewFormat(t, config, tmpHome) 69 } 70 71 func TestEmptyFile(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 78 fn := filepath.Join(tmpHome, ConfigFileName) 79 if err := ioutil.WriteFile(fn, []byte(""), 0600); err != nil { 80 t.Fatal(err) 81 } 82 83 _, err = Load(tmpHome) 84 if err == nil { 85 t.Fatalf("Was supposed to fail") 86 } 87 } 88 89 func TestEmptyJSON(t *testing.T) { 90 tmpHome, err := ioutil.TempDir("", "config-test") 91 if err != nil { 92 t.Fatal(err) 93 } 94 defer os.RemoveAll(tmpHome) 95 96 fn := filepath.Join(tmpHome, ConfigFileName) 97 if err := ioutil.WriteFile(fn, []byte("{}"), 0600); err != nil { 98 t.Fatal(err) 99 } 100 101 config, err := Load(tmpHome) 102 if err != nil { 103 t.Fatalf("Failed loading on empty json file: %q", err) 104 } 105 106 // Now save it and make sure it shows up in new form 107 saveConfigAndValidateNewFormat(t, config, tmpHome) 108 } 109 110 func TestOldInvalidsAuth(t *testing.T) { 111 invalids := map[string]string{ 112 `username = test`: "The Auth config file is empty", 113 `username 114 password`: "Invalid Auth config file", 115 `username = test 116 email`: "Invalid auth configuration file", 117 } 118 119 tmpHome, err := ioutil.TempDir("", "config-test") 120 if err != nil { 121 t.Fatal(err) 122 } 123 defer os.RemoveAll(tmpHome) 124 125 homeKey := homedir.Key() 126 homeVal := homedir.Get() 127 128 defer func() { os.Setenv(homeKey, homeVal) }() 129 os.Setenv(homeKey, tmpHome) 130 131 for content, expectedError := range invalids { 132 fn := filepath.Join(tmpHome, oldConfigfile) 133 if err := ioutil.WriteFile(fn, []byte(content), 0600); err != nil { 134 t.Fatal(err) 135 } 136 137 config, err := Load(tmpHome) 138 // Use Contains instead of == since the file name will change each time 139 if err == nil || !strings.Contains(err.Error(), expectedError) { 140 t.Fatalf("Should have failed\nConfig: %v\nGot: %v\nExpected: %v", config, err, expectedError) 141 } 142 143 } 144 } 145 146 func TestOldValidAuth(t *testing.T) { 147 tmpHome, err := ioutil.TempDir("", "config-test") 148 if err != nil { 149 t.Fatal(err) 150 } 151 if err != nil { 152 t.Fatal(err) 153 } 154 defer os.RemoveAll(tmpHome) 155 156 homeKey := homedir.Key() 157 homeVal := homedir.Get() 158 159 defer func() { os.Setenv(homeKey, homeVal) }() 160 os.Setenv(homeKey, tmpHome) 161 162 fn := filepath.Join(tmpHome, oldConfigfile) 163 js := `username = am9lam9lOmhlbGxv 164 email = user@example.com` 165 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 166 t.Fatal(err) 167 } 168 169 config, err := Load(tmpHome) 170 if err != nil { 171 t.Fatal(err) 172 } 173 174 // defaultIndexserver is https://index.docker.io/v1/ 175 ac := config.AuthConfigs["https://index.docker.io/v1/"] 176 if ac.Username != "joejoe" || ac.Password != "hello" { 177 t.Fatalf("Missing data from parsing:\n%q", config) 178 } 179 180 // Now save it and make sure it shows up in new form 181 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 182 183 expConfStr := `{ 184 "auths": { 185 "https://index.docker.io/v1/": { 186 "auth": "am9lam9lOmhlbGxv" 187 } 188 } 189 }` 190 191 if configStr != expConfStr { 192 t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr) 193 } 194 } 195 196 func TestOldJSONInvalid(t *testing.T) { 197 tmpHome, err := ioutil.TempDir("", "config-test") 198 if err != nil { 199 t.Fatal(err) 200 } 201 defer os.RemoveAll(tmpHome) 202 203 homeKey := homedir.Key() 204 homeVal := homedir.Get() 205 206 defer func() { os.Setenv(homeKey, homeVal) }() 207 os.Setenv(homeKey, tmpHome) 208 209 fn := filepath.Join(tmpHome, oldConfigfile) 210 js := `{"https://index.docker.io/v1/":{"auth":"test","email":"user@example.com"}}` 211 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 212 t.Fatal(err) 213 } 214 215 config, err := Load(tmpHome) 216 // Use Contains instead of == since the file name will change each time 217 if err == nil || !strings.Contains(err.Error(), "Invalid auth configuration file") { 218 t.Fatalf("Expected an error got : %v, %v", config, err) 219 } 220 } 221 222 func TestOldJSON(t *testing.T) { 223 tmpHome, err := ioutil.TempDir("", "config-test") 224 if err != nil { 225 t.Fatal(err) 226 } 227 defer os.RemoveAll(tmpHome) 228 229 homeKey := homedir.Key() 230 homeVal := homedir.Get() 231 232 defer func() { os.Setenv(homeKey, homeVal) }() 233 os.Setenv(homeKey, tmpHome) 234 235 fn := filepath.Join(tmpHome, oldConfigfile) 236 js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}` 237 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 238 t.Fatal(err) 239 } 240 241 config, err := Load(tmpHome) 242 if err != nil { 243 t.Fatalf("Failed loading on empty json file: %q", err) 244 } 245 246 ac := config.AuthConfigs["https://index.docker.io/v1/"] 247 if ac.Username != "joejoe" || ac.Password != "hello" { 248 t.Fatalf("Missing data from parsing:\n%q", config) 249 } 250 251 // Now save it and make sure it shows up in new form 252 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 253 254 expConfStr := `{ 255 "auths": { 256 "https://index.docker.io/v1/": { 257 "auth": "am9lam9lOmhlbGxv", 258 "email": "user@example.com" 259 } 260 } 261 }` 262 263 if configStr != expConfStr { 264 t.Fatalf("Should have save in new form: \n'%s'\n not \n'%s'\n", configStr, expConfStr) 265 } 266 } 267 268 func TestNewJSON(t *testing.T) { 269 tmpHome, err := ioutil.TempDir("", "config-test") 270 if err != nil { 271 t.Fatal(err) 272 } 273 defer os.RemoveAll(tmpHome) 274 275 fn := filepath.Join(tmpHome, ConfigFileName) 276 js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }` 277 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 278 t.Fatal(err) 279 } 280 281 config, err := Load(tmpHome) 282 if err != nil { 283 t.Fatalf("Failed loading on empty json file: %q", err) 284 } 285 286 ac := config.AuthConfigs["https://index.docker.io/v1/"] 287 if ac.Username != "joejoe" || ac.Password != "hello" { 288 t.Fatalf("Missing data from parsing:\n%q", config) 289 } 290 291 // Now save it and make sure it shows up in new form 292 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 293 294 expConfStr := `{ 295 "auths": { 296 "https://index.docker.io/v1/": { 297 "auth": "am9lam9lOmhlbGxv" 298 } 299 } 300 }` 301 302 if configStr != expConfStr { 303 t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr) 304 } 305 } 306 307 func TestNewJSONNoEmail(t *testing.T) { 308 tmpHome, err := ioutil.TempDir("", "config-test") 309 if err != nil { 310 t.Fatal(err) 311 } 312 defer os.RemoveAll(tmpHome) 313 314 fn := filepath.Join(tmpHome, ConfigFileName) 315 js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }` 316 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 317 t.Fatal(err) 318 } 319 320 config, err := Load(tmpHome) 321 if err != nil { 322 t.Fatalf("Failed loading on empty json file: %q", err) 323 } 324 325 ac := config.AuthConfigs["https://index.docker.io/v1/"] 326 if ac.Username != "joejoe" || ac.Password != "hello" { 327 t.Fatalf("Missing data from parsing:\n%q", config) 328 } 329 330 // Now save it and make sure it shows up in new form 331 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 332 333 expConfStr := `{ 334 "auths": { 335 "https://index.docker.io/v1/": { 336 "auth": "am9lam9lOmhlbGxv" 337 } 338 } 339 }` 340 341 if configStr != expConfStr { 342 t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr) 343 } 344 } 345 346 func TestJSONWithPsFormat(t *testing.T) { 347 tmpHome, err := ioutil.TempDir("", "config-test") 348 if err != nil { 349 t.Fatal(err) 350 } 351 defer os.RemoveAll(tmpHome) 352 353 fn := filepath.Join(tmpHome, ConfigFileName) 354 js := `{ 355 "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } }, 356 "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}" 357 }` 358 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 359 t.Fatal(err) 360 } 361 362 config, err := Load(tmpHome) 363 if err != nil { 364 t.Fatalf("Failed loading on empty json file: %q", err) 365 } 366 367 if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` { 368 t.Fatalf("Unknown ps format: %s\n", config.PsFormat) 369 } 370 371 // Now save it and make sure it shows up in new form 372 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 373 if !strings.Contains(configStr, `"psFormat":`) || 374 !strings.Contains(configStr, "{{.ID}}") { 375 t.Fatalf("Should have save in new form: %s", configStr) 376 } 377 } 378 379 func TestJSONWithCredentialStore(t *testing.T) { 380 tmpHome, err := ioutil.TempDir("", "config-test") 381 if err != nil { 382 t.Fatal(err) 383 } 384 defer os.RemoveAll(tmpHome) 385 386 fn := filepath.Join(tmpHome, ConfigFileName) 387 js := `{ 388 "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } }, 389 "credsStore": "crazy-secure-storage" 390 }` 391 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 392 t.Fatal(err) 393 } 394 395 config, err := Load(tmpHome) 396 if err != nil { 397 t.Fatalf("Failed loading on empty json file: %q", err) 398 } 399 400 if config.CredentialsStore != "crazy-secure-storage" { 401 t.Fatalf("Unknown credential store: %s\n", config.CredentialsStore) 402 } 403 404 // Now save it and make sure it shows up in new form 405 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 406 if !strings.Contains(configStr, `"credsStore":`) || 407 !strings.Contains(configStr, "crazy-secure-storage") { 408 t.Fatalf("Should have save in new form: %s", configStr) 409 } 410 } 411 412 func TestJSONWithCredentialHelpers(t *testing.T) { 413 tmpHome, err := ioutil.TempDir("", "config-test") 414 if err != nil { 415 t.Fatal(err) 416 } 417 defer os.RemoveAll(tmpHome) 418 419 fn := filepath.Join(tmpHome, ConfigFileName) 420 js := `{ 421 "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } }, 422 "credHelpers": { "images.io": "images-io", "containers.com": "crazy-secure-storage" } 423 }` 424 if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil { 425 t.Fatal(err) 426 } 427 428 config, err := Load(tmpHome) 429 if err != nil { 430 t.Fatalf("Failed loading on empty json file: %q", err) 431 } 432 433 if config.CredentialHelpers == nil { 434 t.Fatal("config.CredentialHelpers was nil") 435 } else if config.CredentialHelpers["images.io"] != "images-io" || 436 config.CredentialHelpers["containers.com"] != "crazy-secure-storage" { 437 t.Fatalf("Credential helpers not deserialized properly: %v\n", config.CredentialHelpers) 438 } 439 440 // Now save it and make sure it shows up in new form 441 configStr := saveConfigAndValidateNewFormat(t, config, tmpHome) 442 if !strings.Contains(configStr, `"credHelpers":`) || 443 !strings.Contains(configStr, "images.io") || 444 !strings.Contains(configStr, "images-io") || 445 !strings.Contains(configStr, "containers.com") || 446 !strings.Contains(configStr, "crazy-secure-storage") { 447 t.Fatalf("Should have save in new form: %s", configStr) 448 } 449 } 450 451 // Save it and make sure it shows up in new form 452 func saveConfigAndValidateNewFormat(t *testing.T, config *configfile.ConfigFile, homeFolder string) string { 453 if err := config.Save(); err != nil { 454 t.Fatalf("Failed to save: %q", err) 455 } 456 457 buf, err := ioutil.ReadFile(filepath.Join(homeFolder, ConfigFileName)) 458 if err != nil { 459 t.Fatal(err) 460 } 461 if !strings.Contains(string(buf), `"auths":`) { 462 t.Fatalf("Should have save in new form: %s", string(buf)) 463 } 464 return string(buf) 465 } 466 467 func TestConfigDir(t *testing.T) { 468 tmpHome, err := ioutil.TempDir("", "config-test") 469 if err != nil { 470 t.Fatal(err) 471 } 472 defer os.RemoveAll(tmpHome) 473 474 if ConfigDir() == tmpHome { 475 t.Fatalf("Expected ConfigDir to be different than %s by default, but was the same", tmpHome) 476 } 477 478 // Update configDir 479 SetConfigDir(tmpHome) 480 481 if ConfigDir() != tmpHome { 482 t.Fatalf("Expected ConfigDir to %s, but was %s", tmpHome, ConfigDir()) 483 } 484 } 485 486 func TestConfigFile(t *testing.T) { 487 configFilename := "configFilename" 488 configFile := NewConfigFile(configFilename) 489 490 if configFile.Filename != configFilename { 491 t.Fatalf("Expected %s, got %s", configFilename, configFile.Filename) 492 } 493 } 494 495 func TestJSONReaderNoFile(t *testing.T) { 496 js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }` 497 498 config, err := LoadFromReader(strings.NewReader(js)) 499 if err != nil { 500 t.Fatalf("Failed loading on empty json file: %q", err) 501 } 502 503 ac := config.AuthConfigs["https://index.docker.io/v1/"] 504 if ac.Username != "joejoe" || ac.Password != "hello" { 505 t.Fatalf("Missing data from parsing:\n%q", config) 506 } 507 508 } 509 510 func TestOldJSONReaderNoFile(t *testing.T) { 511 js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}` 512 513 config, err := LegacyLoadFromReader(strings.NewReader(js)) 514 if err != nil { 515 t.Fatalf("Failed loading on empty json file: %q", err) 516 } 517 518 ac := config.AuthConfigs["https://index.docker.io/v1/"] 519 if ac.Username != "joejoe" || ac.Password != "hello" { 520 t.Fatalf("Missing data from parsing:\n%q", config) 521 } 522 } 523 524 func TestJSONWithPsFormatNoFile(t *testing.T) { 525 js := `{ 526 "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } }, 527 "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}" 528 }` 529 config, err := LoadFromReader(strings.NewReader(js)) 530 if err != nil { 531 t.Fatalf("Failed loading on empty json file: %q", err) 532 } 533 534 if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` { 535 t.Fatalf("Unknown ps format: %s\n", config.PsFormat) 536 } 537 538 } 539 540 func TestJSONSaveWithNoFile(t *testing.T) { 541 js := `{ 542 "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } }, 543 "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}" 544 }` 545 config, err := LoadFromReader(strings.NewReader(js)) 546 err = config.Save() 547 if err == nil { 548 t.Fatalf("Expected error. File should not have been able to save with no file name.") 549 } 550 551 tmpHome, err := ioutil.TempDir("", "config-test") 552 if err != nil { 553 t.Fatalf("Failed to create a temp dir: %q", err) 554 } 555 defer os.RemoveAll(tmpHome) 556 557 fn := filepath.Join(tmpHome, ConfigFileName) 558 f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 559 defer f.Close() 560 561 err = config.SaveToWriter(f) 562 if err != nil { 563 t.Fatalf("Failed saving to file: %q", err) 564 } 565 buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName)) 566 if err != nil { 567 t.Fatal(err) 568 } 569 expConfStr := `{ 570 "auths": { 571 "https://index.docker.io/v1/": { 572 "auth": "am9lam9lOmhlbGxv" 573 } 574 }, 575 "psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}" 576 }` 577 if string(buf) != expConfStr { 578 t.Fatalf("Should have save in new form: \n%s\nnot \n%s", string(buf), expConfStr) 579 } 580 } 581 582 func TestLegacyJSONSaveWithNoFile(t *testing.T) { 583 584 js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}` 585 config, err := LegacyLoadFromReader(strings.NewReader(js)) 586 err = config.Save() 587 if err == nil { 588 t.Fatalf("Expected error. File should not have been able to save with no file name.") 589 } 590 591 tmpHome, err := ioutil.TempDir("", "config-test") 592 if err != nil { 593 t.Fatalf("Failed to create a temp dir: %q", err) 594 } 595 defer os.RemoveAll(tmpHome) 596 597 fn := filepath.Join(tmpHome, ConfigFileName) 598 f, _ := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 599 defer f.Close() 600 601 if err = config.SaveToWriter(f); err != nil { 602 t.Fatalf("Failed saving to file: %q", err) 603 } 604 buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName)) 605 if err != nil { 606 t.Fatal(err) 607 } 608 609 expConfStr := `{ 610 "auths": { 611 "https://index.docker.io/v1/": { 612 "auth": "am9lam9lOmhlbGxv", 613 "email": "user@example.com" 614 } 615 } 616 }` 617 618 if string(buf) != expConfStr { 619 t.Fatalf("Should have save in new form: \n%s\n not \n%s", string(buf), expConfStr) 620 } 621 }