shelly 0.0.43 → 0.0.44.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/lib/shelly/app.rb +4 -0
- data/lib/shelly/cli/backup.rb +42 -43
- data/lib/shelly/cli/config.rb +34 -47
- data/lib/shelly/cli/deploys.rb +14 -22
- data/lib/shelly/cli/main.rb +95 -88
- data/lib/shelly/cli/runner.rb +6 -2
- data/lib/shelly/cli/user.rb +10 -16
- data/lib/shelly/client.rb +36 -32
- data/lib/shelly/download_progress_bar.rb +1 -1
- data/lib/shelly/helpers.rb +5 -10
- data/lib/shelly/user.rb +10 -2
- data/lib/shelly/version.rb +1 -1
- data/lib/thor/thor.rb +4 -0
- data/shelly.gemspec +2 -1
- data/spec/helpers.rb +7 -0
- data/spec/shelly/app_spec.rb +11 -5
- data/spec/shelly/cli/backup_spec.rb +36 -31
- data/spec/shelly/cli/config_spec.rb +70 -35
- data/spec/shelly/cli/deploys_spec.rb +19 -19
- data/spec/shelly/cli/main_spec.rb +213 -105
- data/spec/shelly/cli/runner_spec.rb +29 -1
- data/spec/shelly/cli/user_spec.rb +20 -53
- data/spec/shelly/client_spec.rb +90 -81
- data/spec/shelly/download_progress_bar_spec.rb +4 -4
- data/spec/shelly/user_spec.rb +23 -0
- data/spec/spec_helper.rb +5 -1
- metadata +43 -32
@@ -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 #
|
28
|
-
shelly backup <command> #
|
29
|
-
shelly config <command> #
|
30
|
-
shelly delete # Delete cloud
|
31
|
-
shelly deploys <command> # View
|
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 #
|
34
|
-
shelly list #
|
35
|
-
shelly login [EMAIL] #
|
36
|
-
shelly
|
37
|
-
shelly
|
38
|
-
shelly
|
39
|
-
shelly
|
40
|
-
shelly
|
41
|
-
shelly
|
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
|
58
|
+
-c, [--cloud=CLOUD] # Specify cloud
|
57
59
|
[--debug] # Show debug information
|
58
60
|
|
59
|
-
Show latest application logs
|
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(
|
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
|
-
|
176
|
-
exception = Shelly::Client::
|
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::
|
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
|
-
|
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
|
-
|
375
|
-
exception = Shelly::Client::
|
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
|
-
|
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.
|
527
|
-
$stdout.should_receive(:puts).with("
|
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(
|
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(
|
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(
|
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(
|
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).
|
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(
|
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
|
-
|
584
|
-
exception =
|
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
|
605
|
-
|
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
|
613
|
-
@
|
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
|
619
|
-
@client.stub(:
|
620
|
-
$stdout.should_receive(:puts).with(red "You
|
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.
|
640
|
-
$stdout.should_receive(:puts).with("
|
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 "#
|
661
|
+
describe "#ip" do
|
657
662
|
before do
|
658
663
|
File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
|
659
|
-
|
664
|
+
@main.stub(:logged_in?).and_return(true)
|
660
665
|
end
|
661
666
|
|
662
|
-
it "should
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
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::
|
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::
|
762
|
-
exception = Shelly::Client::
|
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
|
813
|
-
|
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
|
821
|
-
|
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
|
830
|
-
exception = Shelly::Client::
|
831
|
-
@client.stub(:
|
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
|
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
|
-
|
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
|