shelly 0.0.44.pre → 0.0.44.pre2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/shelly/app.rb CHANGED
@@ -138,6 +138,19 @@ module Shelly
138
138
  shelly.app_delete_config(code_name, path)
139
139
  end
140
140
 
141
+ # returns result of execution of given code, or false when app was not
142
+ # running
143
+ def run(file_name_or_code)
144
+ code = if File.exists?(file_name_or_code)
145
+ File.read(file_name_or_code)
146
+ else
147
+ file_name_or_code
148
+ end
149
+
150
+ response = shelly.run(code_name, code)
151
+ response["result"]
152
+ end
153
+
141
154
  def attributes
142
155
  @attributes ||= shelly.app(code_name)
143
156
  end
@@ -40,6 +40,7 @@ module Shelly
40
40
  end
41
41
  end
42
42
 
43
+ # FIXME: Check if path argument is present via Thor (mandatory arguments)
43
44
  method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
44
45
  desc "show PATH", "View configuration file"
45
46
  def show(path = nil)
@@ -67,7 +68,9 @@ module Shelly
67
68
  output = open_editor(path)
68
69
  multiple_clouds(options[:cloud], "create #{path}")
69
70
  @app.create_config(path, output)
70
- say "File '#{path}' created, it will be used after next code deploy", :green
71
+ say "File '#{path}' created.", :green
72
+ say "To make changes to running application redeploy it using:"
73
+ say "`shelly redeploy --cloud #{@app}`"
71
74
  rescue Client::NotFoundException => e
72
75
  raise unless e.resource == :cloud
73
76
  say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
@@ -85,7 +88,9 @@ module Shelly
85
88
  config = @app.config(path)
86
89
  content = open_editor(config["path"], config["content"])
87
90
  @app.update_config(path, content)
88
- say "File '#{config["path"]}' updated, it will be used after next code deploy", :green
91
+ say "File '#{config["path"]}' updated.", :green
92
+ say "To make changes to running application redeploy it using:"
93
+ say "`shelly redeploy --cloud #{@app}`"
89
94
  rescue Client::NotFoundException => e
90
95
  case e.resource
91
96
  when :cloud
@@ -108,7 +113,9 @@ module Shelly
108
113
  answer = yes?("Are you sure you want to delete 'path' (yes/no): ")
109
114
  if answer
110
115
  @app.delete_config(path)
111
- say "File deleted, redeploy your cloud to make changes", :green
116
+ say "File '#{path}' deleted.", :green
117
+ say "To make changes to running application redeploy it using:"
118
+ say "`shelly redeploy --cloud #{@app}`"
112
119
  else
113
120
  say "File not deleted"
114
121
  end
@@ -16,7 +16,7 @@ module Shelly
16
16
  check_unknown_options!
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]
19
+ before_hook :logged_in?, :only => [:add, :list, :start, :stop, :logs, :delete, :ip, :logout, :execute]
20
20
  before_hook :inside_git_repository?, :only => [:add]
21
21
  before_hook :cloudfile_present?, :only => [:logs, :stop, :start, :ip]
22
22
 
@@ -234,9 +234,24 @@ 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
+ long_desc "Run code given in parameter on one of application servers. If a file name is given, run contents of that file."
239
+ def execute(file_name_or_code)
240
+ cloud = options[:cloud]
241
+ multiple_clouds(cloud, "execute")
242
+
243
+ result = @app.run(file_name_or_code)
244
+ say result
245
+
246
+ rescue Client::APIException => e
247
+ if e[:message] == "App not running"
248
+ say_error "Cloud #{@app} is not running. Cannot run code."
249
+ else
250
+ raise
251
+ end
252
+ end
253
+
237
254
  desc "redeploy", "Redeploy application"
238
- method_option :cloud, :type => :string, :aliases => "-c",
239
- :desc => "Specify which cloud to redeploy application for"
240
255
  def redeploy
241
256
  multiple_clouds(options[:cloud], "redeploy")
242
257
  @app.redeploy
data/lib/shelly/client.rb CHANGED
@@ -115,6 +115,10 @@ 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)
120
+ end
121
+
118
122
  def deploy_logs(cloud)
119
123
  get("/apps/#{cloud}/deployment_logs")
120
124
  end
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.44.pre"
2
+ VERSION = "0.0.44.pre2"
3
3
  end
@@ -288,6 +288,26 @@ config
288
288
  end
289
289
  end
290
290
 
291
+ describe "#run" do
292
+ before do
293
+ @response = {
294
+ "result" => "4"
295
+ }
296
+ @client.stub(:run).and_return(@response)
297
+ File.open("to_run.rb", 'w') {|f| f.write("User.count\n") }
298
+ end
299
+
300
+ it "should return result of executed code" do
301
+ @client.should_receive(:run).with("foo-staging", "2 + 2")
302
+ @app.run("2 + 2").should == "4"
303
+ end
304
+
305
+ it "should send contents of file when file exists" do
306
+ @client.should_receive(:run).with("foo-staging", "User.count\n")
307
+ @app.run("to_run.rb")
308
+ end
309
+ end
310
+
291
311
  describe "#to_s" do
292
312
  it "should return code_name" do
293
313
  @app.to_s.should == "foo-staging"
@@ -145,7 +145,9 @@ describe Shelly::CLI::Config do
145
145
  it "should create file" do
146
146
  @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
147
147
  @client.should_receive(:app_create_config).with("foo-staging", "path", "\n").and_return({})
148
- $stdout.should_receive(:puts).with(green "File 'path' created, it will be used after next code deploy")
148
+ $stdout.should_receive(:puts).with(green "File 'path' created.")
149
+ $stdout.should_receive(:puts).with("To make changes to running application redeploy it using:")
150
+ $stdout.should_receive(:puts).with("`shelly redeploy --cloud foo-staging`")
149
151
  invoke(@config, :create, "path")
150
152
  end
151
153
 
@@ -208,7 +210,9 @@ describe Shelly::CLI::Config do
208
210
  @client.should_receive(:app_config).with("foo-staging", "path").and_return({"path" => "test.rb", "content" => "example content"})
209
211
  @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
210
212
  @client.should_receive(:app_update_config).with("foo-staging", "path", "example content\n").and_return({"path" => "test.rb", "content" => "example content"})
211
- $stdout.should_receive(:puts).with(green "File 'test.rb' updated, it will be used after next code deploy")
213
+ $stdout.should_receive(:puts).with(green "File 'test.rb' updated.")
214
+ $stdout.should_receive(:puts).with("To make changes to running application redeploy it using:")
215
+ $stdout.should_receive(:puts).with("`shelly redeploy --cloud foo-staging`")
212
216
  invoke(@config, :edit, "path")
213
217
  end
214
218
 
@@ -286,7 +290,9 @@ describe Shelly::CLI::Config do
286
290
 
287
291
  it "should delete configuration file" do
288
292
  @client.should_receive(:app_delete_config).with("foo-staging", "path").and_return({})
289
- $stdout.should_receive(:puts).with(green "File deleted, redeploy your cloud to make changes")
293
+ $stdout.should_receive(:puts).with(green "File 'path' deleted.")
294
+ $stdout.should_receive(:puts).with("To make changes to running application redeploy it using:")
295
+ $stdout.should_receive(:puts).with("`shelly redeploy --cloud foo-staging`")
290
296
  fake_stdin(["y"]) do
291
297
  invoke(@config, :delete, "path")
292
298
  end
@@ -313,7 +319,9 @@ describe Shelly::CLI::Config do
313
319
 
314
320
  it "should use cloud specified by parameter" do
315
321
  @client.should_receive(:app_delete_config).with("foo-production", "path").and_return({})
316
- $stdout.should_receive(:puts).with(green "File deleted, redeploy your cloud to make changes")
322
+ $stdout.should_receive(:puts).with(green "File 'path' deleted.")
323
+ $stdout.should_receive(:puts).with("To make changes to running application redeploy it using:")
324
+ $stdout.should_receive(:puts).with("`shelly redeploy --cloud foo-production`")
317
325
  @config.options = {:cloud => "foo-production"}
318
326
  fake_stdin(["y"]) do
319
327
  invoke(@config, :delete, "path")
@@ -29,6 +29,7 @@ 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
33
  shelly help [TASK] # Describe available tasks or one specific task
33
34
  shelly ip # List cloud's IP addresses
34
35
  shelly list # List available clouds
@@ -916,6 +917,81 @@ OUT
916
917
  end
917
918
  end
918
919
 
920
+ describe "#execute" do
921
+ before do
922
+ FileUtils.mkdir_p("/projects/foo")
923
+ Dir.chdir("/projects/foo")
924
+ File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
925
+ @user = Shelly::User.new
926
+ @user.stub(:token)
927
+ Shelly::User.stub(:new).and_return(@user)
928
+ @client.stub(:apps).and_return([{"code_name" => "foo-production"},
929
+ {"code_name" => "foo-staging"}])
930
+ @app = Shelly::App.new
931
+ Shelly::App.stub(:new).and_return(@app)
932
+ File.open("to_execute.rb", 'w') {|f| f.write("User.count") }
933
+ end
934
+
935
+ it "should ensure user has logged in" do
936
+ hooks(@main, :execute).should include(:logged_in?)
937
+ end
938
+
939
+ context "single cloud in Cloudfile" do
940
+ it "should execute code for the cloud" do
941
+ @client.should_receive(:run).with("foo-production", "User.count").
942
+ and_return({"result" => "3"})
943
+ $stdout.should_receive(:puts).with("3")
944
+ invoke(@main, :execute, "to_execute.rb")
945
+ end
946
+ end
947
+
948
+ context "multiple clouds in Cloudfile" do
949
+ before do
950
+ File.open("Cloudfile", 'w') {|f|
951
+ f.write("foo-staging:\nfoo-production:\n") }
952
+ end
953
+
954
+ it "should show information to print logs for specific cloud and exit" do
955
+ $stdout.should_receive(:puts).
956
+ with(red "You have multiple clouds in Cloudfile.")
957
+ $stdout.should_receive(:puts).
958
+ with("Select cloud using `shelly execute --cloud foo-production`")
959
+ $stdout.should_receive(:puts).with("Available clouds:")
960
+ $stdout.should_receive(:puts).with(" * foo-production")
961
+ $stdout.should_receive(:puts).with(" * foo-staging")
962
+ lambda { invoke(@main, :execute, "to_execute.rb") }.should raise_error(SystemExit)
963
+ end
964
+
965
+ it "should fetch from command line which cloud to start" do
966
+ @client.should_receive(:run).with("foo-staging", "User.count").
967
+ and_return({"result" => "3"})
968
+ $stdout.should_receive(:puts).with("3")
969
+ @main.options = {:cloud => "foo-staging"}
970
+ invoke(@main, :execute, "to_execute.rb")
971
+ end
972
+
973
+ it "should run code when no file from parameter is found" do
974
+ @client.should_receive(:run).with("foo-staging", "2 + 2").
975
+ and_return({"result" => "4"})
976
+ $stdout.should_receive(:puts).with("4")
977
+ @main.options = {:cloud => "foo-staging"}
978
+ invoke(@main, :execute, "2 + 2")
979
+ end
980
+ end
981
+
982
+ context "cloud is not running" do
983
+ it "should print error" do
984
+ @client.should_receive(:run).with("foo-staging", "2 + 2").
985
+ and_raise(Shelly::Client::APIException.new(
986
+ {"message" => "App not running"}, 504))
987
+ $stdout.should_receive(:puts).
988
+ with(red "Cloud foo-staging is not running. Cannot run code.")
989
+ @main.options = {:cloud => "foo-staging"}
990
+ lambda { invoke(@main, :execute, "2 + 2") }.should raise_error(SystemExit)
991
+ end
992
+ end
993
+ end
994
+
919
995
  describe "#redeploy" do
920
996
  before do
921
997
  @user = Shelly::User.new
@@ -188,6 +188,15 @@ 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")
196
+ response.should == {"result" => "4"}
197
+ end
198
+ end
199
+
191
200
  describe "#send_invitation" do
192
201
  it "should send post with developer's email" do
193
202
  FakeWeb.register_uri(:post, api_url("apps/staging-foo/collaborations"), :body => {}.to_json)
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.44.pre
4
+ version: 0.0.44.pre2
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-08 00:00:00.000000000 Z
12
+ date: 2012-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70206898312780 !ruby/object:Gem::Requirement
16
+ requirement: &70274550076140 !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: *70206898312780
24
+ version_requirements: *70274550076140
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70206898266580 !ruby/object:Gem::Requirement
27
+ requirement: &70274550075720 !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: *70206898266580
35
+ version_requirements: *70274550075720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: guard
38
- requirement: &70206898212380 !ruby/object:Gem::Requirement
38
+ requirement: &70274550075300 !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: *70206898212380
46
+ version_requirements: *70274550075300
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard-rspec
49
- requirement: &70206898169340 !ruby/object:Gem::Requirement
49
+ requirement: &70274550074880 !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: *70206898169340
57
+ version_requirements: *70274550074880
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &70206898115120 !ruby/object:Gem::Requirement
60
+ requirement: &70274550074460 !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: *70206898115120
68
+ version_requirements: *70274550074460
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby_gntp
71
- requirement: &70206898084560 !ruby/object:Gem::Requirement
71
+ requirement: &70274550074000 !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: *70206898084560
79
+ version_requirements: *70274550074000
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rb-fsevent
82
- requirement: &70206898037160 !ruby/object:Gem::Requirement
82
+ requirement: &70274554592480 !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: *70206898037160
90
+ version_requirements: *70274554592480
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: fakefs
93
- requirement: &70206898006080 !ruby/object:Gem::Requirement
93
+ requirement: &70274554592060 !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: *70206898006080
101
+ version_requirements: *70274554592060
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: fakeweb
104
- requirement: &70206897962100 !ruby/object:Gem::Requirement
104
+ requirement: &70274554591640 !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: *70206897962100
112
+ version_requirements: *70274554591640
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: wijet-thor
115
- requirement: &70206897912840 !ruby/object:Gem::Requirement
115
+ requirement: &70274554591140 !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: *70206897912840
123
+ version_requirements: *70274554591140
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rest-client
126
- requirement: &70206897862480 !ruby/object:Gem::Requirement
126
+ requirement: &70274554590720 !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: *70206897862480
134
+ version_requirements: *70274554590720
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: json
137
- requirement: &70206897821420 !ruby/object:Gem::Requirement
137
+ requirement: &70274554590260 !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: *70206897821420
145
+ version_requirements: *70274554590260
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: wijet-launchy
148
- requirement: &70206897777600 !ruby/object:Gem::Requirement
148
+ requirement: &70274554589840 !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: *70206897777600
156
+ version_requirements: *70274554589840
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: progressbar
159
- requirement: &70206897756220 !ruby/object:Gem::Requirement
159
+ requirement: &70274554589400 !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: *70206897756220
167
+ version_requirements: *70274554589400
168
168
  description: Tool for managing applications and clouds at shellycloud.com
169
169
  email:
170
170
  - support@shellycloud.com
@@ -234,6 +234,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
234
234
  - - ! '>='
235
235
  - !ruby/object:Gem::Version
236
236
  version: '0'
237
+ segments:
238
+ - 0
239
+ hash: 2757033815683066563
237
240
  required_rubygems_version: !ruby/object:Gem::Requirement
238
241
  none: false
239
242
  requirements:
@@ -242,7 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
242
245
  version: 1.3.1
243
246
  requirements: []
244
247
  rubyforge_project: shelly
245
- rubygems_version: 1.8.10
248
+ rubygems_version: 1.8.15
246
249
  signing_key:
247
250
  specification_version: 3
248
251
  summary: Shelly Cloud command line tool