github.com/greenboxal/deis@v1.12.1/deisctl/cmd/cmd_test.go (about) 1 package cmd 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "reflect" 11 "strings" 12 "sync" 13 "testing" 14 15 "github.com/deis/deis/deisctl/backend" 16 "github.com/deis/deis/deisctl/config" 17 "github.com/deis/deis/deisctl/config/model" 18 "github.com/deis/deis/deisctl/test/mock" 19 "github.com/deis/deis/deisctl/units" 20 ) 21 22 type backendStub struct { 23 startedUnits []string 24 stoppedUnits []string 25 installedUnits []string 26 uninstalledUnits []string 27 restartedUnits []string 28 expected bool 29 } 30 31 func (backend *backendStub) Create(targets []string, wg *sync.WaitGroup, out, ew io.Writer) { 32 backend.installedUnits = append(backend.installedUnits, targets...) 33 } 34 func (backend *backendStub) Destroy(targets []string, wg *sync.WaitGroup, out, ew io.Writer) { 35 backend.uninstalledUnits = append(backend.uninstalledUnits, targets...) 36 } 37 func (backend *backendStub) Start(targets []string, wg *sync.WaitGroup, out, ew io.Writer) { 38 backend.startedUnits = append(backend.startedUnits, targets...) 39 } 40 func (backend *backendStub) Stop(targets []string, wg *sync.WaitGroup, out, ew io.Writer) { 41 backend.stoppedUnits = append(backend.stoppedUnits, targets...) 42 } 43 func (backend *backendStub) Scale(component string, num int, wg *sync.WaitGroup, out, ew io.Writer) { 44 switch { 45 case component == "router" && num == 3: 46 backend.expected = true 47 case component == "registry" && num == 4: 48 backend.expected = true 49 default: 50 backend.expected = false 51 } 52 } 53 func (backend *backendStub) RollingRestart(target string, wg *sync.WaitGroup, out, ew io.Writer) { 54 backend.restartedUnits = append(backend.restartedUnits, target) 55 } 56 57 func (backend *backendStub) ListMachines() error { 58 return nil 59 } 60 61 func (backend *backendStub) ListUnits() error { 62 return nil 63 } 64 func (backend *backendStub) ListUnitFiles() error { 65 return nil 66 } 67 func (backend *backendStub) Status(target string) error { 68 if target == "controller" || target == "builder" { 69 return nil 70 } 71 return errors.New("Test Error") 72 } 73 func (backend *backendStub) Journal(target string) error { 74 if target == "controller" || target == "builder" { 75 return nil 76 } 77 return errors.New("Test Error") 78 } 79 func (backend *backendStub) SSH(target string) error { 80 if target == "controller" { 81 return nil 82 } 83 return errors.New("Error") 84 } 85 func (backend *backendStub) SSHExec(target, command string) error { 86 if target == "controller" && command == "sh" { 87 return nil 88 } 89 return errors.New("Error") 90 } 91 92 func (backend *backendStub) Dock(target string, command []string) error { 93 return nil 94 } 95 96 var _ backend.Backend = &backendStub{} 97 98 func fakeCheckKeys(cb config.Backend) error { 99 return nil 100 } 101 102 type fakeHTTPServer struct{} 103 104 func (fakeHTTPServer) ServeHTTP(res http.ResponseWriter, req *http.Request) { 105 106 if strings.Split(req.URL.Path, "/")[1] != "v1.7.2" { 107 res.WriteHeader(http.StatusNotFound) 108 } 109 110 res.Write([]byte("test")) 111 } 112 113 func TestRefreshUnits(t *testing.T) { 114 t.Parallel() 115 116 name, err := ioutil.TempDir("", "deisctl") 117 118 if err != nil { 119 t.Error(err) 120 } 121 122 handler := fakeHTTPServer{} 123 server := httptest.NewServer(handler) 124 defer server.Close() 125 126 err = RefreshUnits(name, "v1.7.2", server.URL+"/") 127 128 if err != nil { 129 t.Error(err) 130 } 131 132 files, err := ioutil.ReadDir(name) 133 134 // There will be a "decorators" subdirectory and that shouldn't be 135 // counted as a unit when making the upcoming assertion. 136 numFiles := len(files) - 1 137 138 if len(units.Names) != numFiles { 139 t.Error(fmt.Errorf("Expected %d units, Got %d", len(units.Names), numFiles)) 140 } 141 142 for _, unit := range units.Names { 143 found := false 144 145 for _, file := range files { 146 if unit+".service" == file.Name() { 147 found = true 148 } 149 } 150 151 if found == false { 152 t.Error(fmt.Errorf("Expected to find %s in %v", unit, files)) 153 } 154 } 155 } 156 157 func TestRefreshUnitsError(t *testing.T) { 158 t.Parallel() 159 160 name, err := ioutil.TempDir("", "deisctl") 161 162 if err != nil { 163 t.Error(err) 164 } 165 166 handler := fakeHTTPServer{} 167 server := httptest.NewServer(handler) 168 defer server.Close() 169 170 err = RefreshUnits(name, "foo", server.URL+"/") 171 result := err.Error() 172 expected := "404 Not Found" 173 174 if result != expected { 175 t.Error(fmt.Errorf("Expected %s, Got %s", expected, result)) 176 } 177 } 178 179 func TestListUnits(t *testing.T) { 180 t.Parallel() 181 182 b := backendStub{installedUnits: []string{"router@1", "router@2"}} 183 184 if ListUnits(&b) != nil { 185 t.Error("unexpected error") 186 } 187 } 188 189 func TestListUnitFiles(t *testing.T) { 190 t.Parallel() 191 192 b := backendStub{} 193 194 if ListUnitFiles(&b) != nil { 195 t.Error("unexpected error") 196 } 197 } 198 199 func TestScaling(t *testing.T) { 200 t.Parallel() 201 202 b := backendStub{expected: false} 203 scale := []string{"registry=4", "router=3"} 204 205 Scale(scale, &b) 206 207 if b.expected == false { 208 t.Error("b.Scale called with unexpected arguements") 209 } 210 } 211 212 func TestScalingNonScalableComponent(t *testing.T) { 213 t.Parallel() 214 215 b := backendStub{} 216 expected := "cannot scale controller component" 217 err := Scale([]string{"controller=2"}, &b).Error() 218 219 if err != expected { 220 t.Error(fmt.Errorf("Expected '%v', Got '%v'", expected, err)) 221 } 222 } 223 224 func TestScalingInvalidFormat(t *testing.T) { 225 t.Parallel() 226 227 b := backendStub{} 228 expected := "Could not parse: controller2" 229 err := Scale([]string{"controller2"}, &b).Error() 230 231 if err != expected { 232 t.Error(fmt.Errorf("Expected '%v', Got '%v'", expected, err)) 233 } 234 } 235 236 func TestStart(t *testing.T) { 237 t.Parallel() 238 239 b := backendStub{} 240 expected := []string{"router@1", "router@2"} 241 242 Start(expected, &b) 243 244 if !reflect.DeepEqual(b.startedUnits, expected) { 245 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.startedUnits)) 246 } 247 } 248 249 func TestStartPlatform(t *testing.T) { 250 t.Parallel() 251 252 b := backendStub{} 253 expected := []string{"store-monitor", "store-daemon", "store-metadata", "store-gateway@*", 254 "store-volume", "logger", "logspout", "database", "registry@*", "controller", 255 "builder", "publisher", "router@*", "database", "registry@*", "controller", 256 "builder", "publisher", "router@*"} 257 258 Start([]string{"platform"}, &b) 259 260 if !reflect.DeepEqual(b.startedUnits, expected) { 261 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.startedUnits)) 262 } 263 } 264 265 func TestStartStatelessPlatform(t *testing.T) { 266 t.Parallel() 267 268 b := backendStub{} 269 expected := []string{"logger", "logspout", "registry@*", "controller", 270 "builder", "publisher", "router@*", "registry@*", "controller", 271 "builder", "publisher", "router@*"} 272 273 Start([]string{"stateless-platform"}, &b) 274 275 if !reflect.DeepEqual(b.startedUnits, expected) { 276 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.startedUnits)) 277 } 278 } 279 280 func TestStartSwarm(t *testing.T) { 281 t.Parallel() 282 283 b := backendStub{} 284 expected := []string{"swarm-manager", "swarm-node"} 285 286 Start([]string{"swarm"}, &b) 287 288 if !reflect.DeepEqual(b.startedUnits, expected) { 289 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.startedUnits)) 290 } 291 } 292 293 func TestRollingRestart(t *testing.T) { 294 t.Parallel() 295 296 b := backendStub{} 297 expected := []string{"router"} 298 299 RollingRestart("router", &b) 300 301 if !reflect.DeepEqual(b.restartedUnits, expected) { 302 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.restartedUnits)) 303 } 304 } 305 306 func TestUpgradePrep(t *testing.T) { 307 t.Parallel() 308 309 b := backendStub{} 310 expected := []string{"database", "registry@*", "controller", "builder", "logger", "logspout", "store-volume", 311 "store-gateway@*", "store-metadata", "store-daemon", "store-monitor"} 312 313 UpgradePrep(false, &b) 314 315 if !reflect.DeepEqual(b.stoppedUnits, expected) { 316 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 317 } 318 } 319 320 func TestStatelessUpgradePrep(t *testing.T) { 321 t.Parallel() 322 323 b := backendStub{} 324 expected := []string{"database", "registry@*", "controller", "builder", "logger", "logspout"} 325 326 UpgradePrep(true, &b) 327 328 if !reflect.DeepEqual(b.stoppedUnits, expected) { 329 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 330 } 331 } 332 333 func TestUpgradeTakeover(t *testing.T) { 334 t.Parallel() 335 testMock := mock.ConfigBackend{Expected: []*model.ConfigNode{{Key: "/deis/services/app1", Value: "foo", TTL: 10}, 336 {Key: "/deis/services/app2", Value: "8000", TTL: 10}}} 337 338 b := backendStub{} 339 expectedRestarted := []string{"router"} 340 expectedStarted := []string{"publisher", "store-monitor", "store-daemon", "store-metadata", 341 "store-gateway@*", "store-volume", "logger", "logspout", "database", "registry@*", 342 "controller", "builder", "publisher", "database", "registry@*", 343 "controller", "builder", "publisher"} 344 345 if err := doUpgradeTakeOver(false, &b, testMock); err != nil { 346 t.Error(fmt.Errorf("Takeover failed: %v", err)) 347 } 348 349 if !reflect.DeepEqual(b.restartedUnits, expectedRestarted) { 350 t.Error(fmt.Errorf("Expected %v, Got %v", expectedRestarted, b.restartedUnits)) 351 } 352 if !reflect.DeepEqual(b.startedUnits, expectedStarted) { 353 t.Error(fmt.Errorf("Expected %v, Got %v", expectedStarted, b.startedUnits)) 354 } 355 } 356 357 func TestStatelessUpgradeTakeover(t *testing.T) { 358 t.Parallel() 359 testMock := mock.ConfigBackend{Expected: []*model.ConfigNode{{Key: "/deis/services/app1", Value: "foo", TTL: 10}, 360 {Key: "/deis/services/app2", Value: "8000", TTL: 10}}} 361 362 b := backendStub{} 363 expectedRestarted := []string{"router"} 364 expectedStarted := []string{"publisher", "logspout", "registry@*", 365 "controller", "builder", "publisher", "router@*", "registry@*", 366 "controller", "builder", "publisher"} 367 368 if err := doUpgradeTakeOver(true, &b, testMock); err != nil { 369 t.Error(fmt.Errorf("Takeover failed: %v", err)) 370 } 371 372 if !reflect.DeepEqual(b.restartedUnits, expectedRestarted) { 373 t.Error(fmt.Errorf("Expected %v, Got %v", expectedRestarted, b.restartedUnits)) 374 } 375 if !reflect.DeepEqual(b.startedUnits, expectedStarted) { 376 t.Error(fmt.Errorf("Expected %v, Got %v", expectedStarted, b.startedUnits)) 377 } 378 } 379 380 func TestStop(t *testing.T) { 381 t.Parallel() 382 383 b := backendStub{} 384 expected := []string{"router@1", "router@2"} 385 Stop(expected, &b) 386 387 if !reflect.DeepEqual(b.stoppedUnits, expected) { 388 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 389 } 390 } 391 392 func TestStopPlatform(t *testing.T) { 393 t.Parallel() 394 395 b := backendStub{} 396 expected := []string{"router@*", "publisher", "controller", "builder", "database", 397 "registry@*", "logger", "logspout", "store-volume", "store-gateway@*", 398 "store-metadata", "store-daemon", "store-monitor"} 399 Stop([]string{"platform"}, &b) 400 401 if !reflect.DeepEqual(b.stoppedUnits, expected) { 402 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 403 } 404 } 405 406 func TestStopStatelessPlatform(t *testing.T) { 407 t.Parallel() 408 409 b := backendStub{} 410 expected := []string{"router@*", "publisher", "controller", "builder", 411 "registry@*", "logspout"} 412 Stop([]string{"stateless-platform"}, &b) 413 414 if !reflect.DeepEqual(b.stoppedUnits, expected) { 415 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 416 } 417 } 418 419 func TestStopSwarm(t *testing.T) { 420 t.Parallel() 421 422 b := backendStub{} 423 expected := []string{"swarm-node", "swarm-manager"} 424 Stop([]string{"swarm"}, &b) 425 426 if !reflect.DeepEqual(b.stoppedUnits, expected) { 427 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 428 } 429 } 430 431 func TestRestart(t *testing.T) { 432 t.Parallel() 433 434 b := backendStub{} 435 expected := []string{"router@4", "router@5"} 436 437 Restart(expected, &b) 438 439 if !reflect.DeepEqual(b.stoppedUnits, expected) { 440 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.stoppedUnits)) 441 } 442 if !reflect.DeepEqual(b.startedUnits, expected) { 443 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.startedUnits)) 444 } 445 } 446 447 func TestSSH(t *testing.T) { 448 t.Parallel() 449 450 b := backendStub{} 451 err := SSH("controller", []string{}, &b) 452 453 if err != nil { 454 t.Error(err) 455 } 456 } 457 func TestSSHExec(t *testing.T) { 458 t.Parallel() 459 460 b := backendStub{} 461 err := SSH("controller", []string{"sh"}, &b) 462 463 if err != nil { 464 t.Error(err) 465 } 466 } 467 468 func TestSSHError(t *testing.T) { 469 t.Parallel() 470 471 b := backendStub{} 472 err := SSH("registry", []string{}, &b) 473 474 if err == nil { 475 t.Error("Error expected") 476 } 477 } 478 479 func TestStatus(t *testing.T) { 480 t.Parallel() 481 482 b := backendStub{} 483 484 if Status([]string{"controller", "builder"}, &b) != nil { 485 t.Error("Unexpected Error") 486 } 487 } 488 489 func TestStatusError(t *testing.T) { 490 t.Parallel() 491 492 b := backendStub{} 493 494 expected := "Test Error" 495 err := Status([]string{"blah"}, &b).Error() 496 497 if err != expected { 498 t.Error(fmt.Errorf("Expected '%v', Got '%v'", expected, err)) 499 } 500 } 501 502 func TestJournal(t *testing.T) { 503 t.Parallel() 504 505 b := backendStub{} 506 507 if Journal([]string{"controller", "builder"}, &b) != nil { 508 t.Error("Unexpected Error") 509 } 510 } 511 512 func TestJournalError(t *testing.T) { 513 t.Parallel() 514 515 b := backendStub{} 516 517 expected := "Test Error" 518 err := Journal([]string{"blah"}, &b).Error() 519 520 if err != expected { 521 t.Error(fmt.Errorf("Expected '%v', Got '%v'", expected, err)) 522 } 523 } 524 525 func TestInstall(t *testing.T) { 526 t.Parallel() 527 528 b := backendStub{} 529 cb := mock.ConfigBackend{} 530 531 expected := []string{"router@1", "router@2"} 532 533 Install(expected, &b, &cb, fakeCheckKeys) 534 535 if !reflect.DeepEqual(b.installedUnits, expected) { 536 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.installedUnits)) 537 } 538 } 539 540 func TestInstallPlatform(t *testing.T) { 541 t.Parallel() 542 543 b := backendStub{} 544 cb := mock.ConfigBackend{} 545 546 expected := []string{"store-daemon", "store-monitor", "store-metadata", "store-volume", 547 "store-gateway@1", "logger", "logspout", "database", "registry@1", 548 "controller", "builder", "publisher", "router@1", "router@2", "router@3"} 549 550 Install([]string{"platform"}, &b, &cb, fakeCheckKeys) 551 552 if !reflect.DeepEqual(b.installedUnits, expected) { 553 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.installedUnits)) 554 } 555 } 556 557 func TestInstallPlatformWithCustomRouterMeshSize(t *testing.T) { 558 t.Parallel() 559 560 b := backendStub{} 561 cb := mock.ConfigBackend{} 562 563 expected := []string{"store-daemon", "store-monitor", "store-metadata", "store-volume", 564 "store-gateway@1", "logger", "logspout", "database", "registry@1", 565 "controller", "builder", "publisher", "router@1", "router@2", "router@3", "router@4", "router@5"} 566 RouterMeshSize = 5 567 568 Install([]string{"platform"}, &b, &cb, fakeCheckKeys) 569 RouterMeshSize = DefaultRouterMeshSize 570 571 if !reflect.DeepEqual(b.installedUnits, expected) { 572 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.installedUnits)) 573 } 574 } 575 576 func TestInstallStatelessPlatform(t *testing.T) { 577 t.Parallel() 578 579 b := backendStub{} 580 cb := mock.ConfigBackend{} 581 582 expected := []string{"logger", "logspout", "registry@1", 583 "controller", "builder", "publisher", "router@1", "router@2", "router@3"} 584 585 Install([]string{"stateless-platform"}, &b, &cb, fakeCheckKeys) 586 587 if !reflect.DeepEqual(b.installedUnits, expected) { 588 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.installedUnits)) 589 } 590 } 591 592 func TestInstallSwarm(t *testing.T) { 593 t.Parallel() 594 595 b := backendStub{} 596 cb := mock.ConfigBackend{} 597 598 expected := []string{"swarm-manager", "swarm-node"} 599 600 Install([]string{"swarm"}, &b, &cb, fakeCheckKeys) 601 602 if !reflect.DeepEqual(b.installedUnits, expected) { 603 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.installedUnits)) 604 } 605 } 606 607 func TestUninstall(t *testing.T) { 608 t.Parallel() 609 610 b := backendStub{} 611 expected := []string{"router@3", "router@4"} 612 613 Uninstall(expected, &b) 614 615 if !reflect.DeepEqual(b.uninstalledUnits, expected) { 616 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.uninstalledUnits)) 617 } 618 } 619 620 func TestUninstallPlatform(t *testing.T) { 621 t.Parallel() 622 623 b := backendStub{} 624 expected := []string{"router@*", "publisher", "controller", "builder", "database", 625 "registry@*", "logger", "logspout", "store-volume", "store-gateway@*", 626 "store-metadata", "store-daemon", "store-monitor"} 627 628 Uninstall([]string{"platform"}, &b) 629 630 if !reflect.DeepEqual(b.uninstalledUnits, expected) { 631 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.uninstalledUnits)) 632 } 633 } 634 635 func TestUninstallStatelessPlatform(t *testing.T) { 636 t.Parallel() 637 638 b := backendStub{} 639 expected := []string{"router@*", "publisher", "controller", "builder", 640 "registry@*", "logspout"} 641 642 Uninstall([]string{"stateless-platform"}, &b) 643 644 if !reflect.DeepEqual(b.uninstalledUnits, expected) { 645 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.uninstalledUnits)) 646 } 647 } 648 649 func TestUninstallSwarm(t *testing.T) { 650 t.Parallel() 651 652 b := backendStub{} 653 expected := []string{"swarm-node", "swarm-manager"} 654 655 Uninstall([]string{"swarm"}, &b) 656 657 if !reflect.DeepEqual(b.uninstalledUnits, expected) { 658 t.Error(fmt.Errorf("Expected %v, Got %v", expected, b.uninstalledUnits)) 659 } 660 }