shelly 0.0.49 → 0.0.50.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/Rakefile +1 -1
- data/lib/shelly/app.rb +32 -7
- data/lib/shelly/cli/main.rb +15 -9
- data/lib/shelly/cli/runner.rb +5 -0
- data/lib/shelly/cli/user.rb +5 -1
- data/lib/shelly/client.rb +2 -2
- data/lib/shelly/version.rb +1 -1
- data/shelly.gemspec +1 -1
- data/spec/shelly/app_spec.rb +29 -9
- data/spec/shelly/cli/main_spec.rb +51 -16
- data/spec/shelly/cli/runner_spec.rb +33 -0
- data/spec/shelly/cli/user_spec.rb +18 -7
- data/spec/shelly/client_spec.rb +7 -5
- metadata +150 -164
data/Rakefile
CHANGED
data/lib/shelly/app.rb
CHANGED
@@ -13,12 +13,16 @@ module Shelly
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def add_git_remote
|
16
|
-
system("git remote rm
|
17
|
-
system("git remote add
|
16
|
+
system("git remote rm #{code_name} > /dev/null 2>&1")
|
17
|
+
system("git remote add #{code_name} #{git_url}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def git_remote_exist?
|
21
|
+
IO.popen("git remote").read.include?(code_name)
|
18
22
|
end
|
19
23
|
|
20
24
|
def remove_git_remote
|
21
|
-
system("git remote rm
|
25
|
+
system("git remote rm #{code_name} > /dev/null 2>&1")
|
22
26
|
end
|
23
27
|
|
24
28
|
def generate_cloudfile
|
@@ -33,7 +37,7 @@ module Shelly
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def create
|
36
|
-
attributes = {:
|
40
|
+
attributes = {:code_name => code_name, :domains => domains}
|
37
41
|
response = shelly.create_app(attributes)
|
38
42
|
self.git_url = response["git_url"]
|
39
43
|
self.domains = response["domains"]
|
@@ -102,11 +106,32 @@ module Shelly
|
|
102
106
|
end
|
103
107
|
|
104
108
|
def self.guess_code_name
|
105
|
-
|
109
|
+
guessed = nil
|
110
|
+
if Cloudfile.present?
|
111
|
+
clouds = Cloudfile.new.clouds
|
112
|
+
if clouds.grep(/staging/)
|
113
|
+
guessed = "production"
|
114
|
+
production_clouds = clouds.grep(/production/)
|
115
|
+
production_clouds.sort.each do |cloud|
|
116
|
+
cloud =~ /production(\d*)/
|
117
|
+
guessed = "production#{$1.to_i+1}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
"#{File.basename(Dir.pwd)}-#{guessed || 'staging'}"
|
122
|
+
end
|
123
|
+
|
124
|
+
def collaborations
|
125
|
+
@collaborations ||= Array(shelly.collaborations(code_name)).
|
126
|
+
sort_by { |c| c["email"] }
|
127
|
+
end
|
128
|
+
|
129
|
+
def active_collaborations
|
130
|
+
collaborations.select { |c| c["active"] }
|
106
131
|
end
|
107
132
|
|
108
|
-
def
|
109
|
-
|
133
|
+
def inactive_collaborations
|
134
|
+
collaborations.select { |c| !c["active"] }
|
110
135
|
end
|
111
136
|
|
112
137
|
def configs
|
data/lib/shelly/cli/main.rb
CHANGED
@@ -16,7 +16,7 @@ module Shelly
|
|
16
16
|
check_unknown_options!(:except => :rake)
|
17
17
|
|
18
18
|
# FIXME: it should be possible to pass single symbol, instead of one element array
|
19
|
-
before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete, :ip, :logout, :execute, :rake]
|
19
|
+
before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :ip, :logout, :execute, :rake]
|
20
20
|
before_hook :inside_git_repository?, :only => [:add]
|
21
21
|
before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip, :execute, :rake]
|
22
22
|
|
@@ -85,8 +85,14 @@ module Shelly
|
|
85
85
|
@app.domains = options["domains"] || ["#{@app.code_name}.shellyapp.com"]
|
86
86
|
@app.create
|
87
87
|
|
88
|
-
|
89
|
-
@app
|
88
|
+
git_remote = @app.git_remote_exist?
|
89
|
+
if !git_remote or (git_remote and yes?("Git remote #{@app} exists, overwrite (yes/no): "))
|
90
|
+
say "Adding remote #{@app} #{@app.git_url}", :green
|
91
|
+
@app.add_git_remote
|
92
|
+
else
|
93
|
+
say "You have to manually add git remote:"
|
94
|
+
say "`git remote add NAME #{@app.git_url}`"
|
95
|
+
end
|
90
96
|
|
91
97
|
say "Creating Cloudfile", :green
|
92
98
|
@app.create_cloudfile
|
@@ -100,7 +106,7 @@ module Shelly
|
|
100
106
|
end
|
101
107
|
|
102
108
|
info_adding_cloudfile_to_repository
|
103
|
-
info_deploying_to_shellycloud
|
109
|
+
info_deploying_to_shellycloud(@app)
|
104
110
|
|
105
111
|
rescue Client::ValidationException => e
|
106
112
|
e.each_error { |error| say_error error, :with_exit => false }
|
@@ -344,8 +350,8 @@ module Shelly
|
|
344
350
|
end
|
345
351
|
|
346
352
|
def ask_for_code_name
|
347
|
-
default_code_name =
|
348
|
-
code_name = ask("Cloud code name (#{
|
353
|
+
default_code_name = Shelly::App.guess_code_name
|
354
|
+
code_name = ask("Cloud code name (#{Shelly::App.guess_code_name} - default):")
|
349
355
|
code_name.blank? ? default_code_name : code_name
|
350
356
|
end
|
351
357
|
|
@@ -369,15 +375,15 @@ module Shelly
|
|
369
375
|
say " git status"
|
370
376
|
end
|
371
377
|
|
372
|
-
def info_deploying_to_shellycloud
|
378
|
+
def info_deploying_to_shellycloud(remote)
|
373
379
|
say_new_line
|
374
380
|
say "When you make sure all settings are correct please issue following commands:", :green
|
375
381
|
say " git add ."
|
376
382
|
say ' git commit -m "Application added to Shelly Cloud"'
|
377
383
|
say " git push"
|
378
384
|
say_new_line
|
379
|
-
say "Deploy to
|
380
|
-
say " git push
|
385
|
+
say "Deploy to your cloud using:", :green
|
386
|
+
say " git push #{remote} master"
|
381
387
|
say_new_line
|
382
388
|
end
|
383
389
|
end
|
data/lib/shelly/cli/runner.rb
CHANGED
@@ -18,11 +18,16 @@ module Shelly
|
|
18
18
|
def start
|
19
19
|
Shelly::CLI::Main.start(args)
|
20
20
|
rescue SystemExit; raise
|
21
|
+
rescue Client::UnauthorizedException
|
22
|
+
raise if debug?
|
23
|
+
say_error "You are not logged in. To log in use: `shelly login`"
|
21
24
|
rescue Client::GemVersionException => e
|
25
|
+
raise if debug?
|
22
26
|
say "Required shelly gem version: #{e.body["required_version"]}"
|
23
27
|
say "Your version: #{VERSION}"
|
24
28
|
say_error "Update shelly gem with `gem install shelly`"
|
25
29
|
rescue Interrupt
|
30
|
+
raise if debug?
|
26
31
|
say_new_line
|
27
32
|
say_error "[canceled]"
|
28
33
|
rescue Exception
|
data/lib/shelly/cli/user.rb
CHANGED
@@ -16,7 +16,9 @@ module Shelly
|
|
16
16
|
begin
|
17
17
|
@app = App.new(cloud)
|
18
18
|
say "Cloud #{cloud}:"
|
19
|
-
@app.
|
19
|
+
@app.active_collaborations.each { |c| say " #{c["email"]}" }
|
20
|
+
@app.inactive_collaborations.each { |c|
|
21
|
+
say " #{c["email"]} (invited)" }
|
20
22
|
rescue Client::NotFoundException => e
|
21
23
|
raise unless e.resource == :cloud
|
22
24
|
say_error "You have no access to '#{cloud}' cloud defined in Cloudfile"
|
@@ -56,6 +58,8 @@ module Shelly
|
|
56
58
|
begin
|
57
59
|
@user.delete_collaboration(cloud, user_email)
|
58
60
|
say "User #{user_email} deleted from cloud #{cloud}"
|
61
|
+
rescue Client::ConflictException => e
|
62
|
+
say_error e[:message]
|
59
63
|
rescue Client::NotFoundException => e
|
60
64
|
case e.resource
|
61
65
|
when :cloud
|
data/lib/shelly/client.rb
CHANGED
@@ -152,8 +152,8 @@ module Shelly
|
|
152
152
|
post("/apps/#{code_name}/database_backups", :kind => kind)
|
153
153
|
end
|
154
154
|
|
155
|
-
def
|
156
|
-
get("/apps/#{cloud}/
|
155
|
+
def collaborations(cloud)
|
156
|
+
get("/apps/#{cloud}/collaborations")
|
157
157
|
end
|
158
158
|
|
159
159
|
def redeploy(cloud)
|
data/lib/shelly/version.rb
CHANGED
data/shelly.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = %q{Tool for managing applications and clouds at shellycloud.com}
|
13
13
|
|
14
14
|
s.rubyforge_project = "shelly"
|
15
|
-
s.add_development_dependency "rspec"
|
15
|
+
s.add_development_dependency "rspec", "~> 2.8.0"
|
16
16
|
s.add_development_dependency "rake"
|
17
17
|
s.add_development_dependency "guard"
|
18
18
|
s.add_development_dependency "guard-rspec"
|
data/spec/shelly/app_spec.rb
CHANGED
@@ -12,15 +12,29 @@ describe Shelly::App do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
describe ".guess_code_name" do
|
15
|
-
|
16
|
-
|
15
|
+
context "no Cloudfile" do
|
16
|
+
it "should return name of current working directory" do
|
17
|
+
Shelly::App.guess_code_name.should == "foo-staging"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with Cloudfile" do
|
22
|
+
it "should return production" do
|
23
|
+
File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
|
24
|
+
Shelly::App.guess_code_name.should == "foo-production"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return productionNUMBER" do
|
28
|
+
File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
|
29
|
+
Shelly::App.guess_code_name.should == "foo-production1"
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
19
33
|
|
20
|
-
describe "#
|
34
|
+
describe "#collaborations" do
|
21
35
|
it "should fetch app's users" do
|
22
|
-
@client.should_receive(:
|
23
|
-
@app.
|
36
|
+
@client.should_receive(:collaborations).with("foo-staging")
|
37
|
+
@app.collaborations
|
24
38
|
end
|
25
39
|
end
|
26
40
|
|
@@ -31,16 +45,24 @@ describe Shelly::App do
|
|
31
45
|
end
|
32
46
|
|
33
47
|
it "should try to remove existing git remote" do
|
34
|
-
@app.should_receive(:system).with("git remote rm
|
48
|
+
@app.should_receive(:system).with("git remote rm foo-staging > /dev/null 2>&1")
|
35
49
|
@app.add_git_remote
|
36
50
|
end
|
37
51
|
|
38
52
|
it "should add git remote with proper name and git repository" do
|
39
|
-
@app.should_receive(:system).with("git remote add
|
53
|
+
@app.should_receive(:system).with("git remote add foo-staging git@git.shellycloud.com:foo-staging.git")
|
40
54
|
@app.add_git_remote
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
58
|
+
describe "git_remote_exist" do
|
59
|
+
it "should return true if git remote exist" do
|
60
|
+
io = mock(:read => "origin\nfoo-staging")
|
61
|
+
IO.should_receive(:popen).with("git remote").and_return(io)
|
62
|
+
@app.git_remote_exist?.should be_true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
44
66
|
describe "#configs" do
|
45
67
|
it "should get configs from client" do
|
46
68
|
@client.should_receive(:app_configs).with("foo-staging").and_return(config_response)
|
@@ -229,7 +251,6 @@ config
|
|
229
251
|
@app.code_name = "fooo"
|
230
252
|
attributes = {
|
231
253
|
:code_name => "fooo",
|
232
|
-
:name => "fooo",
|
233
254
|
:domains => nil
|
234
255
|
}
|
235
256
|
@client.should_receive(:create_app).with(attributes).and_return("git_url" => "git@git.shellycloud.com:fooo.git",
|
@@ -254,7 +275,6 @@ config
|
|
254
275
|
@app.domains = ["boo.shellyapp.com", "boo.example.com"]
|
255
276
|
attributes = {
|
256
277
|
:code_name => "boo",
|
257
|
-
:name => "boo",
|
258
278
|
:domains => %w(boo.shellyapp.com boo.example.com)
|
259
279
|
}
|
260
280
|
@client.should_receive(:create_app).with(attributes).and_return("git_url" => "git@git.shellycloud.com:fooo.git",
|
@@ -274,6 +274,7 @@ OUT
|
|
274
274
|
Shelly::App.stub(:new).and_return(@app)
|
275
275
|
@client.stub(:token).and_return("abc")
|
276
276
|
@app.stub(:attributes).and_return({"trial" => false})
|
277
|
+
@app.stub(:git_remote_exist?).and_return(false)
|
277
278
|
end
|
278
279
|
|
279
280
|
# This spec tests inside_git_repository? hook
|
@@ -328,7 +329,7 @@ OUT
|
|
328
329
|
end
|
329
330
|
|
330
331
|
it "should use code name provided by user" do
|
331
|
-
$stdout.should_receive(:print).with("Cloud code name (foo-
|
332
|
+
$stdout.should_receive(:print).with("Cloud code name (foo-staging - default): ")
|
332
333
|
@app.should_receive(:code_name=).with("mycodename")
|
333
334
|
fake_stdin(["mycodename", ""]) do
|
334
335
|
invoke(@main, :add)
|
@@ -337,8 +338,8 @@ OUT
|
|
337
338
|
|
338
339
|
context "when user provided empty code name" do
|
339
340
|
it "should use 'current_dirname-purpose' as default" do
|
340
|
-
$stdout.should_receive(:print).with("Cloud code name (foo-
|
341
|
-
@app.should_receive(:code_name=).with("foo-
|
341
|
+
$stdout.should_receive(:print).with("Cloud code name (foo-staging - default): ")
|
342
|
+
@app.should_receive(:code_name=).with("foo-staging")
|
342
343
|
fake_stdin(["", ""]) do
|
343
344
|
invoke(@main, :add)
|
344
345
|
end
|
@@ -393,7 +394,7 @@ OUT
|
|
393
394
|
$stdout.should_receive(:puts).with(green "Billing information")
|
394
395
|
$stdout.should_receive(:puts).with("Cloud created with 20 Euro credit.")
|
395
396
|
$stdout.should_receive(:puts).with("Remember to provide billing details before trial ends.")
|
396
|
-
$stdout.should_receive(:puts).with("http://example.com/apps/foo-
|
397
|
+
$stdout.should_receive(:puts).with("http://example.com/apps/foo-staging/billing/edit")
|
397
398
|
|
398
399
|
fake_stdin(["", ""]) do
|
399
400
|
invoke(@main, :add)
|
@@ -415,7 +416,7 @@ OUT
|
|
415
416
|
@app.should_receive(:create).and_raise(exception)
|
416
417
|
$stdout.should_receive(:puts).with("\e[31mCode name has been already taken\e[0m")
|
417
418
|
$stdout.should_receive(:puts).with("\e[31mFix erros in the below command and type it again to create your cloud\e[0m")
|
418
|
-
$stdout.should_receive(:puts).with("\e[31mshelly add --code-name=foo-
|
419
|
+
$stdout.should_receive(:puts).with("\e[31mshelly add --code-name=foo-staging --databases=postgresql --domains=foo-staging.shellyapp.com\e[0m")
|
419
420
|
lambda {
|
420
421
|
fake_stdin(["", ""]) do
|
421
422
|
invoke(@main, :add)
|
@@ -436,11 +437,39 @@ OUT
|
|
436
437
|
}.should raise_error(SystemExit)
|
437
438
|
end
|
438
439
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
440
|
+
context "git remote" do
|
441
|
+
it "should add one if it doesn't exist" do
|
442
|
+
$stdout.should_receive(:puts).with("\e[32mAdding remote foooo git@git.shellycloud.com:foooo.git\e[0m")
|
443
|
+
@app.should_receive(:add_git_remote)
|
444
|
+
fake_stdin(["foooo", ""]) do
|
445
|
+
invoke(@main, :add)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context "does exist" do
|
450
|
+
before do
|
451
|
+
@app.stub(:git_remote_exist?).and_return(true)
|
452
|
+
end
|
453
|
+
|
454
|
+
it "should ask if one exist and overwrite" do
|
455
|
+
$stdout.should_receive(:print).with("Git remote foooo exists, overwrite (yes/no): ")
|
456
|
+
$stdout.should_receive(:puts).with(green "Adding remote foooo git@git.shellycloud.com:foooo.git")
|
457
|
+
@app.should_receive(:add_git_remote)
|
458
|
+
fake_stdin(["foooo", "", "yes"]) do
|
459
|
+
invoke(@main, :add)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
it "should ask if one exist and not overwrite" do
|
464
|
+
$stdout.should_receive(:print).with("Git remote foooo exists, overwrite (yes/no): ")
|
465
|
+
$stdout.should_receive(:puts).with("You have to manually add git remote:")
|
466
|
+
$stdout.should_receive(:puts).with("`git remote add NAME git@git.shellycloud.com:foooo.git`")
|
467
|
+
@app.should_not_receive(:add_git_remote)
|
468
|
+
fake_stdin(["foooo", "", "no"]) do
|
469
|
+
invoke(@main, :add)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
444
473
|
end
|
445
474
|
end
|
446
475
|
|
@@ -466,8 +495,8 @@ OUT
|
|
466
495
|
$stdout.should_receive(:puts).with(" git add .")
|
467
496
|
$stdout.should_receive(:puts).with(' git commit -m "Application added to Shelly Cloud"')
|
468
497
|
$stdout.should_receive(:puts).with(" git push")
|
469
|
-
$stdout.should_receive(:puts).with("\e[32mDeploy to
|
470
|
-
$stdout.should_receive(:puts).with(" git push
|
498
|
+
$stdout.should_receive(:puts).with("\e[32mDeploy to your cloud using:\e[0m")
|
499
|
+
$stdout.should_receive(:puts).with(" git push foooo master")
|
471
500
|
fake_stdin(["foooo", "none"]) do
|
472
501
|
invoke(@main, :add)
|
473
502
|
end
|
@@ -500,10 +529,16 @@ OUT
|
|
500
529
|
invoke(@main, :list)
|
501
530
|
end
|
502
531
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
532
|
+
context "#status" do
|
533
|
+
it "should ensure user has logged in" do
|
534
|
+
hooks(@main, :status).should include(:logged_in?)
|
535
|
+
end
|
536
|
+
|
537
|
+
it "should have a 'status' alias" do
|
538
|
+
@client.stub(:apps).and_return([])
|
539
|
+
$stdout.should_receive(:puts).with("\e[32mYou have no clouds yet\e[0m")
|
540
|
+
invoke(@main, :status)
|
541
|
+
end
|
507
542
|
end
|
508
543
|
end
|
509
544
|
|
@@ -64,6 +64,18 @@ describe Shelly::CLI::Runner do
|
|
64
64
|
}.should raise_error(SystemExit)
|
65
65
|
end
|
66
66
|
|
67
|
+
it "should rescue unauthorized exception and display message" do
|
68
|
+
@client = mock
|
69
|
+
runner = Shelly::CLI::Runner.new(%w(status))
|
70
|
+
Shelly::Client.stub(:new).and_return(@client)
|
71
|
+
@client.stub(:token).and_return("abc")
|
72
|
+
@client.stub(:apps).and_raise(Shelly::Client::UnauthorizedException.new)
|
73
|
+
$stdout.should_receive(:puts).with("You are not logged in. To log in use: `shelly login`")
|
74
|
+
lambda {
|
75
|
+
runner.start
|
76
|
+
}.should raise_error(SystemExit)
|
77
|
+
end
|
78
|
+
|
67
79
|
context "with --debug option (debug mode)" do
|
68
80
|
it "should re-raise caught exception to the console" do
|
69
81
|
Shelly::CLI::Main.stub(:start).and_raise(RuntimeError.new)
|
@@ -71,6 +83,27 @@ describe Shelly::CLI::Runner do
|
|
71
83
|
@runner.start
|
72
84
|
}.should raise_error(RuntimeError)
|
73
85
|
end
|
86
|
+
|
87
|
+
it "should re-raise unauthorized exception" do
|
88
|
+
Shelly::CLI::Main.stub(:start).and_raise(Shelly::Client::UnauthorizedException.new)
|
89
|
+
lambda {
|
90
|
+
@runner.start
|
91
|
+
}.should raise_error(Shelly::Client::UnauthorizedException)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should re-raise gem version exception" do
|
95
|
+
Shelly::CLI::Main.stub(:start).and_raise(Shelly::Client::GemVersionException.new)
|
96
|
+
lambda {
|
97
|
+
@runner.start
|
98
|
+
}.should raise_error(Shelly::Client::GemVersionException)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should re-raise interupt exception" do
|
102
|
+
Shelly::CLI::Main.stub(:start).and_raise(Interrupt.new)
|
103
|
+
lambda {
|
104
|
+
@runner.start
|
105
|
+
}.should raise_error(Interrupt)
|
106
|
+
end
|
74
107
|
end
|
75
108
|
|
76
109
|
context "without --debug option (normal mode)" do
|
@@ -27,6 +27,10 @@ describe Shelly::CLI::User do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe "#list" do
|
30
|
+
let(:response) {
|
31
|
+
[{'email' => 'user@example.com', 'active' => true},
|
32
|
+
{'email' => 'auser2@example2.com', 'active' => false}]
|
33
|
+
}
|
30
34
|
before do
|
31
35
|
@cloudfile = Shelly::Cloudfile.new
|
32
36
|
Shelly::Cloudfile.stub(:new).and_return(@cloudfile)
|
@@ -42,27 +46,24 @@ describe Shelly::CLI::User do
|
|
42
46
|
|
43
47
|
context "on success" do
|
44
48
|
it "should receive clouds from the Cloudfile" do
|
45
|
-
@client.stub(:
|
49
|
+
@client.stub(:collaborations).and_return(response)
|
46
50
|
@cloudfile.should_receive(:clouds).and_return(["foo-staging", "foo-production"])
|
47
51
|
invoke(@cli_user, :list)
|
48
52
|
end
|
49
53
|
|
50
54
|
it "should display clouds and users" do
|
51
|
-
@client.stub(:
|
55
|
+
@client.stub(:collaborations).and_return(response)
|
52
56
|
$stdout.should_receive(:puts).with("Cloud foo-production:")
|
53
57
|
$stdout.should_receive(:puts).with(" user@example.com")
|
58
|
+
$stdout.should_receive(:puts).with(" auser2@example2.com (invited)")
|
54
59
|
invoke(@cli_user, :list)
|
55
60
|
end
|
56
61
|
end
|
57
62
|
|
58
|
-
def response
|
59
|
-
[{'email' => 'user@example.com'}]
|
60
|
-
end
|
61
|
-
|
62
63
|
context "on failure" do
|
63
64
|
it "should exit with 1 if user does not have access to cloud" do
|
64
65
|
exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
|
65
|
-
@client.stub(:
|
66
|
+
@client.stub(:collaborations).and_raise(exception)
|
66
67
|
$stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
|
67
68
|
lambda { invoke(@cli_user, :list) }.should raise_error(SystemExit)
|
68
69
|
end
|
@@ -175,6 +176,16 @@ describe Shelly::CLI::User do
|
|
175
176
|
invoke(@cli_user, :delete, "megan@example.com")
|
176
177
|
}.should raise_error(SystemExit)
|
177
178
|
end
|
179
|
+
|
180
|
+
it "should show that user can't delete own collaboration" do
|
181
|
+
exception = Shelly::Client::ConflictException.new("message" =>
|
182
|
+
"Can't remove own collaboration")
|
183
|
+
@client.stub(:delete_collaboration).and_raise(exception)
|
184
|
+
$stdout.should_receive(:puts).with(red "Can't remove own collaboration")
|
185
|
+
lambda {
|
186
|
+
invoke(@cli_user, :delete, "megan@example.com")
|
187
|
+
}.should raise_error(SystemExit)
|
188
|
+
end
|
178
189
|
end
|
179
190
|
end
|
180
191
|
end
|
data/spec/shelly/client_spec.rb
CHANGED
@@ -170,12 +170,14 @@ describe Shelly::Client do
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
-
describe "#
|
173
|
+
describe "#collaborations" do
|
174
174
|
it "should send get request with app code_names" do
|
175
|
-
FakeWeb.register_uri(:get, api_url("apps/staging-foo/
|
176
|
-
{:email => "
|
177
|
-
|
178
|
-
response
|
175
|
+
FakeWeb.register_uri(:get, api_url("apps/staging-foo/collaborations"),
|
176
|
+
:body => [{:email => "test@example.com", :active => true},
|
177
|
+
{:email => "test2@example.com", :active => false}].to_json)
|
178
|
+
response = @client.collaborations("staging-foo")
|
179
|
+
response.should == [{"email" => "test@example.com", 'active' => true},
|
180
|
+
{"email" => "test2@example.com", 'active' => false}]
|
179
181
|
end
|
180
182
|
end
|
181
183
|
|
metadata
CHANGED
@@ -1,188 +1,167 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: shelly
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 49
|
10
|
-
version: 0.0.49
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.50.pre
|
5
|
+
prerelease: 7
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Shelly Cloud team
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
version_requirements: &id001 !ruby/object:Gem::Requirement
|
22
|
-
none: false
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
hash: 3
|
27
|
-
segments:
|
28
|
-
- 0
|
29
|
-
version: "0"
|
30
|
-
requirement: *id001
|
31
|
-
prerelease: false
|
32
|
-
type: :development
|
12
|
+
date: 2012-02-28 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
33
15
|
name: rspec
|
34
|
-
|
35
|
-
version_requirements: &id002 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70352069078820 !ruby/object:Gem::Requirement
|
36
17
|
none: false
|
37
|
-
requirements:
|
38
|
-
- -
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
|
41
|
-
segments:
|
42
|
-
- 0
|
43
|
-
version: "0"
|
44
|
-
requirement: *id002
|
45
|
-
prerelease: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.8.0
|
46
22
|
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70352069078820
|
25
|
+
- !ruby/object:Gem::Dependency
|
47
26
|
name: rake
|
48
|
-
|
49
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
27
|
+
requirement: &70352069078400 !ruby/object:Gem::Requirement
|
50
28
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
segments:
|
56
|
-
- 0
|
57
|
-
version: "0"
|
58
|
-
requirement: *id003
|
59
|
-
prerelease: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
60
33
|
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70352069078400
|
36
|
+
- !ruby/object:Gem::Dependency
|
61
37
|
name: guard
|
62
|
-
|
63
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
38
|
+
requirement: &70352069077940 !ruby/object:Gem::Requirement
|
64
39
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
segments:
|
70
|
-
- 0
|
71
|
-
version: "0"
|
72
|
-
requirement: *id004
|
73
|
-
prerelease: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
74
44
|
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70352069077940
|
47
|
+
- !ruby/object:Gem::Dependency
|
75
48
|
name: guard-rspec
|
76
|
-
|
77
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
49
|
+
requirement: &70352069077520 !ruby/object:Gem::Requirement
|
78
50
|
none: false
|
79
|
-
requirements:
|
80
|
-
- -
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
|
83
|
-
segments:
|
84
|
-
- 0
|
85
|
-
version: "0"
|
86
|
-
requirement: *id005
|
87
|
-
prerelease: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
88
55
|
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70352069077520
|
58
|
+
- !ruby/object:Gem::Dependency
|
89
59
|
name: simplecov
|
90
|
-
|
91
|
-
|
60
|
+
requirement: &70352069077100 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70352069077100
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ruby_gntp
|
71
|
+
requirement: &70352069076580 !ruby/object:Gem::Requirement
|
92
72
|
none: false
|
93
|
-
requirements:
|
94
|
-
- -
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
|
97
|
-
|
98
|
-
- 0
|
99
|
-
version: "0"
|
100
|
-
requirement: *id006
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
101
78
|
prerelease: false
|
79
|
+
version_requirements: *70352069076580
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rb-fsevent
|
82
|
+
requirement: &70352069076120 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
102
88
|
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70352069076120
|
91
|
+
- !ruby/object:Gem::Dependency
|
103
92
|
name: fakefs
|
104
|
-
|
105
|
-
version_requirements: &id007 !ruby/object:Gem::Requirement
|
93
|
+
requirement: &70352069075600 !ruby/object:Gem::Requirement
|
106
94
|
none: false
|
107
|
-
requirements:
|
108
|
-
- -
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
|
111
|
-
segments:
|
112
|
-
- 0
|
113
|
-
version: "0"
|
114
|
-
requirement: *id007
|
115
|
-
prerelease: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
116
99
|
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70352069075600
|
102
|
+
- !ruby/object:Gem::Dependency
|
117
103
|
name: fakeweb
|
118
|
-
|
119
|
-
version_requirements: &id008 !ruby/object:Gem::Requirement
|
104
|
+
requirement: &70352069075060 !ruby/object:Gem::Requirement
|
120
105
|
none: false
|
121
|
-
requirements:
|
122
|
-
- -
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
|
125
|
-
|
126
|
-
- 0
|
127
|
-
- 14
|
128
|
-
- 7
|
129
|
-
version: 0.14.7
|
130
|
-
requirement: *id008
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
131
111
|
prerelease: false
|
132
|
-
|
112
|
+
version_requirements: *70352069075060
|
113
|
+
- !ruby/object:Gem::Dependency
|
133
114
|
name: wijet-thor
|
134
|
-
|
135
|
-
version_requirements: &id009 !ruby/object:Gem::Requirement
|
115
|
+
requirement: &70352069074100 !ruby/object:Gem::Requirement
|
136
116
|
none: false
|
137
|
-
requirements:
|
138
|
-
- -
|
139
|
-
- !ruby/object:Gem::Version
|
140
|
-
|
141
|
-
segments:
|
142
|
-
- 0
|
143
|
-
version: "0"
|
144
|
-
requirement: *id009
|
145
|
-
prerelease: false
|
117
|
+
requirements:
|
118
|
+
- - ~>
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.14.7
|
146
121
|
type: :runtime
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *70352069074100
|
124
|
+
- !ruby/object:Gem::Dependency
|
147
125
|
name: rest-client
|
148
|
-
|
149
|
-
version_requirements: &id010 !ruby/object:Gem::Requirement
|
126
|
+
requirement: &70352069073660 !ruby/object:Gem::Requirement
|
150
127
|
none: false
|
151
|
-
requirements:
|
152
|
-
- -
|
153
|
-
- !ruby/object:Gem::Version
|
154
|
-
|
155
|
-
segments:
|
156
|
-
- 0
|
157
|
-
version: "0"
|
158
|
-
requirement: *id010
|
159
|
-
prerelease: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
160
132
|
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *70352069073660
|
135
|
+
- !ruby/object:Gem::Dependency
|
161
136
|
name: json
|
162
|
-
|
163
|
-
version_requirements: &id011 !ruby/object:Gem::Requirement
|
137
|
+
requirement: &70352069073200 !ruby/object:Gem::Requirement
|
164
138
|
none: false
|
165
|
-
requirements:
|
166
|
-
- -
|
167
|
-
- !ruby/object:Gem::Version
|
168
|
-
|
169
|
-
segments:
|
170
|
-
- 0
|
171
|
-
version: "0"
|
172
|
-
requirement: *id011
|
173
|
-
prerelease: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
174
143
|
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: *70352069073200
|
146
|
+
- !ruby/object:Gem::Dependency
|
175
147
|
name: progressbar
|
148
|
+
requirement: &70352069072600 !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
type: :runtime
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: *70352069072600
|
176
157
|
description: Tool for managing applications and clouds at shellycloud.com
|
177
|
-
email:
|
158
|
+
email:
|
178
159
|
- support@shellycloud.com
|
179
|
-
executables:
|
160
|
+
executables:
|
180
161
|
- shelly
|
181
162
|
extensions: []
|
182
|
-
|
183
163
|
extra_rdoc_files: []
|
184
|
-
|
185
|
-
files:
|
164
|
+
files:
|
186
165
|
- .gitignore
|
187
166
|
- .travis.yml
|
188
167
|
- Gemfile
|
@@ -234,36 +213,43 @@ files:
|
|
234
213
|
- spec/thor/options_spec.rb
|
235
214
|
homepage: http://shellycloud.com
|
236
215
|
licenses: []
|
237
|
-
|
238
216
|
post_install_message:
|
239
217
|
rdoc_options: []
|
240
|
-
|
241
|
-
require_paths:
|
218
|
+
require_paths:
|
242
219
|
- lib
|
243
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
220
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
244
221
|
none: false
|
245
|
-
requirements:
|
246
|
-
- -
|
247
|
-
- !ruby/object:Gem::Version
|
248
|
-
|
249
|
-
|
250
|
-
- 0
|
251
|
-
version: "0"
|
252
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - ! '>='
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '0'
|
226
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
253
227
|
none: false
|
254
|
-
requirements:
|
255
|
-
- -
|
256
|
-
- !ruby/object:Gem::Version
|
257
|
-
|
258
|
-
segments:
|
259
|
-
- 0
|
260
|
-
version: "0"
|
228
|
+
requirements:
|
229
|
+
- - ! '>'
|
230
|
+
- !ruby/object:Gem::Version
|
231
|
+
version: 1.3.1
|
261
232
|
requirements: []
|
262
|
-
|
263
233
|
rubyforge_project: shelly
|
264
234
|
rubygems_version: 1.8.10
|
265
235
|
signing_key:
|
266
236
|
specification_version: 3
|
267
237
|
summary: Shelly Cloud command line tool
|
268
|
-
test_files:
|
269
|
-
|
238
|
+
test_files:
|
239
|
+
- spec/helpers.rb
|
240
|
+
- spec/input_faker.rb
|
241
|
+
- spec/shelly/app_spec.rb
|
242
|
+
- spec/shelly/backup_spec.rb
|
243
|
+
- spec/shelly/cli/backup_spec.rb
|
244
|
+
- spec/shelly/cli/config_spec.rb
|
245
|
+
- spec/shelly/cli/deploys_spec.rb
|
246
|
+
- spec/shelly/cli/main_spec.rb
|
247
|
+
- spec/shelly/cli/runner_spec.rb
|
248
|
+
- spec/shelly/cli/user_spec.rb
|
249
|
+
- spec/shelly/client_spec.rb
|
250
|
+
- spec/shelly/cloudfile_spec.rb
|
251
|
+
- spec/shelly/download_progress_bar_spec.rb
|
252
|
+
- spec/shelly/model_spec.rb
|
253
|
+
- spec/shelly/user_spec.rb
|
254
|
+
- spec/spec_helper.rb
|
255
|
+
- spec/thor/options_spec.rb
|