shelly 0.0.45 → 0.0.46.pre

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"
@@ -234,9 +234,8 @@ module Shelly
234
234
  say "You have been successfully logged out" if user.delete_credentials
235
235
  end
236
236
 
237
- desc "execute [CODE]", "Run code on one of application servers"
238
- method_option :cloud, :type => :string, :aliases => "-c",
239
- :desc => "Specify which cloud to run code for"
237
+ desc "execute CODE", "Run code on one of application servers"
238
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
240
239
  long_desc "Run code given in parameter on one of application servers. If a file name is given, run contents of that file."
241
240
  def execute(file_name_or_code)
242
241
  cloud = options[:cloud]
@@ -253,6 +252,18 @@ module Shelly
253
252
  end
254
253
  end
255
254
 
255
+ desc "rake TASK", "Run rake task"
256
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
257
+ def rake(task = nil)
258
+ task = rake_args.join(" ")
259
+ multiple_clouds(options[:cloud], "rake #{task}")
260
+ result = @app.rake(task)
261
+ say result
262
+ rescue Client::APIException => e
263
+ raise unless e[:message] == "App not running"
264
+ say_error "Cloud #{@app} is not running. Cannot run rake task."
265
+ end
266
+
256
267
  desc "redeploy", "Redeploy application"
257
268
  method_option :cloud, :type => :string, :aliases => "-c",
258
269
  :desc => "Specify which cloud to redeploy application for"
@@ -277,6 +288,23 @@ module Shelly
277
288
 
278
289
  # FIXME: move to helpers
279
290
  no_tasks do
291
+ # Returns valid arguments for rake, removes shelly gem arguments
292
+ def rake_args(args = ARGV)
293
+ skip_next = false
294
+ [].tap do |out|
295
+ args.each do |arg|
296
+ case arg
297
+ when "rake", "--debug"
298
+ when "--cloud", "-c"
299
+ skip_next = true
300
+ else
301
+ out << arg unless skip_next
302
+ skip_next = false
303
+ end
304
+ end
305
+ end
306
+ end
307
+
280
308
  def check_options(options)
281
309
  unless options.empty?
282
310
  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.45"
2
+ VERSION = "0.0.46.pre"
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
@@ -936,9 +937,13 @@ OUT
936
937
  hooks(@main, :execute).should include(:logged_in?)
937
938
  end
938
939
 
940
+ it "should ensure cloudfile present" do
941
+ hooks(@main, :execute).should include(:cloudfile_present?)
942
+ end
943
+
939
944
  context "single cloud in Cloudfile" do
940
945
  it "should execute code for the cloud" do
941
- @client.should_receive(:run).with("foo-production", "User.count").
946
+ @client.should_receive(:command).with("foo-production", "User.count", :ruby).
942
947
  and_return({"result" => "3"})
943
948
  $stdout.should_receive(:puts).with("3")
944
949
  invoke(@main, :execute, "to_execute.rb")
@@ -963,7 +968,7 @@ OUT
963
968
  end
964
969
 
965
970
  it "should fetch from command line which cloud to start" do
966
- @client.should_receive(:run).with("foo-staging", "User.count").
971
+ @client.should_receive(:command).with("foo-staging", "User.count", :ruby).
967
972
  and_return({"result" => "3"})
968
973
  $stdout.should_receive(:puts).with("3")
969
974
  @main.options = {:cloud => "foo-staging"}
@@ -971,7 +976,7 @@ OUT
971
976
  end
972
977
 
973
978
  it "should run code when no file from parameter is found" do
974
- @client.should_receive(:run).with("foo-staging", "2 + 2").
979
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby).
975
980
  and_return({"result" => "4"})
976
981
  $stdout.should_receive(:puts).with("4")
977
982
  @main.options = {:cloud => "foo-staging"}
@@ -979,9 +984,9 @@ OUT
979
984
  end
980
985
  end
981
986
 
982
- context "cloud is not running" do
987
+ context "cloud is not in running state" do
983
988
  it "should print error" do
984
- @client.should_receive(:run).with("foo-staging", "2 + 2").
989
+ @client.should_receive(:command).with("foo-staging", "2 + 2", :ruby).
985
990
  and_raise(Shelly::Client::APIException.new(
986
991
  {"message" => "App not running"}, 504))
987
992
  $stdout.should_receive(:puts).
@@ -992,6 +997,93 @@ OUT
992
997
  end
993
998
  end
994
999
 
1000
+ describe "#rake" do
1001
+ before do
1002
+ FileUtils.mkdir_p("/projects/foo")
1003
+ Dir.chdir("/projects/foo")
1004
+ File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
1005
+ @user = Shelly::User.new
1006
+ @user.stub(:token)
1007
+ Shelly::User.stub(:new).and_return(@user)
1008
+ @app = Shelly::App.new
1009
+ Shelly::App.stub(:new).and_return(@app)
1010
+ @main.stub(:rake_args).and_return(%w(db:migrate))
1011
+ end
1012
+
1013
+ it "should ensure user has logged in" do
1014
+ hooks(@main, :rake).should include(:logged_in?)
1015
+ end
1016
+
1017
+ it "should ensure cloudfile present" do
1018
+ hooks(@main, :execute).should include(:cloudfile_present?)
1019
+ end
1020
+
1021
+ it "should invoke :command on app with rake task" do
1022
+ @client.should_receive(:command).with("foo-production", "db:migrate", :rake).and_return("result" => "OK")
1023
+ $stdout.should_receive(:puts).with("OK")
1024
+ invoke(@main, :rake, "db:migrate")
1025
+ end
1026
+
1027
+ it "should pass rake arguments to the client" do
1028
+ @main.stub(:rake_args).and_return(%w(-T db:schema))
1029
+ @client.should_receive(:command).with("foo-production", "-T db:schema", :rake).and_return("result" => "OK")
1030
+ $stdout.should_receive(:puts).with("OK")
1031
+ invoke(@main, :rake, nil)
1032
+ end
1033
+
1034
+ describe "#rake_args" do
1035
+ before { @main.unstub!(:rake_args) }
1036
+
1037
+ it "should return Array of rake arguments (skipping shelly gem arguments)" do
1038
+ argv = %w(rake -T db --cloud foo-production --debug)
1039
+ @main.rake_args(argv).should == %w(-T db)
1040
+ end
1041
+
1042
+ it "should take ARGV as default default argument" do
1043
+ # Rather poor, I test if method without args returns the same as method with ARGV
1044
+ @main.rake_args.should == @main.rake_args(ARGV)
1045
+ end
1046
+ end
1047
+
1048
+ context "cloud is not in running state" do
1049
+ it "should print error" do
1050
+ @client.should_receive(:command).with("foo-staging", "db:migrate", :rake).
1051
+ and_raise(Shelly::Client::APIException.new(
1052
+ {"message" => "App not running"}, 504))
1053
+ $stdout.should_receive(:puts).
1054
+ with(red "Cloud foo-staging is not running. Cannot run rake task.")
1055
+ @main.options = {:cloud => "foo-staging"}
1056
+ lambda { invoke(@main, :rake, "db:migrate") }.should raise_error(SystemExit)
1057
+ end
1058
+ end
1059
+
1060
+ context "multiple clouds in Cloudfile" do
1061
+ before do
1062
+ File.open("Cloudfile", 'w') {|f|
1063
+ f.write("foo-staging:\nfoo-production:\n") }
1064
+ end
1065
+
1066
+ it "should show information to run rake task for specific cloud and exit" do
1067
+ $stdout.should_receive(:puts).
1068
+ with(red "You have multiple clouds in Cloudfile.")
1069
+ $stdout.should_receive(:puts).
1070
+ with("Select cloud using `shelly rake db:migrate --cloud foo-production`")
1071
+ $stdout.should_receive(:puts).with("Available clouds:")
1072
+ $stdout.should_receive(:puts).with(" * foo-production")
1073
+ $stdout.should_receive(:puts).with(" * foo-staging")
1074
+ lambda { invoke(@main, :rake, "db:migrate") }.should raise_error(SystemExit)
1075
+ end
1076
+
1077
+ it "should fetch from command line for which cloud run rake task" do
1078
+ @client.should_receive(:command).with("foo-staging", "db:migrate", :rake).
1079
+ and_return({"result" => "3"})
1080
+ $stdout.should_receive(:puts).with("3")
1081
+ @main.options = {:cloud => "foo-staging"}
1082
+ invoke(@main, :rake, "db:migrate")
1083
+ end
1084
+ end
1085
+ end
1086
+
995
1087
  describe "#redeploy" do
996
1088
  before do
997
1089
  @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,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.45
5
- prerelease:
4
+ version: 0.0.46.pre
5
+ prerelease: 7
6
6
  platform: ruby
7
7
  authors:
8
8
  - Shelly Cloud team
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-10 00:00:00.000000000 Z
12
+ date: 2012-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70242679918440 !ruby/object:Gem::Requirement
16
+ requirement: &70183697675760 !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: *70242679918440
24
+ version_requirements: *70183697675760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70242679920240 !ruby/object:Gem::Requirement
27
+ requirement: &70183697629560 !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: *70242679920240
35
+ version_requirements: *70183697629560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: guard
38
- requirement: &70242679876100 !ruby/object:Gem::Requirement
38
+ requirement: &70183697575360 !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: *70242679876100
46
+ version_requirements: *70183697575360
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard-rspec
49
- requirement: &70242679792880 !ruby/object:Gem::Requirement
49
+ requirement: &70183697532320 !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: *70242679792880
57
+ version_requirements: *70183697532320
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &70242679772100 !ruby/object:Gem::Requirement
60
+ requirement: &70183697478100 !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: *70242679772100
68
+ version_requirements: *70183697478100
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby_gntp
71
- requirement: &70242679713860 !ruby/object:Gem::Requirement
71
+ requirement: &70183697447560 !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: *70242679713860
79
+ version_requirements: *70183697447560
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rb-fsevent
82
- requirement: &70242679679780 !ruby/object:Gem::Requirement
82
+ requirement: &70183697400160 !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: *70242679679780
90
+ version_requirements: *70183697400160
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: fakefs
93
- requirement: &70242679649600 !ruby/object:Gem::Requirement
93
+ requirement: &70183697369060 !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: *70242679649600
101
+ version_requirements: *70183697369060
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: fakeweb
104
- requirement: &70242679605320 !ruby/object:Gem::Requirement
104
+ requirement: &70183697325100 !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: *70242679605320
112
+ version_requirements: *70183697325100
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: wijet-thor
115
- requirement: &70242679548560 !ruby/object:Gem::Requirement
115
+ requirement: &70183697275820 !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: *70242679548560
123
+ version_requirements: *70183697275820
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rest-client
126
- requirement: &70242679511680 !ruby/object:Gem::Requirement
126
+ requirement: &70183697225460 !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: *70242679511680
134
+ version_requirements: *70183697225460
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: json
137
- requirement: &70242679459460 !ruby/object:Gem::Requirement
137
+ requirement: &70183697184400 !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: *70242679459460
145
+ version_requirements: *70183697184400
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: wijet-launchy
148
- requirement: &70242679417320 !ruby/object:Gem::Requirement
148
+ requirement: &70183697140580 !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: *70242679417320
156
+ version_requirements: *70183697140580
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: progressbar
159
- requirement: &70242679388380 !ruby/object:Gem::Requirement
159
+ requirement: &70183697119220 !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: *70242679388380
167
+ version_requirements: *70183697119220
168
168
  description: Tool for managing applications and clouds at shellycloud.com
169
169
  email:
170
170
  - support@shellycloud.com
@@ -237,9 +237,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
237
  required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  none: false
239
239
  requirements:
240
- - - ! '>='
240
+ - - ! '>'
241
241
  - !ruby/object:Gem::Version
242
- version: '0'
242
+ version: 1.3.1
243
243
  requirements: []
244
244
  rubyforge_project: shelly
245
245
  rubygems_version: 1.8.10