shelly 0.0.46.pre3 → 0.0.46.pre4

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