shelly 0.0.46.pre3 → 0.0.46.pre4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/shelly/app.rb CHANGED
@@ -147,7 +147,12 @@ module Shelly
147
147
  file_name_or_code
148
148
  end
149
149
 
150
- response = shelly.run(code_name, code)
150
+ response = shelly.command(code_name, code, :ruby)
151
+ response["result"]
152
+ end
153
+
154
+ def rake(task)
155
+ response = shelly.command(code_name, task, :rake)
151
156
  response["result"]
152
157
  end
153
158
 
@@ -13,12 +13,12 @@ module Shelly
13
13
  register(Backup, "backup", "backup <command>", "Manage database backups")
14
14
  register(Deploys, "deploys", "deploys <command>", "View deploy logs")
15
15
  register(Config, "config", "config <command>", "Manage application configuration files")
16
- check_unknown_options!
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]
19
+ before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete, :ip, :logout, :execute, :rake]
20
20
  before_hook :inside_git_repository?, :only => [:add]
21
- before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip]
21
+ before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip, :execute, :rake]
22
22
 
23
23
  map %w(-v --version) => :version
24
24
  desc "version", "Display shelly version"
@@ -231,9 +231,8 @@ module Shelly
231
231
  say "You have been successfully logged out" if user.delete_credentials
232
232
  end
233
233
 
234
- desc "execute [CODE]", "Run code on one of application servers"
235
- method_option :cloud, :type => :string, :aliases => "-c",
236
- :desc => "Specify which cloud to run code for"
234
+ desc "execute CODE", "Run code on one of application servers"
235
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
237
236
  long_desc "Run code given in parameter on one of application servers. If a file name is given, run contents of that file."
238
237
  def execute(file_name_or_code)
239
238
  cloud = options[:cloud]
@@ -250,6 +249,18 @@ module Shelly
250
249
  end
251
250
  end
252
251
 
252
+ desc "rake TASK", "Run rake task"
253
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
254
+ def rake(task = nil)
255
+ task = rake_args.join(" ")
256
+ multiple_clouds(options[:cloud], "rake #{task}")
257
+ result = @app.rake(task)
258
+ say result
259
+ rescue Client::APIException => e
260
+ raise unless e[:message] == "App not running"
261
+ say_error "Cloud #{@app} is not running. Cannot run rake task."
262
+ end
263
+
253
264
  desc "redeploy", "Redeploy application"
254
265
  method_option :cloud, :type => :string, :aliases => "-c",
255
266
  :desc => "Specify which cloud to redeploy application for"
@@ -274,6 +285,23 @@ module Shelly
274
285
 
275
286
  # FIXME: move to helpers
276
287
  no_tasks do
288
+ # Returns valid arguments for rake, removes shelly gem arguments
289
+ def rake_args(args = ARGV)
290
+ skip_next = false
291
+ [].tap do |out|
292
+ args.each do |arg|
293
+ case arg
294
+ when "rake", "--debug"
295
+ when "--cloud", "-c"
296
+ skip_next = true
297
+ else
298
+ out << arg unless skip_next
299
+ skip_next = false
300
+ end
301
+ end
302
+ end
303
+ end
304
+
277
305
  def check_options(options)
278
306
  unless options.empty?
279
307
  unless ["code-name", "databases", "domains"].all? do |option|
data/lib/shelly/client.rb CHANGED
@@ -115,8 +115,8 @@ module Shelly
115
115
  get("/apps/#{code_name}")
116
116
  end
117
117
 
118
- def run(cloud, code)
119
- post("/apps/#{cloud}/run", :body => code)
118
+ def command(cloud, body, type)
119
+ post("/apps/#{cloud}/command", {:body => body, :type => type})
120
120
  end
121
121
 
122
122
  def deploy_logs(cloud)
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.46.pre3"
2
+ VERSION = "0.0.46.pre4"
3
3
  end
@@ -293,21 +293,28 @@ config
293
293
  @response = {
294
294
  "result" => "4"
295
295
  }
296
- @client.stub(:run).and_return(@response)
296
+ @client.stub(:command).and_return(@response)
297
297
  File.open("to_run.rb", 'w') {|f| f.write("User.count\n") }
298
298
  end
299
299
 
300
300
  it "should return result of executed code" do
301
- @client.should_receive(:run).with("foo-staging", "2 + 2")
301
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby)
302
302
  @app.run("2 + 2").should == "4"
303
303
  end
304
304
 
305
305
  it "should send contents of file when file exists" do
306
- @client.should_receive(:run).with("foo-staging", "User.count\n")
306
+ @client.should_receive(:command).with("foo-staging", "User.count\n", :ruby)
307
307
  @app.run("to_run.rb")
308
308
  end
309
309
  end
310
310
 
311
+ describe "#rake" do
312
+ it "should return result of rake task" do
313
+ @client.should_receive(:command).with("foo-staging", "db:create", :rake).and_return({"result" => "OK"})
314
+ @app.rake("db:create").should == "OK"
315
+ end
316
+ end
317
+
311
318
  describe "#to_s" do
312
319
  it "should return code_name" do
313
320
  @app.to_s.should == "foo-staging"
@@ -29,13 +29,14 @@ Tasks:
29
29
  shelly config <command> # Manage application configuration files
30
30
  shelly delete # Delete the cloud
31
31
  shelly deploys <command> # View deploy logs
32
- shelly execute [CODE] # Run code on one of application servers
32
+ shelly execute CODE # Run code on one of application servers
33
33
  shelly help [TASK] # Describe available tasks or one specific task
34
34
  shelly ip # List cloud's IP addresses
35
35
  shelly list # List available clouds
36
36
  shelly login [EMAIL] # Log into Shelly Cloud
37
37
  shelly logout # Logout from Shelly Cloud
38
38
  shelly logs # Show latest application logs
39
+ shelly rake TASK # Run rake task
39
40
  shelly redeploy # Redeploy application
40
41
  shelly register [EMAIL] # Register new account
41
42
  shelly start # Start the cloud
@@ -933,9 +934,13 @@ OUT
933
934
  hooks(@main, :execute).should include(:logged_in?)
934
935
  end
935
936
 
937
+ it "should ensure cloudfile present" do
938
+ hooks(@main, :execute).should include(:cloudfile_present?)
939
+ end
940
+
936
941
  context "single cloud in Cloudfile" do
937
942
  it "should execute code for the cloud" do
938
- @client.should_receive(:run).with("foo-production", "User.count").
943
+ @client.should_receive(:command).with("foo-production", "User.count", :ruby).
939
944
  and_return({"result" => "3"})
940
945
  $stdout.should_receive(:puts).with("3")
941
946
  invoke(@main, :execute, "to_execute.rb")
@@ -960,7 +965,7 @@ OUT
960
965
  end
961
966
 
962
967
  it "should fetch from command line which cloud to start" do
963
- @client.should_receive(:run).with("foo-staging", "User.count").
968
+ @client.should_receive(:command).with("foo-staging", "User.count", :ruby).
964
969
  and_return({"result" => "3"})
965
970
  $stdout.should_receive(:puts).with("3")
966
971
  @main.options = {:cloud => "foo-staging"}
@@ -968,7 +973,7 @@ OUT
968
973
  end
969
974
 
970
975
  it "should run code when no file from parameter is found" do
971
- @client.should_receive(:run).with("foo-staging", "2 + 2").
976
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby).
972
977
  and_return({"result" => "4"})
973
978
  $stdout.should_receive(:puts).with("4")
974
979
  @main.options = {:cloud => "foo-staging"}
@@ -976,9 +981,9 @@ OUT
976
981
  end
977
982
  end
978
983
 
979
- context "cloud is not running" do
984
+ context "cloud is not in running state" do
980
985
  it "should print error" do
981
- @client.should_receive(:run).with("foo-staging", "2 + 2").
986
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby).
982
987
  and_raise(Shelly::Client::APIException.new(
983
988
  {"message" => "App not running"}, 504))
984
989
  $stdout.should_receive(:puts).
@@ -988,7 +993,7 @@ OUT
988
993
  end
989
994
 
990
995
  it "should re-raise other exceptions" do
991
- @client.should_receive(:run).with("foo-staging", "2 + 2").
996
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby).
992
997
  and_raise(Exception)
993
998
  @main.options = {:cloud => "foo-staging"}
994
999
  lambda { invoke(@main, :execute, "2 + 2") }.should raise_error(Exception)
@@ -996,6 +1001,93 @@ OUT
996
1001
  end
997
1002
  end
998
1003
 
1004
+ describe "#rake" do
1005
+ before do
1006
+ FileUtils.mkdir_p("/projects/foo")
1007
+ Dir.chdir("/projects/foo")
1008
+ File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
1009
+ @user = Shelly::User.new
1010
+ @user.stub(:token)
1011
+ Shelly::User.stub(:new).and_return(@user)
1012
+ @app = Shelly::App.new
1013
+ Shelly::App.stub(:new).and_return(@app)
1014
+ @main.stub(:rake_args).and_return(%w(db:migrate))
1015
+ end
1016
+
1017
+ it "should ensure user has logged in" do
1018
+ hooks(@main, :rake).should include(:logged_in?)
1019
+ end
1020
+
1021
+ it "should ensure cloudfile present" do
1022
+ hooks(@main, :execute).should include(:cloudfile_present?)
1023
+ end
1024
+
1025
+ it "should invoke :command on app with rake task" do
1026
+ @client.should_receive(:command).with("foo-production", "db:migrate", :rake).and_return("result" => "OK")
1027
+ $stdout.should_receive(:puts).with("OK")
1028
+ invoke(@main, :rake, "db:migrate")
1029
+ end
1030
+
1031
+ it "should pass rake arguments to the client" do
1032
+ @main.stub(:rake_args).and_return(%w(-T db:schema))
1033
+ @client.should_receive(:command).with("foo-production", "-T db:schema", :rake).and_return("result" => "OK")
1034
+ $stdout.should_receive(:puts).with("OK")
1035
+ invoke(@main, :rake, nil)
1036
+ end
1037
+
1038
+ describe "#rake_args" do
1039
+ before { @main.unstub!(:rake_args) }
1040
+
1041
+ it "should return Array of rake arguments (skipping shelly gem arguments)" do
1042
+ argv = %w(rake -T db --cloud foo-production --debug)
1043
+ @main.rake_args(argv).should == %w(-T db)
1044
+ end
1045
+
1046
+ it "should take ARGV as default default argument" do
1047
+ # Rather poor, I test if method without args returns the same as method with ARGV
1048
+ @main.rake_args.should == @main.rake_args(ARGV)
1049
+ end
1050
+ end
1051
+
1052
+ context "cloud is not in running state" do
1053
+ it "should print error" do
1054
+ @client.should_receive(:command).with("foo-staging", "db:migrate", :rake).
1055
+ and_raise(Shelly::Client::APIException.new(
1056
+ {"message" => "App not running"}, 504))
1057
+ $stdout.should_receive(:puts).
1058
+ with(red "Cloud foo-staging is not running. Cannot run rake task.")
1059
+ @main.options = {:cloud => "foo-staging"}
1060
+ lambda { invoke(@main, :rake, "db:migrate") }.should raise_error(SystemExit)
1061
+ end
1062
+ end
1063
+
1064
+ context "multiple clouds in Cloudfile" do
1065
+ before do
1066
+ File.open("Cloudfile", 'w') {|f|
1067
+ f.write("foo-staging:\nfoo-production:\n") }
1068
+ end
1069
+
1070
+ it "should show information to run rake task for specific cloud and exit" do
1071
+ $stdout.should_receive(:puts).
1072
+ with(red "You have multiple clouds in Cloudfile.")
1073
+ $stdout.should_receive(:puts).
1074
+ with("Select cloud using `shelly rake db:migrate --cloud foo-production`")
1075
+ $stdout.should_receive(:puts).with("Available clouds:")
1076
+ $stdout.should_receive(:puts).with(" * foo-production")
1077
+ $stdout.should_receive(:puts).with(" * foo-staging")
1078
+ lambda { invoke(@main, :rake, "db:migrate") }.should raise_error(SystemExit)
1079
+ end
1080
+
1081
+ it "should fetch from command line for which cloud run rake task" do
1082
+ @client.should_receive(:command).with("foo-staging", "db:migrate", :rake).
1083
+ and_return({"result" => "3"})
1084
+ $stdout.should_receive(:puts).with("3")
1085
+ @main.options = {:cloud => "foo-staging"}
1086
+ invoke(@main, :rake, "db:migrate")
1087
+ end
1088
+ end
1089
+ end
1090
+
999
1091
  describe "#redeploy" do
1000
1092
  before do
1001
1093
  @user = Shelly::User.new
@@ -188,11 +188,11 @@ describe Shelly::Client do
188
188
  end
189
189
  end
190
190
 
191
- describe "#run" do
192
- it "should send post request with app code_name and code" do
193
- FakeWeb.register_uri(:post, api_url("apps/staging-foo/run"),
194
- :body => {:result => "4"}.to_json)
195
- response = @client.run("staging-foo", "2 + 2")
191
+ describe "#command" do
192
+ it "should send post request with app code_name, body and type" do
193
+ @client.should_receive(:post).with("/apps/staging-foo/command",
194
+ {:body => "2 + 2", :type => :ruby}).and_return({"result" => "4"})
195
+ response = @client.command("staging-foo", "2 + 2", :ruby)
196
196
  response.should == {"result" => "4"}
197
197
  end
198
198
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.46.pre3
4
+ version: 0.0.46.pre4
5
5
  prerelease: 7
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-19 00:00:00.000000000Z
12
+ date: 2012-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70197902930340 !ruby/object:Gem::Requirement
16
+ requirement: &70120545982000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70197902930340
24
+ version_requirements: *70120545982000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70197902929860 !ruby/object:Gem::Requirement
27
+ requirement: &70120545935800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70197902929860
35
+ version_requirements: *70120545935800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: guard
38
- requirement: &70197902929420 !ruby/object:Gem::Requirement
38
+ requirement: &70120545881600 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70197902929420
46
+ version_requirements: *70120545881600
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard-rspec
49
- requirement: &70197902929000 !ruby/object:Gem::Requirement
49
+ requirement: &70120545838560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70197902929000
57
+ version_requirements: *70120545838560
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &70197902928580 !ruby/object:Gem::Requirement
60
+ requirement: &70120545784360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70197902928580
68
+ version_requirements: *70120545784360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby_gntp
71
- requirement: &70197902928120 !ruby/object:Gem::Requirement
71
+ requirement: &70120545753800 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70197902928120
79
+ version_requirements: *70120545753800
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rb-fsevent
82
- requirement: &70197902927700 !ruby/object:Gem::Requirement
82
+ requirement: &70120545706400 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70197902927700
90
+ version_requirements: *70120545706400
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: fakefs
93
- requirement: &70197902927280 !ruby/object:Gem::Requirement
93
+ requirement: &70120545675300 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70197902927280
101
+ version_requirements: *70120545675300
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: fakeweb
104
- requirement: &70197902926860 !ruby/object:Gem::Requirement
104
+ requirement: &70120545631340 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70197902926860
112
+ version_requirements: *70120545631340
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: wijet-thor
115
- requirement: &70197902912840 !ruby/object:Gem::Requirement
115
+ requirement: &70120545582080 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 0.14.7
121
121
  type: :runtime
122
122
  prerelease: false
123
- version_requirements: *70197902912840
123
+ version_requirements: *70120545582080
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rest-client
126
- requirement: &70197902912420 !ruby/object:Gem::Requirement
126
+ requirement: &70120545531700 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: '0'
132
132
  type: :runtime
133
133
  prerelease: false
134
- version_requirements: *70197902912420
134
+ version_requirements: *70120545531700
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: json
137
- requirement: &70197902911960 !ruby/object:Gem::Requirement
137
+ requirement: &70120545490640 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ! '>='
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: '0'
143
143
  type: :runtime
144
144
  prerelease: false
145
- version_requirements: *70197902911960
145
+ version_requirements: *70120545490640
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: wijet-launchy
148
- requirement: &70197902911500 !ruby/object:Gem::Requirement
148
+ requirement: &70120545446820 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ! '>='
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: '0'
154
154
  type: :runtime
155
155
  prerelease: false
156
- version_requirements: *70197902911500
156
+ version_requirements: *70120545446820
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: progressbar
159
- requirement: &70197902911060 !ruby/object:Gem::Requirement
159
+ requirement: &70120545425460 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ! '>='
@@ -164,7 +164,7 @@ dependencies:
164
164
  version: '0'
165
165
  type: :runtime
166
166
  prerelease: false
167
- version_requirements: *70197902911060
167
+ version_requirements: *70120545425460
168
168
  description: Tool for managing applications and clouds at shellycloud.com
169
169
  email:
170
170
  - support@shellycloud.com