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.
- 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
|