shelly 0.0.43 → 0.0.44.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,21 +24,23 @@ describe Shelly::CLI::Main do
24
24
  it "should display available commands" do
25
25
  expected = <<-OUT
26
26
  Tasks:
27
- shelly add # Adds new cloud to Shelly Cloud
28
- shelly backup <command> # Manages database backups from this cloud
29
- shelly config <command> # Manages cloud configuration files
30
- shelly delete # Delete cloud from Shelly Cloud
31
- shelly deploys <command> # View cloud deploy logs
27
+ shelly add # Add a new cloud
28
+ shelly backup <command> # Manage database backups
29
+ shelly config <command> # Manage application configuration files
30
+ shelly delete # Delete the cloud
31
+ shelly deploys <command> # View deploy logs
32
32
  shelly help [TASK] # Describe available tasks or one specific task
33
- shelly ip # Lists clouds IP's
34
- shelly list # Lists all your clouds
35
- shelly login [EMAIL] # Logs user in to Shelly Cloud
36
- shelly logs # Show latest application logs from each instance
37
- shelly register [EMAIL] # Registers new user account on Shelly Cloud
38
- shelly start # Starts the cloud
39
- shelly stop # Stops the cloud
40
- shelly user <command> # Manages users using this cloud
41
- shelly version # Displays shelly version
33
+ shelly ip # List cloud's IP addresses
34
+ shelly list # List available clouds
35
+ shelly login [EMAIL] # Log into Shelly Cloud
36
+ shelly logout # Logout from Shelly Cloud
37
+ shelly logs # Show latest application logs
38
+ shelly redeploy # Redeploy application
39
+ shelly register [EMAIL] # Register new account
40
+ shelly start # Start the cloud
41
+ shelly stop # Stop the cloud
42
+ shelly user <command> # Manage collaborators
43
+ shelly version # Display shelly version
42
44
 
43
45
  Options:
44
46
  [--debug] # Show debug information
@@ -53,10 +55,10 @@ Usage:
53
55
  shelly logs
54
56
 
55
57
  Options:
56
- -c, [--cloud=CLOUD] # Specify which cloud to show logs for
58
+ -c, [--cloud=CLOUD] # Specify cloud
57
59
  [--debug] # Show debug information
58
60
 
59
- Show latest application logs from each instance
61
+ Show latest application logs
60
62
  OUT
61
63
  out = IO.popen("bin/shelly help logs").read.strip
62
64
  out.should == expected.strip
@@ -85,7 +87,7 @@ OUT
85
87
  end
86
88
 
87
89
  it "should check ssh key in database" do
88
- @user.stub(:ssh_key_registered?).and_raise(RestClient::Conflict)
90
+ @user.stub(:ssh_key_registered?).and_raise(Shelly::Client::ConflictException.new)
89
91
  $stdout.should_receive(:puts).with("\e[31mUser with your ssh key already exists.\e[0m")
90
92
  $stdout.should_receive(:puts).with("\e[31mYou can login using: shelly login [EMAIL]\e[0m")
91
93
  lambda {
@@ -172,8 +174,8 @@ OUT
172
174
 
173
175
  context "on unsuccessful registration" do
174
176
  it "should display errors and exit with 1" do
175
- response = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]}
176
- exception = Shelly::Client::APIError.new(422, response)
177
+ body = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]}
178
+ exception = Shelly::Client::ValidationException.new(body)
177
179
  @client.stub(:register_user).and_raise(exception)
178
180
  $stdout.should_receive(:puts).with("\e[31mEmail has been already taken\e[0m")
179
181
  lambda {
@@ -252,7 +254,7 @@ OUT
252
254
  context "on unauthorized user" do
253
255
  it "should exit with 1 and display error message" do
254
256
  response = {"message" => "Unauthorized", "url" => "https://admin.winniecloud.com/users/password/new"}
255
- exception = Shelly::Client::APIError.new(401, response)
257
+ exception = Shelly::Client::UnauthorizedException.new(response)
256
258
  @client.stub(:token).and_raise(exception)
257
259
  $stdout.should_receive(:puts).with("\e[31mWrong email or password\e[0m")
258
260
  $stdout.should_receive(:puts).with("\e[31mYou can reset password by using link:\e[0m")
@@ -281,6 +283,7 @@ OUT
281
283
  @client.stub(:token).and_return("abc")
282
284
  end
283
285
 
286
+ # This spec tests inside_git_repository? hook
284
287
  it "should exit with message if command run outside git repository" do
285
288
  Shelly::App.stub(:inside_git_repository?).and_return(false)
286
289
  $stdout.should_receive(:puts).with("\e[31mMust be run inside your project git repository\e[0m")
@@ -291,8 +294,19 @@ OUT
291
294
  }.should raise_error(SystemExit)
292
295
  end
293
296
 
294
- context "command line options" do
297
+ # This spec tests logged_in? hook
298
+ it "should exit with message if user is not logged in" do
299
+ exception = Shelly::Client::UnauthorizedException.new
300
+ @client.stub(:token).and_raise(exception)
301
+ $stdout.should_receive(:puts).with(red "You are not logged in. To log in use: `shelly login`")
302
+ lambda {
303
+ fake_stdin(["", ""]) do
304
+ invoke(@main, :add)
305
+ end
306
+ }.should raise_error(SystemExit)
307
+ end
295
308
 
309
+ context "command line options" do
296
310
  context "invalid params" do
297
311
  it "should show help and exit if not all options are passed" do
298
312
  $stdout.should_receive(:puts).with("\e[31mTry 'shelly help add' for more information\e[0m")
@@ -363,6 +377,15 @@ OUT
363
377
  end
364
378
  end
365
379
 
380
+ context "when user provided 'none' database" do
381
+ it "shouldn't take it into account" do
382
+ @app.should_receive(:databases=).with(["postgresql"])
383
+ fake_stdin(["", "postgresql, none"]) do
384
+ invoke(@main, :add)
385
+ end
386
+ end
387
+ end
388
+
366
389
  it "should create the app on shelly cloud" do
367
390
  @app.should_receive(:create)
368
391
  fake_stdin(["", ""]) do
@@ -371,8 +394,8 @@ OUT
371
394
  end
372
395
 
373
396
  it "should display validation errors if they are any" do
374
- response = {"message" => "Validation Failed", "errors" => [["code_name", "has been already taken"]]}
375
- exception = Shelly::Client::APIError.new(422, response)
397
+ body = {"message" => "Validation Failed", "errors" => [["code_name", "has been already taken"]]}
398
+ exception = Shelly::Client::ValidationException.new(body)
376
399
  @app.should_receive(:create).and_raise(exception)
377
400
  $stdout.should_receive(:puts).with("\e[31mCode name has been already taken\e[0m")
378
401
  $stdout.should_receive(:puts).with("\e[31mFix erros in the below command and type it again to create your cloud\e[0m")
@@ -439,6 +462,10 @@ OUT
439
462
  Shelly::User.stub(:new).and_return(@user)
440
463
  end
441
464
 
465
+ it "should ensure user has logged in" do
466
+ hooks(@main, :list).should include(:logged_in?)
467
+ end
468
+
442
469
  it "should display user's clouds" do
443
470
  $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m")
444
471
  $stdout.should_receive(:puts).with(/abc\s+\| running/)
@@ -457,18 +484,6 @@ OUT
457
484
  $stdout.should_receive(:puts).with("\e[32mYou have no clouds yet\e[0m")
458
485
  invoke(@main, :status)
459
486
  end
460
-
461
- context "on failure" do
462
- it "should display info that user is not logged in" do
463
- error = Shelly::Client::APIError.new(401)
464
- @client.stub(:token).and_raise(error)
465
- $stdout.should_receive(:puts).with(red "You are not logged in. To log in use:")
466
- $stdout.should_receive(:puts).with(" shelly login")
467
- lambda {
468
- invoke(@main, :list)
469
- }.should raise_error(SystemExit)
470
- end
471
- end
472
487
  end
473
488
 
474
489
  describe "#start" do
@@ -484,6 +499,7 @@ OUT
484
499
  Shelly::App.stub(:new).and_return(@app)
485
500
  end
486
501
 
502
+ # This spec tests cloudfile_present? hook
487
503
  it "should exit if there is no Cloudfile" do
488
504
  File.delete("Cloudfile")
489
505
  $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
@@ -492,22 +508,17 @@ OUT
492
508
  }.should raise_error(SystemExit)
493
509
  end
494
510
 
511
+ it "should ensure user has logged in" do
512
+ hooks(@main, :start).should include(:logged_in?)
513
+ end
514
+
495
515
  it "should exit if user doesn't have access to clouds in Cloudfile" do
496
- response = {"message" => "Couldn't find Cloud with"}
497
- exception = Shelly::Client::APIError.new(404, response)
516
+ exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
498
517
  @client.stub(:start_cloud).and_raise(exception)
499
518
  $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
500
519
  lambda { invoke(@main, :start) }.should raise_error(SystemExit)
501
520
  end
502
521
 
503
- it "should exit if user is not logged in" do
504
- exception = Shelly::Client::APIError.new(401)
505
- @client.stub(:token).and_raise(exception)
506
- $stdout.should_receive(:puts).with(red "You are not logged in. To log in use:")
507
- $stdout.should_receive(:puts).with(" shelly login")
508
- lambda { invoke(@main, :start) }.should raise_error(SystemExit)
509
- end
510
-
511
522
  context "single cloud in Cloudfile" do
512
523
  it "should start the cloud" do
513
524
  @client.stub(:start_cloud)
@@ -523,8 +534,8 @@ OUT
523
534
  end
524
535
 
525
536
  it "should show information to start specific cloud and exit" do
526
- $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to start using:")
527
- $stdout.should_receive(:puts).with(" shelly start --cloud foo-production")
537
+ $stdout.should_receive(:puts).with(red "You have multiple clouds in Cloudfile.")
538
+ $stdout.should_receive(:puts).with("Select cloud using `shelly start --cloud foo-production`")
528
539
  $stdout.should_receive(:puts).with("Available clouds:")
529
540
  $stdout.should_receive(:puts).with(" * foo-production")
530
541
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -542,21 +553,21 @@ OUT
542
553
 
543
554
  context "on failure" do
544
555
  it "should show information that cloud is running" do
545
- raise_conflict(:state => "running")
556
+ raise_conflict("state" => "running")
546
557
  $stdout.should_receive(:puts).with(red "Not starting: cloud 'foo-production' is already running")
547
558
  lambda { invoke(@main, :start) }.should raise_error(SystemExit)
548
559
  end
549
560
 
550
561
  %w{deploying configuring}.each do |state|
551
562
  it "should show information that cloud is #{state}" do
552
- raise_conflict(:state => state)
563
+ raise_conflict("state" => state)
553
564
  $stdout.should_receive(:puts).with(red "Not starting: cloud 'foo-production' is currently deploying")
554
565
  lambda { invoke(@main, :start) }.should raise_error(SystemExit)
555
566
  end
556
567
  end
557
568
 
558
569
  it "should show information that cloud has no code" do
559
- raise_conflict(:state => "no_code")
570
+ raise_conflict("state" => "no_code")
560
571
  $stdout.should_receive(:puts).with(red "Not starting: no source code provided")
561
572
  $stdout.should_receive(:puts).with(red "Push source code using:")
562
573
  $stdout.should_receive(:puts).with(" git push production master")
@@ -565,24 +576,25 @@ OUT
565
576
 
566
577
  %w{deploy_failed configuration_failed}.each do |state|
567
578
  it "should show information that cloud #{state}" do
568
- raise_conflict(:state => state, :link => "http://example.com/logs")
579
+ raise_conflict("state" => state)
569
580
  $stdout.should_receive(:puts).with(red "Not starting: deployment failed")
570
581
  $stdout.should_receive(:puts).with(red "Support has been notified")
571
- $stdout.should_receive(:puts).with(red "See http://example.com/logs for reasons of failure")
582
+ $stdout.should_receive(:puts).
583
+ with(red "Check `shelly deploys show last --cloud foo-production` for reasons of failure")
572
584
  lambda { invoke(@main, :start) }.should raise_error(SystemExit)
573
585
  end
574
586
  end
587
+
575
588
  it "should open billing page" do
576
- raise_conflict(:state => "no_billing")
589
+ raise_conflict("state" => "no_billing")
577
590
  $stdout.should_receive(:puts).with(red "Please fill in billing details to start foo-production. Opening browser.")
578
591
  @app.should_receive(:open_billing_page)
579
592
  lambda { invoke(@main, :start) }.should raise_error(SystemExit)
580
593
  end
581
594
 
582
595
  def raise_conflict(options = {})
583
- options = {:state => "no_code"}.merge(options)
584
- exception = RestClient::Conflict.new
585
- exception.stub(:response).and_return(options.to_json)
596
+ body = {"state" => "no_code"}.merge(options)
597
+ exception = Shelly::Client::ConflictException.new(body)
586
598
  @client.stub(:start_cloud).and_raise(exception)
587
599
  end
588
600
  end
@@ -601,24 +613,17 @@ OUT
601
613
  Shelly::App.stub(:new).and_return(@app)
602
614
  end
603
615
 
604
- it "should exit if there is no Cloudfile" do
605
- File.delete("Cloudfile")
606
- $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
607
- lambda {
608
- invoke(@main, :stop)
609
- }.should raise_error(SystemExit)
616
+ it "should ensure user has logged in" do
617
+ hooks(@main, :stop).should include(:logged_in?)
610
618
  end
611
619
 
612
- it "should exit if user doesn't have access to clouds in Cloudfile" do
613
- @client.stub(:stop_cloud).and_raise(Shelly::Client::APIError.new(404))
614
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
615
- lambda { invoke(@main, :stop) }.should raise_error(SystemExit)
620
+ it "should ensure that Cloudfile is present" do
621
+ hooks(@main, :stop).should include(:cloudfile_present?)
616
622
  end
617
623
 
618
- it "should exit if user is not logged in" do
619
- @client.stub(:token).and_raise(Shelly::Client::APIError.new(401))
620
- $stdout.should_receive(:puts).with(red "You are not logged in. To log in use:")
621
- $stdout.should_receive(:puts).with(" shelly login")
624
+ it "should exit if user doesn't have access to clouds in Cloudfile" do
625
+ @client.stub(:stop_cloud).and_raise(Shelly::Client::NotFoundException.new("resource" => "cloud"))
626
+ $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
622
627
  lambda { invoke(@main, :stop) }.should raise_error(SystemExit)
623
628
  end
624
629
 
@@ -636,8 +641,8 @@ OUT
636
641
  end
637
642
 
638
643
  it "should show information to start specific cloud and exit" do
639
- $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to stop using:")
640
- $stdout.should_receive(:puts).with(" shelly stop --cloud foo-production")
644
+ $stdout.should_receive(:puts).with(red "You have multiple clouds in Cloudfile.")
645
+ $stdout.should_receive(:puts).with("Select cloud using `shelly stop --cloud foo-production`")
641
646
  $stdout.should_receive(:puts).with("Available clouds:")
642
647
  $stdout.should_receive(:puts).with(" * foo-production")
643
648
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -653,18 +658,18 @@ OUT
653
658
  end
654
659
  end
655
660
 
656
- describe "#ips" do
661
+ describe "#ip" do
657
662
  before do
658
663
  File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
659
- Shelly::App.stub(:inside_git_repository?).and_return(true)
664
+ @main.stub(:logged_in?).and_return(true)
660
665
  end
661
666
 
662
- it "should exit with message if there is no Cloudfile" do
663
- File.delete("Cloudfile")
664
- $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
665
- lambda {
666
- invoke(@main, :ip)
667
- }.should raise_error(SystemExit)
667
+ it "should ensure user has logged in" do
668
+ hooks(@main, :ip).should include(:logged_in?)
669
+ end
670
+
671
+ it "should ensure that Cloudfile is present" do
672
+ hooks(@main, :ip).should include(:cloudfile_present?)
668
673
  end
669
674
 
670
675
  context "on success" do
@@ -683,7 +688,7 @@ OUT
683
688
 
684
689
  context "on failure" do
685
690
  it "should raise an error if user does not have access to cloud" do
686
- exception = Shelly::Client::APIError.new(404, {"message" => "Cloud foo-staging not found"})
691
+ exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
687
692
  @client.stub(:app).and_raise(exception)
688
693
  $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
689
694
  invoke(@main, :ip)
@@ -702,6 +707,10 @@ OUT
702
707
  Shelly::App.stub(:new).and_return(@app)
703
708
  end
704
709
 
710
+ it "should ensure user has logged in" do
711
+ hooks(@main, :delete).should include(:logged_in?)
712
+ end
713
+
705
714
  context "when cloud is given" do
706
715
  before do
707
716
  File.open("Cloudfile", 'w') {|f|
@@ -758,8 +767,8 @@ OUT
758
767
  f.write("foo-staging:\n") }
759
768
  end
760
769
 
761
- it "should raise Client::APIError" do
762
- exception = Shelly::Client::APIError.new(404)
770
+ it "should raise Client::NotFoundException" do
771
+ exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
763
772
  @app.stub(:delete).and_raise(exception)
764
773
  $stdout.should_receive(:puts).with(red "You have no access to 'foo-bar' cloud defined in Cloudfile")
765
774
  lambda{
@@ -795,13 +804,46 @@ OUT
795
804
  end
796
805
  end
797
806
 
807
+ describe "#logout" do
808
+ before do
809
+ @user = Shelly::User.new
810
+ @client.stub(:token).and_return("abc")
811
+ Shelly::User.stub(:new).and_return(@user)
812
+ FileUtils.mkdir_p("~/.ssh")
813
+ FileUtils.mkdir_p("~/.shelly")
814
+ File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
815
+ File.open("~/.ssh/id_rsa.pub", "w") { |f| f << "ssh-key AAbbcc" }
816
+ @key_path = File.expand_path("~/.ssh/id_rsa.pub")
817
+ File.open("~/.shelly/credentials", "w") { |f| f << "megan@fox.pl\nsecret" }
818
+ @client.stub(:logout).and_return(true)
819
+ end
820
+
821
+ it "should ensure user has logged in" do
822
+ hooks(@main, :logout).should include(:logged_in?)
823
+ end
824
+
825
+ it "should logout from shelly cloud and show message" do
826
+ $stdout.should_receive(:puts).with("Your public SSH key has been removed from Shelly Cloud")
827
+ $stdout.should_receive(:puts).with("You have been successfully logged out")
828
+ invoke(@main, :logout)
829
+ File.exists?("~/.shelly/credentials").should be_false
830
+ end
831
+
832
+ it "should remove only credentiales when local ssh key doesn't exist" do
833
+ FileUtils.rm_rf(@key_path)
834
+ $stdout.should_receive(:puts).with("You have been successfully logged out")
835
+ invoke(@main, :logout)
836
+ File.exists?("~/.shelly/credentials").should be_false
837
+ end
838
+ end
839
+
798
840
  describe "#logs" do
799
841
  before do
800
842
  @user = Shelly::User.new
801
843
  @client.stub(:token).and_return("abc")
802
844
  FileUtils.mkdir_p("/projects/foo")
803
845
  Dir.chdir("/projects/foo")
804
- File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
846
+ File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
805
847
  Shelly::User.stub(:new).and_return(@user)
806
848
  @client.stub(:apps).and_return([{"code_name" => "foo-production"},
807
849
  {"code_name" => "foo-staging"}])
@@ -809,29 +851,19 @@ OUT
809
851
  Shelly::App.stub(:new).and_return(@app)
810
852
  end
811
853
 
812
- it "should exit if there is no Cloudfile" do
813
- File.delete("Cloudfile")
814
- $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
815
- lambda {
816
- invoke(@main, :logs)
817
- }.should raise_error(SystemExit)
854
+ it "should ensure user has logged in" do
855
+ hooks(@main, :logs).should include(:logged_in?)
818
856
  end
819
857
 
820
- it "should exit if user doesn't have access to clouds in Cloudfile" do
821
- response = {"message" => "Cloud foo-production not found"}
822
- exception = Shelly::Client::APIError.new(404, response)
823
- @client.stub(:application_logs).and_raise(exception)
824
- $stdout.should_receive(:puts).
825
- with(red "You have no access to cloud 'foo-production'")
826
- lambda { invoke(@main, :logs) }.should raise_error(SystemExit)
858
+ it "should ensure that Cloudfile is present" do
859
+ hooks(@main, :logs).should include(:cloudfile_present?)
827
860
  end
828
861
 
829
- it "should exit if user is not logged in" do
830
- exception = Shelly::Client::APIError.new(401)
831
- @client.stub(:token).and_raise(exception)
862
+ it "should exit if user doesn't have access to clouds in Cloudfile" do
863
+ exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
864
+ @client.stub(:application_logs).and_raise(exception)
832
865
  $stdout.should_receive(:puts).
833
- with(red "You are not logged in. To log in use:")
834
- $stdout.should_receive(:puts).with(" shelly login")
866
+ with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
835
867
  lambda { invoke(@main, :logs) }.should raise_error(SystemExit)
836
868
  end
837
869
 
@@ -852,9 +884,8 @@ OUT
852
884
  end
853
885
 
854
886
  it "should show information to print logs for specific cloud and exit" do
855
- $stdout.should_receive(:puts).
856
- with("You have multiple clouds in Cloudfile. Select which to show logs for using:")
857
- $stdout.should_receive(:puts).with(" shelly logs --cloud foo-production")
887
+ $stdout.should_receive(:puts).with(red "You have multiple clouds in Cloudfile.")
888
+ $stdout.should_receive(:puts).with("Select cloud using `shelly logs --cloud foo-production`")
858
889
  $stdout.should_receive(:puts).with("Available clouds:")
859
890
  $stdout.should_receive(:puts).with(" * foo-production")
860
891
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -884,4 +915,81 @@ OUT
884
915
  end
885
916
  end
886
917
  end
918
+
919
+ describe "#redeploy" do
920
+ before do
921
+ @user = Shelly::User.new
922
+ @client.stub(:token).and_return("abc")
923
+ @app = Shelly::App.new
924
+ Shelly::App.stub(:new).and_return(@app)
925
+ FileUtils.mkdir_p("/projects/foo")
926
+ Dir.chdir("/projects/foo")
927
+ File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
928
+ end
929
+
930
+ it "should redeploy the application" do
931
+ $stdout.should_receive(:puts).with(green "Redeploying your application for cloud 'foo-production'")
932
+ @app.should_receive(:redeploy)
933
+ invoke(@main, :redeploy)
934
+ end
935
+
936
+ context "on redeploy failure" do
937
+ %w(deploying configuring).each do |state|
938
+ context "when application is in #{state} state" do
939
+ it "should display error that deploy is in progress" do
940
+ exception = Shelly::Client::ConflictException.new("state" => state)
941
+ @client.should_receive(:redeploy).with("foo-production").and_raise(exception)
942
+ $stdout.should_receive(:puts).with(red "Your application is being redeployed at the moment")
943
+ lambda {
944
+ invoke(@main, :redeploy)
945
+ }.should raise_error(SystemExit)
946
+ end
947
+ end
948
+ end
949
+
950
+ %w(no_code no_billing turned_off).each do |state|
951
+ context "when application is in #{state} state" do
952
+ it "should display error that cloud is not running" do
953
+ exception = Shelly::Client::ConflictException.new("state" => state)
954
+ @client.should_receive(:redeploy).with("foo-production").and_raise(exception)
955
+ $stdout.should_receive(:puts).with(red "Cloud foo-production is not running")
956
+ $stdout.should_receive(:puts).with("Start your cloud with `shelly start --cloud foo-production`")
957
+ lambda {
958
+ invoke(@main, :redeploy)
959
+ }.should raise_error(SystemExit)
960
+ end
961
+ end
962
+ end
963
+
964
+ it "should re-raise exception on unknown state" do
965
+ exception = Shelly::Client::ConflictException.new("state" => "doing_something")
966
+ @client.should_receive(:redeploy).with("foo-production").and_raise(exception)
967
+ lambda {
968
+ invoke(@main, :redeploy)
969
+ }.should raise_error(Shelly::Client::ConflictException)
970
+ end
971
+ end
972
+
973
+ context "on multiple clouds in Cloudfile" do
974
+ before do
975
+ File.open("Cloudfile", 'w') { |f| f.write("foo-staging:\nfoo-production:\n") }
976
+ end
977
+
978
+ it "should show information to redeploy application for specific cloud and exit" do
979
+ $stdout.should_receive(:puts).with(red "You have multiple clouds in Cloudfile.")
980
+ $stdout.should_receive(:puts).with("Select cloud using `shelly redeploy --cloud foo-production`")
981
+ $stdout.should_receive(:puts).with("Available clouds:")
982
+ $stdout.should_receive(:puts).with(" * foo-production")
983
+ $stdout.should_receive(:puts).with(" * foo-staging")
984
+ lambda { invoke(@main, :redeploy) }.should raise_error(SystemExit)
985
+ end
986
+
987
+ it "should fetch from command line which cloud to redeploy application for" do
988
+ @client.should_receive(:redeploy).with("foo-staging")
989
+ $stdout.should_receive(:puts).with(green "Redeploying your application for cloud 'foo-staging'")
990
+ @main.options = {:cloud => "foo-staging"}
991
+ invoke(@main, :redeploy)
992
+ end
993
+ end
994
+ end
887
995
  end
@@ -22,7 +22,7 @@ describe Shelly::CLI::Runner do
22
22
  it "should be true if args include --debug option" do
23
23
  @runner.should be_debug
24
24
  end
25
-
25
+
26
26
  it "should be true if SHELLY_DEBUG is set to true" do
27
27
  runner = Shelly::CLI::Runner.new
28
28
  runner.should_not be_debug
@@ -42,6 +42,16 @@ describe Shelly::CLI::Runner do
42
42
  @runner.start
43
43
  end
44
44
 
45
+ it "should rescue interrupt exception and display message" do
46
+ Shelly::CLI::Main.stub(:start).and_raise(Interrupt.new)
47
+ runner = Shelly::CLI::Runner.new(%w(login))
48
+ $stdout.should_receive(:puts).with("\n")
49
+ $stdout.should_receive(:puts).with("[canceled]")
50
+ lambda {
51
+ runner.start
52
+ }.should raise_error(SystemExit)
53
+ end
54
+
45
55
  context "with --debug option (debug mode)" do
46
56
  it "should re-raise caught exception to the console" do
47
57
  Shelly::CLI::Main.stub(:start).and_raise(RuntimeError.new)
@@ -60,6 +70,24 @@ describe Shelly::CLI::Runner do
60
70
  runner.start
61
71
  }.should raise_error(SystemExit)
62
72
  end
73
+
74
+ it "should caught exception thrown by API Client" do
75
+ Shelly::CLI::Main.stub(:start).and_raise(Shelly::Client::APIException.new)
76
+ runner = Shelly::CLI::Runner.new(%w(version))
77
+ $stdout.should_receive(:puts).with("Unknown error, to see debug information run command with --debug")
78
+ lambda {
79
+ runner.start
80
+ }.should raise_error(SystemExit)
81
+ end
82
+
83
+ it "should re-reise SystemExit exceptions" do
84
+ Shelly::CLI::Main.stub(:start).and_raise(SystemExit.new)
85
+ $stdout.should_not_receive(:puts).with("Unknown error, to see debug information run command with --debug")
86
+ runner = Shelly::CLI::Runner.new(%w(version))
87
+ lambda {
88
+ runner.start
89
+ }.should raise_error(SystemExit)
90
+ end
63
91
  end
64
92
  end
65
93
  end