shelly 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
data/lib/shelly/app.rb CHANGED
@@ -170,7 +170,7 @@ module Shelly
170
170
  end
171
171
 
172
172
  def rake(task)
173
- ssh("rake_runner \"#{task}\"")
173
+ ssh_command("rake_runner \"#{task}\"")
174
174
  end
175
175
 
176
176
  def attributes
@@ -213,22 +213,35 @@ module Shelly
213
213
  Launchy.open("http://#{attributes["domain"]}")
214
214
  end
215
215
 
216
- def node_and_port
217
- shelly.node_and_port(code_name)
216
+ def console
217
+ ssh_command
218
218
  end
219
219
 
220
- def console
221
- ssh
220
+ def upload(source)
221
+ rsync(source, "#{ssh['node_ip']}:/srv/glusterfs/disk")
222
+ end
223
+
224
+ def download(relative_source, destination)
225
+ source = File.join("#{ssh['node_ip']}:/srv/glusterfs/disk", relative_source)
226
+ rsync(source, destination)
227
+ end
228
+
229
+ private
230
+
231
+ def ssh
232
+ @ssh ||= shelly.node_and_port(code_name)
233
+ end
234
+
235
+ def ssh_command(command = "")
236
+ exec "ssh #{ssh_options} #{ssh['node_ip']} #{command}"
222
237
  end
223
238
 
224
- def ssh(command = "")
225
- params = node_and_port
226
- exec "ssh -o StrictHostKeyChecking=no -p #{params['port']} -l #{params['user']} #{params['node_ip']} #{command}"
239
+ def ssh_options
240
+ "-o StrictHostKeyChecking=no -p #{ssh['port']} -l #{ssh['user']}"
227
241
  end
228
242
 
229
- def upload(path)
230
- params = node_and_port
231
- exec "rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p #{params['port']}' --progress #{path} #{params['user']}@#{params['node_ip']}:/srv/glusterfs/disk"
243
+ def rsync(source, destination)
244
+ exec "rsync -avz -e 'ssh #{ssh_options}' --progress #{source} #{destination}"
232
245
  end
233
246
  end
234
247
  end
@@ -28,9 +28,6 @@ module Shelly
28
28
  else
29
29
  say "No database backups available"
30
30
  end
31
- rescue Client::NotFoundException => e
32
- raise unless e.resource == :cloud
33
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
34
31
  end
35
32
 
36
33
  desc "get [FILENAME]", "Download database backup"
@@ -48,14 +45,9 @@ module Shelly
48
45
  say_new_line
49
46
  say "Backup file saved to #{backup.filename}", :green
50
47
  rescue Client::NotFoundException => e
51
- case e.resource
52
- when :cloud
53
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
54
- when :database_backup
55
- say_error "Backup not found", :with_exit => false
56
- say "You can list available backups with `shelly backup list` command"
57
- else; raise
58
- end
48
+ raise unless e.resource == :database_backup
49
+ say_error "Backup not found", :with_exit => false
50
+ say "You can list available backups with `shelly backup list` command"
59
51
  end
60
52
 
61
53
  desc "create [DB_KIND]", "Create backup of given database"
@@ -70,9 +62,6 @@ module Shelly
70
62
  "the backup process to finish and the backup to show up in backups list.", :green
71
63
  rescue Client::ValidationException => e
72
64
  say_error e[:message]
73
- rescue Client::NotFoundException => e
74
- raise unless e.resource == :cloud
75
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
76
65
  end
77
66
 
78
67
  desc "restore FILENAME", "Restore database to state from given backup"
@@ -86,14 +75,9 @@ module Shelly
86
75
  say_new_line
87
76
  say "Restore has been scheduled. Wait a few minutes till database is restored.", :green
88
77
  rescue Client::NotFoundException => e
89
- case e.resource
90
- when :cloud
91
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
92
- when :database_backup
93
- say_error "Backup not found", :with_exit => false
94
- say "You can list available backups with `shelly backup list` command"
95
- else; raise
96
- end
78
+ raise unless e.resource == :database_backup
79
+ say_error "Backup not found", :with_exit => false
80
+ say "You can list available backups with `shelly backup list` command"
97
81
  end
98
82
  end
99
83
  end
@@ -30,9 +30,6 @@ module Shelly
30
30
  else
31
31
  say "Cloud #{cloud} has no configuration files"
32
32
  end
33
- rescue Client::NotFoundException => e
34
- raise unless e.resource == :cloud
35
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
36
33
  end
37
34
 
38
35
  desc "show PATH", "View configuration file"
@@ -42,14 +39,9 @@ module Shelly
42
39
  say "Content of #{config["path"]}:", :green
43
40
  say config["content"]
44
41
  rescue Client::NotFoundException => e
45
- case e.resource
46
- when :cloud
47
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
48
- when :config
49
- say_error "Config '#{path}' not found", :with_exit => false
50
- say_error "You can list available config files with `shelly config list --cloud #{app}`"
51
- else raise
52
- end
42
+ raise unless e.resource == :config
43
+ say_error "Config '#{path}' not found", :with_exit => false
44
+ say_error "You can list available config files with `shelly config list --cloud #{app}`"
53
45
  end
54
46
 
55
47
  map "new" => :create
@@ -61,9 +53,6 @@ module Shelly
61
53
  say "File '#{path}' created.", :green
62
54
  say "To make changes to running application redeploy it using:"
63
55
  say "`shelly redeploy --cloud #{app}`"
64
- rescue Client::NotFoundException => e
65
- raise unless e.resource == :cloud
66
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
67
56
  rescue Client::ValidationException => e
68
57
  e.each_error { |error| say_error error, :with_exit => false }
69
58
  exit 1
@@ -81,14 +70,9 @@ module Shelly
81
70
  say "To make changes to running application redeploy it using:"
82
71
  say "`shelly redeploy --cloud #{app}`"
83
72
  rescue Client::NotFoundException => e
84
- case e.resource
85
- when :cloud
86
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
87
- when :config
88
- say_error "Config '#{path}' not found", :with_exit => false
89
- say_error "You can list available config files with `shelly config list --cloud #{app}`"
90
- else raise
91
- end
73
+ raise unless e.resource == :config
74
+ say_error "Config '#{path}' not found", :with_exit => false
75
+ say_error "You can list available config files with `shelly config list --cloud #{app}`"
92
76
  rescue Client::ValidationException => e
93
77
  e.each_error { |error| say_error error, :with_exit => false }
94
78
  exit 1
@@ -108,14 +92,9 @@ module Shelly
108
92
  say "File not deleted"
109
93
  end
110
94
  rescue Client::NotFoundException => e
111
- case e.resource
112
- when :cloud
113
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
114
- when :config
115
- say_error "Config '#{path}' not found", :with_exit => false
116
- say_error "You can list available config files with `shelly config list --cloud #{app}`"
117
- else raise
118
- end
95
+ raise unless e.resource == :config
96
+ say_error "Config '#{path}' not found", :with_exit => false
97
+ say_error "You can list available config files with `shelly config list --cloud #{app}`"
119
98
  end
120
99
 
121
100
  no_tasks do
@@ -145,7 +124,6 @@ module Shelly
145
124
  say_error "Please set EDITOR environment variable"
146
125
  end
147
126
  end
148
-
149
127
  end
150
128
  end
151
129
  end
@@ -22,9 +22,6 @@ module Shelly
22
22
  else
23
23
  say "No deploy logs available"
24
24
  end
25
- rescue Client::NotFoundException => e
26
- raise unless e.resource == :cloud
27
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
28
25
  end
29
26
 
30
27
  desc "show LOG", "Show specific deploy log"
@@ -49,13 +46,8 @@ module Shelly
49
46
  say("Starting thin", :green); say(content["thin_restart"])
50
47
  end
51
48
  rescue Client::NotFoundException => e
52
- case e.resource
53
- when :cloud
54
- say_error "You have no access to '#{app.code_name}' cloud defined in Cloudfile"
55
- when :log
56
- say_error "Log not found, list all deploy logs using `shelly deploys list --cloud=#{app.code_name}`"
57
- else raise
58
- end
49
+ raise unless e.resource == :log
50
+ say_error "Log not found, list all deploy logs using `shelly deploys list --cloud=#{app.code_name}`"
59
51
  end
60
52
 
61
53
  no_tasks do
@@ -0,0 +1,43 @@
1
+ require "shelly/cli/command"
2
+
3
+ module Shelly
4
+ module CLI
5
+ class Files < Command
6
+ namespace :files
7
+ include Helpers
8
+
9
+ before_hook :logged_in?, :only => [:upload, :download]
10
+ before_hook :require_rsync, :only => [:upload, :download]
11
+ class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
12
+
13
+ desc "upload PATH", "Upload files to persistent data storage"
14
+ def upload(path)
15
+ app = multiple_clouds(options[:cloud], "upload #{path}")
16
+ app.upload(path)
17
+ rescue Client::ConflictException
18
+ say_error "Cloud #{app} is not running. Cannot upload files."
19
+ end
20
+
21
+ desc "download [SOURCE_PATH] [DEST_PATH]", "Download files from persistent data storage"
22
+ long_desc %{
23
+ Download files from persistent data storage.\n
24
+ SOURCE_PATH - optional source directory or file.\n
25
+ DEST_PATH - optional destination where files should be saved. By default is current working directory.
26
+ }
27
+ def download(relative_source = ".", destination = ".")
28
+ app = multiple_clouds(options[:cloud], "download #{relative_source} #{destination}")
29
+ app.download(relative_source, destination)
30
+ rescue Client::ConflictException
31
+ say_error "Cloud #{app} is not running. Cannot download files."
32
+ end
33
+
34
+ no_tasks do
35
+ def require_rsync
36
+ unless command_exists?("rsync")
37
+ say_error "You need to install rsync in order to upload and download files"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -3,6 +3,7 @@ require "shelly/cli/user"
3
3
  require "shelly/cli/backup"
4
4
  require "shelly/cli/deploys"
5
5
  require "shelly/cli/config"
6
+ require "shelly/cli/files"
6
7
 
7
8
  module Shelly
8
9
  module CLI
@@ -13,10 +14,12 @@ module Shelly
13
14
  register(Backup, "backup", "backup <command>", "Manage database backups")
14
15
  register(Deploys, "deploys", "deploys <command>", "View deploy logs")
15
16
  register(Config, "config", "config <command>", "Manage application configuration files")
17
+ register(Files, "files", "files <command>", "Upload and download files to and from persistent storage")
18
+
16
19
  check_unknown_options!(:except => :rake)
17
20
 
18
21
  # FIXME: it should be possible to pass single symbol, instead of one element array
19
- before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :info, :ip, :logout, :execute, :rake, :setup, :console, :upload]
22
+ before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :info, :ip, :logout, :execute, :rake, :setup, :console]
20
23
  before_hook :inside_git_repository?, :only => [:add, :setup, :check]
21
24
 
22
25
  map %w(-v --version) => :version
@@ -159,9 +162,6 @@ module Shelly
159
162
  print_wrapped "CPU: #{stat['cpu']['wait']}%, MEM: #{stat['memory']['percent']}%, SWAP: #{stat['swap']['percent']}%", :ident => 6
160
163
  end
161
164
  end
162
- rescue Client::NotFoundException => e
163
- raise unless e.resource == :cloud
164
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
165
165
  rescue Client::GatewayTimeoutException
166
166
  say_error "Server statistics temporarily unavailable"
167
167
  end
@@ -198,9 +198,6 @@ We have been notified about it. We will be adding new resources shortly}
198
198
  say_error "Not starting. Invoice for cloud '#{app}' was declined."
199
199
  end
200
200
  exit 1
201
- rescue Client::NotFoundException => e
202
- raise unless e.resource == :cloud
203
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
204
201
  end
205
202
 
206
203
  desc "setup", "Set up clouds"
@@ -225,9 +222,6 @@ We have been notified about it. We will be adding new resources shortly}
225
222
 
226
223
  say_new_line
227
224
  say "Your application is set up.", :green
228
- rescue Client::NotFoundException => e
229
- raise unless e.resource == :cloud
230
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
231
225
  end
232
226
 
233
227
  desc "stop", "Shutdown the cloud"
@@ -263,9 +257,6 @@ We have been notified about it. We will be adding new resources shortly}
263
257
  else
264
258
  say "Missing git remote"
265
259
  end
266
- rescue Client::NotFoundException => e
267
- raise unless e.resource == :cloud
268
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
269
260
  end
270
261
 
271
262
  desc "logs", "Show latest application logs"
@@ -276,28 +267,23 @@ We have been notified about it. We will be adding new resources shortly}
276
267
  def logs
277
268
  cloud = options[:cloud]
278
269
  app = multiple_clouds(cloud, "logs")
279
- begin
280
- limit = options[:limit].to_i <= 0 ? 100 : options[:limit]
281
- query = {:limit => limit}
282
- query.merge!(:from => options[:from]) if options[:from]
283
-
284
- logs = app.application_logs(query)
285
- print_logs(logs)
286
-
287
- if options[:tail]
288
- loop do
289
- logs = app.application_logs(:from => logs['range']['last'])
290
- print_logs(logs)
291
- sleep 1
292
- end
270
+ limit = options[:limit].to_i <= 0 ? 100 : options[:limit]
271
+ query = {:limit => limit}
272
+ query.merge!(:from => options[:from]) if options[:from]
273
+
274
+ logs = app.application_logs(query)
275
+ print_logs(logs)
276
+
277
+ if options[:tail]
278
+ loop do
279
+ logs = app.application_logs(:from => logs['range']['last'])
280
+ print_logs(logs)
281
+ sleep 1
293
282
  end
294
- rescue Client::NotFoundException => e
295
- raise unless e.resource == :cloud
296
- say_error "You have no access to '#{cloud || app}' cloud defined in Cloudfile"
297
- rescue Client::APIException => e
298
- raise e unless e.status_code == 416
299
- say_error "You have requested too many log messages. Try a lower number."
300
283
  end
284
+ rescue Client::APIException => e
285
+ raise e unless e.status_code == 416
286
+ say_error "You have requested too many log messages. Try a lower number."
301
287
  end
302
288
 
303
289
  desc "logout", "Logout from Shelly Cloud"
@@ -313,9 +299,6 @@ We have been notified about it. We will be adding new resources shortly}
313
299
  task = rake_args.join(" ")
314
300
  app = multiple_clouds(options[:cloud], "rake #{task}")
315
301
  app.rake(task)
316
- rescue Client::NotFoundException => e
317
- raise unless e.resource == :cloud
318
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
319
302
  rescue Client::ConflictException
320
303
  say_error "Cloud #{app} is not running. Cannot run rake task."
321
304
  end
@@ -337,9 +320,6 @@ We have been notified about it. We will be adding new resources shortly}
337
320
  exit 1
338
321
  else raise
339
322
  end
340
- rescue Client::NotFoundException => e
341
- raise unless e.resource == :cloud
342
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
343
323
  end
344
324
 
345
325
  desc "open", "Open application page in browser"
@@ -360,29 +340,10 @@ We have been notified about it. We will be adding new resources shortly}
360
340
  def console
361
341
  app = multiple_clouds(options[:cloud], "console")
362
342
  app.console
363
- rescue Client::NotFoundException => e
364
- raise unless e.resource == :cloud
365
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
366
343
  rescue Client::ConflictException
367
344
  say_error "Cloud #{app} is not running. Cannot run console."
368
345
  end
369
346
 
370
- desc "upload PATH", "Upload files to persisted data storage"
371
- method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
372
- def upload(path)
373
- unless command_exists?("rsync")
374
- say_error "You need to install rsync in order to use `shelly upload`"
375
- end
376
- app = multiple_clouds(options[:cloud], "upload #{path}")
377
- app.upload(path)
378
- rescue Client::NotFoundException => e
379
- raise unless e.resource == :cloud
380
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
381
- rescue Client::ConflictException
382
- say_error "Cloud #{app} is not running. Cannot upload files."
383
- end
384
-
385
- require 'bundler'
386
347
  desc "check", "List all requirements and check which are fulfilled"
387
348
  def check
388
349
  s = Shelly::StructureValidator.new
@@ -21,6 +21,10 @@ module Shelly
21
21
  rescue Client::UnauthorizedException
22
22
  raise if debug?
23
23
  say_error "You are not logged in. To log in use: `shelly login`"
24
+ desc "download [SOURCE_PATH] [DEST_PATH]", "Download files from persitent data storage"
25
+ rescue Client::NotFoundException => e
26
+ raise if debug? or e.resource != :cloud
27
+ say_error "You have no access to '#{e.id}' cloud defined in Cloudfile"
24
28
  rescue Client::GemVersionException => e
25
29
  raise if debug?
26
30
  say "Required shelly gem version: #{e.body["required_version"]}"
@@ -16,9 +16,6 @@ module Shelly
16
16
  app.active_collaborations.each { |c| say " #{c["email"]}" }
17
17
  app.inactive_collaborations.each { |c|
18
18
  say " #{c["email"]} (invited)" }
19
- rescue Client::NotFoundException => e
20
- raise unless e.resource == :cloud
21
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
22
19
  end
23
20
 
24
21
  desc "add [EMAIL]", "Add new developer to clouds defined in Cloudfile"
@@ -35,9 +32,6 @@ module Shelly
35
32
  e.each_error { |error| say_error error, :with_exit => false }
36
33
  exit 1
37
34
  end
38
- rescue Client::NotFoundException => e
39
- raise unless e.resource == :cloud
40
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
41
35
  end
42
36
 
43
37
  desc "delete [EMAIL]", "Remove developer from clouds defined in Cloudfile"
@@ -50,16 +44,10 @@ module Shelly
50
44
  rescue Client::ConflictException => e
51
45
  say_error e[:message]
52
46
  rescue Client::NotFoundException => e
53
- case e.resource
54
- when :cloud
55
- say_error "You have no access to '#{app}' cloud defined in Cloudfile"
56
- when :user
57
- say_error "User '#{user_email}' not found", :with_exit => false
58
- say_error "You can list users with `shelly user list`"
59
- else raise
60
- end
47
+ raise unless e.resource == :user
48
+ say_error "User '#{user_email}' not found", :with_exit => false
49
+ say_error "You can list users with `shelly user list`"
61
50
  end
62
-
63
51
  end
64
52
  end
65
53
  end
data/lib/shelly/client.rb CHANGED
@@ -37,6 +37,10 @@ module Shelly
37
37
  def resource
38
38
  self[:resource].to_sym
39
39
  end
40
+
41
+ def id
42
+ self[:id]
43
+ end
40
44
  end
41
45
 
42
46
  attr_reader :email, :password
@@ -1,4 +1,5 @@
1
1
  require 'grit'
2
+ require 'bundler'
2
3
 
3
4
  module Shelly
4
5
  class StructureValidator
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
@@ -312,13 +312,6 @@ describe Shelly::App do
312
312
  end
313
313
  end
314
314
 
315
- describe "#node_and_console" do
316
- it "should fetch instance data from Api" do
317
- @client.should_receive(:node_and_port).with("foo-staging")
318
- @app.node_and_port
319
- end
320
- end
321
-
322
315
  describe "#console" do
323
316
  it "should run ssh with all parameters" do
324
317
  @client.stub(:node_and_port).and_return(
@@ -329,14 +322,23 @@ describe Shelly::App do
329
322
  end
330
323
 
331
324
  describe "#upload" do
332
- it "should run rsync with all parameters" do
325
+ it "should run rsync with proper parameters" do
333
326
  @client.stub(:node_and_port).and_return(
334
327
  {"node_ip" => "10.0.0.1", "port" => "40010", "user" => "foo"})
335
- @app.should_receive(:exec).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010' --progress /path foo@10.0.0.1:/srv/glusterfs/disk")
328
+ @app.should_receive(:exec).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress /path 10.0.0.1:/srv/glusterfs/disk")
336
329
  @app.upload("/path")
337
330
  end
338
331
  end
339
332
 
333
+ describe "#download" do
334
+ it "should run rsync with proper parameters" do
335
+ @client.stub(:node_and_port).and_return(
336
+ {"node_ip" => "10.0.0.1", "port" => "40010", "user" => "foo"})
337
+ @app.should_receive(:exec).with("rsync -avz -e 'ssh -o StrictHostKeyChecking=no -p 40010 -l foo' --progress 10.0.0.1:/srv/glusterfs/disk/. /tmp")
338
+ @app.download(".", "/tmp")
339
+ end
340
+ end
341
+
340
342
  describe "#create_cloudfile" do
341
343
  it "should create cloudfile with app attributes" do
342
344
  @app.ruby_version = "1.9.3"
@@ -36,13 +36,6 @@ describe Shelly::CLI::Backup do
36
36
  invoke(@backup, :list)
37
37
  end
38
38
 
39
- it "should exit if user doesn't have access to cloud in Cloudfile" do
40
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
41
- @client.stub(:database_backups).and_raise(exception)
42
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
43
- lambda { invoke(@backup, :list) }.should raise_error(SystemExit)
44
- end
45
-
46
39
  it "should take cloud from command line for which to show backups" do
47
40
  @client.should_receive(:database_backups).with("foo-staging").and_return([{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb", "size" => 12345},{"filename" => "backup.mongo.tar.gz", "human_size" => "22kb", "size" => 333}])
48
41
  $stdout.should_receive(:puts).with(green "Available backups:")
@@ -136,13 +129,6 @@ describe Shelly::CLI::Backup do
136
129
  invoke(@backup, :create)
137
130
  end
138
131
 
139
- it "should exit if user doesn't have access to cloud in Cloudfile" do
140
- exception = Shelly::Client::NotFoundException.new({"resource" => "cloud"})
141
- @client.stub(:request_backup).and_raise(exception)
142
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
143
- lambda { invoke(@backup, :create) }.should raise_error(SystemExit)
144
- end
145
-
146
132
  it "should display errors and exit 1 when kind is not valid" do
147
133
  response = {"message" => "Wrong KIND argument. User one of following: postgresql, mongodb, redis"}
148
134
  exception = Shelly::Client::ValidationException.new(response)
@@ -33,13 +33,6 @@ describe Shelly::CLI::Config do
33
33
  invoke(@config, :list)
34
34
  end
35
35
 
36
- it "should exit if user doesn't have access to cloud in Cloudfile" do
37
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
38
- @client.stub(:app_configs).and_raise(exception)
39
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
40
- lambda { invoke(@config, :list) }.should raise_error(SystemExit)
41
- end
42
-
43
36
  it "should list available configuration files for clouds" do
44
37
  @client.should_receive(:app_configs).with("foo-production").and_return([{"created_by_user" => false, "path" => "config/app.yml"}])
45
38
  $stdout.should_receive(:puts).with(green "Configuration files for foo-production")
@@ -82,17 +75,6 @@ describe Shelly::CLI::Config do
82
75
  }.should raise_error(SystemExit)
83
76
  end
84
77
  end
85
-
86
- context "when user doesn't have access to cloud" do
87
- it "should display error message and exit with 1" do
88
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
89
- @client.should_receive(:app_config).and_raise(exception)
90
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
91
- lambda {
92
- invoke(@config, :show, "config/app.yml")
93
- }.should raise_error(SystemExit)
94
- end
95
- end
96
78
  end
97
79
  end
98
80
 
@@ -192,17 +174,6 @@ describe Shelly::CLI::Config do
192
174
  end
193
175
  end
194
176
 
195
- context "when user doesn't have access to cloud" do
196
- it "should display error message and exit with 1" do
197
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
198
- @client.should_receive(:app_config).and_raise(exception)
199
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
200
- lambda {
201
- invoke(@config, :edit, "config/app.yml")
202
- }.should raise_error(SystemExit)
203
- end
204
- end
205
-
206
177
  context "on validation errors" do
207
178
  it "should display validation errors" do
208
179
  exception = Shelly::Client::ValidationException.new({"errors" => [["path", "is already taken"]]})
@@ -262,19 +233,6 @@ describe Shelly::CLI::Config do
262
233
  end
263
234
  end
264
235
  end
265
-
266
- context "when user doesn't have access to cloud" do
267
- it "should display error message and exit with 1" do
268
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
269
- @client.should_receive(:app_delete_config).and_raise(exception)
270
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
271
- fake_stdin(["y"]) do
272
- lambda {
273
- invoke(@config, :delete, "config/app.yml")
274
- }.should raise_error(SystemExit)
275
- end
276
- end
277
- end
278
236
  end
279
237
  end
280
238
  end
@@ -33,12 +33,6 @@ describe Shelly::CLI::Deploys do
33
33
  invoke(@deploys, :list)
34
34
  end
35
35
 
36
- it "should exit if user doesn't have access to cloud in Cloudfile" do
37
- @client.stub(:deploy_logs).and_raise(Shelly::Client::NotFoundException.new("resource" => "cloud"))
38
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
39
- lambda { invoke(@deploys, :list) }.should raise_error(SystemExit)
40
- end
41
-
42
36
  it "should display available logs" do
43
37
  @client.should_receive(:deploy_logs).with("foo-staging").and_return([
44
38
  {"failed" => false, "created_at" => "2011-12-12-14-14-59"},
@@ -69,15 +63,6 @@ describe Shelly::CLI::Deploys do
69
63
  invoke(@deploys, :show, "last")
70
64
  end
71
65
 
72
- context "user doesn't have access to cloud" do
73
- it "should exit 1 with message" do
74
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
75
- @client.stub(:deploy_log).and_raise(exception)
76
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
77
- lambda { @deploys.show("last") }.should raise_error(SystemExit)
78
- end
79
- end
80
-
81
66
  context "log not found" do
82
67
  it "should exit 1 with message" do
83
68
  exception = Shelly::Client::NotFoundException.new("resource" => "log")
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+ require "shelly/cli/files"
3
+
4
+ describe Shelly::CLI::Files do
5
+ before do
6
+ FileUtils.stub(:chmod)
7
+ @cli_files = Shelly::CLI::Files.new
8
+ @client = mock
9
+ Shelly::Client.stub(:new).and_return(@client)
10
+ @client.stub(:token).and_return("abc")
11
+ FileUtils.mkdir_p("/projects/foo")
12
+ Dir.chdir("/projects/foo")
13
+ @app = Shelly::App.new("foo-staging")
14
+ Shelly::App.stub(:new).and_return(@app)
15
+ File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
16
+ end
17
+
18
+ describe "#upload" do
19
+ it "should ensure user has logged in" do
20
+ hooks(@cli_files, :upload).should include(:logged_in?)
21
+ end
22
+
23
+ it "should upload files" do
24
+ expected = {"port" => "40010", "node_ip" => "10.0.0.10", "user"=>"foo-production"}
25
+ @client.stub(:node_and_port).and_return(expected)
26
+ @app.should_receive(:upload).with("some/path")
27
+ invoke(@cli_files, :upload, "some/path")
28
+ end
29
+
30
+ it "should exit if rsync isn't installed" do
31
+ FakeFS::File.stub(:executable?).and_return(false)
32
+
33
+ $stdout.should_receive(:puts).with(red "You need to install rsync in order to upload and download files")
34
+ lambda { invoke(@cli_files, :upload, "some/path") }.should raise_error(SystemExit)
35
+ end
36
+
37
+ context "cloud is not running" do
38
+ it "should display error" do
39
+ @client.stub(:node_and_port).and_raise(Shelly::Client::ConflictException)
40
+ $stdout.should_receive(:puts).with(red "Cloud foo-production is not running. Cannot upload files.")
41
+ lambda {
42
+ invoke(@cli_files, :upload, "some/path")
43
+ }.should raise_error(SystemExit)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#download" do
49
+ it "should ensure user has logged in" do
50
+ hooks(@cli_files, :download).should include(:logged_in?)
51
+ end
52
+
53
+ it "should exit if rsync isn't installed" do
54
+ FakeFS::File.stub(:executable?).and_return(false)
55
+ $stdout.should_receive(:puts).with(red "You need to install rsync in order to upload and download files")
56
+ lambda { invoke(@cli_files, :download, "some/path") }.should raise_error(SystemExit)
57
+ end
58
+
59
+ it "should download files" do
60
+ expected = {"port" => "40010", "node_ip" => "10.0.0.10", "user"=>"foo-production"}
61
+ @client.stub(:node_and_port).and_return(expected)
62
+ @app.should_receive(:download).with("some/path", "/destination")
63
+ invoke(@cli_files, :download, "some/path", "/destination")
64
+ end
65
+ end
66
+ end
@@ -1,5 +1,6 @@
1
1
  require "spec_helper"
2
2
  require "shelly/cli/main"
3
+ require "grit"
3
4
 
4
5
  describe Shelly::CLI::Main do
5
6
  before do
@@ -32,6 +33,7 @@ Tasks:
32
33
  shelly delete # Delete the cloud
33
34
  shelly deploys <command> # View deploy logs
34
35
  shelly execute CODE # Run code on one of application servers
36
+ shelly files <command> # Upload and download files to and from persistent storage
35
37
  shelly help [TASK] # Describe available tasks or one specific task
36
38
  shelly info # Show basic information about cloud
37
39
  shelly list # List available clouds
@@ -45,7 +47,6 @@ Tasks:
45
47
  shelly setup # Set up clouds
46
48
  shelly start # Start the cloud
47
49
  shelly stop # Shutdown the cloud
48
- shelly upload PATH # Upload files to persisted data storage
49
50
  shelly user <command> # Manage collaborators
50
51
  shelly version # Display shelly version
51
52
 
@@ -558,13 +559,6 @@ OUT
558
559
  hooks(@main, :start).should include(:logged_in?)
559
560
  end
560
561
 
561
- it "should exit if user doesn't have access to clouds in Cloudfile" do
562
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
563
- @client.stub(:start_cloud).and_raise(exception)
564
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
565
- lambda { invoke(@main, :start) }.should raise_error(SystemExit)
566
- end
567
-
568
562
  context "single cloud in Cloudfile" do
569
563
  it "should start the cloud" do
570
564
  @client.stub(:start_cloud)
@@ -832,15 +826,6 @@ We have been notified about it. We will be adding new resources shortly")
832
826
  end
833
827
  end
834
828
 
835
- context "on failure" do
836
- it "should raise an error if user does not have access to cloud" do
837
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
838
- @client.stub(:app).and_raise(exception)
839
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
840
- lambda { invoke(@main, :ip) }.should raise_error(SystemExit)
841
- end
842
- end
843
-
844
829
  def response(options = {})
845
830
  { "code_name" => "foo-production",
846
831
  "state" => "running",
@@ -1010,25 +995,6 @@ We have been notified about it. We will be adding new resources shortly")
1010
995
  end
1011
996
  end
1012
997
 
1013
- context "when cloud given in option doesn't exist" do
1014
- before do
1015
- File.open("Cloudfile", 'w') {|f|
1016
- f.write("foo-staging:\n") }
1017
- end
1018
-
1019
- it "should raise Client::NotFoundException" do
1020
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
1021
- @app.stub(:delete).and_raise(exception)
1022
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-bar' cloud defined in Cloudfile")
1023
- lambda{
1024
- fake_stdin(["yes", "yes", "yes"]) do
1025
- @main.options = {:cloud => "foo-bar"}
1026
- invoke(@main, :delete)
1027
- end
1028
- }.should raise_error(SystemExit)
1029
- end
1030
- end
1031
-
1032
998
  context "when no cloud option is given" do
1033
999
  before do
1034
1000
  File.open("Cloudfile", 'w') {|f|
@@ -1112,14 +1078,6 @@ We have been notified about it. We will be adding new resources shortly")
1112
1078
  invoke(@main, :logs)
1113
1079
  end
1114
1080
 
1115
- it "should exit if user doesn't have access to clouds in Cloudfile" do
1116
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
1117
- @client.stub(:application_logs).and_raise(exception)
1118
- $stdout.should_receive(:puts).
1119
- with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
1120
- lambda { invoke(@main, :logs) }.should raise_error(SystemExit)
1121
- end
1122
-
1123
1081
  it "should exit if user requested too many log lines" do
1124
1082
  exception = Shelly::Client::APIException.new({}, 416)
1125
1083
  @client.stub(:application_logs).and_raise(exception)
@@ -1185,16 +1143,6 @@ We have been notified about it. We will be adding new resources shortly")
1185
1143
  @main.rake_args.should == @main.rake_args(ARGV)
1186
1144
  end
1187
1145
  end
1188
-
1189
- context "cloud is not in running state" do
1190
- it "should print error" do
1191
- @client.stub(:node_and_port).and_raise(Shelly::Client::ConflictException)
1192
- $stdout.should_receive(:puts).with(red "Cloud foo-production is not running. Cannot upload files.")
1193
- lambda {
1194
- invoke(@main, :upload, "some/path")
1195
- }.should raise_error(SystemExit)
1196
- end
1197
- end
1198
1146
  end
1199
1147
 
1200
1148
  describe "#redeploy" do
@@ -1305,13 +1253,6 @@ We have been notified about it. We will be adding new resources shortly")
1305
1253
  invoke(@main, :console)
1306
1254
  end
1307
1255
 
1308
- it "should exit if user doesn't have access to clouds in Cloudfile" do
1309
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
1310
- @client.stub(:node_and_port).and_raise(exception)
1311
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
1312
- lambda { invoke(@main, :console) }.should raise_error(SystemExit)
1313
- end
1314
-
1315
1256
  context "Instances are not running" do
1316
1257
  it "should display error" do
1317
1258
  @client.stub(:node_and_port).and_raise(Shelly::Client::ConflictException)
@@ -1323,51 +1264,6 @@ We have been notified about it. We will be adding new resources shortly")
1323
1264
  end
1324
1265
  end
1325
1266
 
1326
- describe "#upload" do
1327
- before do
1328
- @client.stub(:token).and_return("abc")
1329
- @app = Shelly::App.new("foo-production")
1330
- Shelly::App.stub(:new).and_return(@app)
1331
- FileUtils.mkdir_p("/projects/foo")
1332
- Dir.chdir("/projects/foo")
1333
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
1334
- end
1335
-
1336
- it "should ensure user has logged in" do
1337
- hooks(@main, :upload).should include(:logged_in?)
1338
- end
1339
-
1340
- it "should upload files" do
1341
- expected = {"port" => "40010", "node_ip" => "10.0.0.10", "user"=>"foo-production"}
1342
- @client.stub(:node_and_port).and_return(expected)
1343
- @app.should_receive(:upload).with("some/path")
1344
- invoke(@main, :upload, "some/path")
1345
- end
1346
-
1347
- it "should exit if user doesn't have access to clouds in Cloudfile" do
1348
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
1349
- @client.stub(:node_and_port).and_raise(exception)
1350
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
1351
- lambda { invoke(@main, :upload, "some/path") }.should raise_error(SystemExit)
1352
- end
1353
-
1354
- it "should exit if rsync isn't installed" do
1355
- FakeFS::File.stub(:executable?).and_return(false)
1356
- $stdout.should_receive(:puts).with(red "You need to install rsync in order to use `shelly upload`")
1357
- lambda { invoke(@main, :upload, "some/path") }.should raise_error(SystemExit)
1358
- end
1359
-
1360
- context "Instances are not running" do
1361
- it "should display error" do
1362
- @client.stub(:node_and_port).and_raise(Shelly::Client::ConflictException)
1363
- $stdout.should_receive(:puts).with(red "Cloud foo-production is not running. Cannot upload files.")
1364
- lambda {
1365
- invoke(@main, :upload, "some/path")
1366
- }.should raise_error(SystemExit)
1367
- end
1368
- end
1369
- end
1370
-
1371
1267
  describe "#check" do
1372
1268
  before do
1373
1269
  Shelly::App.stub(:inside_git_repository?).and_return(true)
@@ -65,16 +65,38 @@ describe Shelly::CLI::Runner do
65
65
  }.should raise_error(SystemExit)
66
66
  end
67
67
 
68
- it "should rescue unauthorized exception and display message" do
69
- @client = mock
70
- runner = Shelly::CLI::Runner.new(%w(status))
71
- Shelly::Client.stub(:new).and_return(@client)
72
- @client.stub(:token).and_return("abc")
73
- @client.stub(:apps).and_raise(Shelly::Client::UnauthorizedException.new)
74
- $stdout.should_receive(:puts).with("You are not logged in. To log in use: `shelly login`")
75
- lambda {
76
- runner.start
77
- }.should raise_error(SystemExit)
68
+ describe "API exception handling" do
69
+ before do
70
+ @client = mock
71
+ Shelly::Client.stub(:new).and_return(@client)
72
+ @client.stub(:token).and_return("abc")
73
+ @runner = Shelly::CLI::Runner.new(%w(status))
74
+ end
75
+
76
+ it "should rescue unauthorized exception and display message" do
77
+ @client.stub(:apps).and_raise(Shelly::Client::UnauthorizedException.new)
78
+ $stdout.should_receive(:puts).with("You are not logged in. To log in use: `shelly login`")
79
+ lambda {
80
+ @runner.start
81
+ }.should raise_error(SystemExit)
82
+ end
83
+
84
+ it "should rescue not found exception for cloud" do
85
+ exception = Shelly::Client::NotFoundException.new({"resource" => "cloud", "id" => "foooo"}, 404)
86
+ @client.stub(:apps).and_raise(exception)
87
+ $stdout.should_receive(:puts).with("You have no access to 'foooo' cloud defined in Cloudfile")
88
+ lambda {
89
+ @runner.start
90
+ }.should raise_error(SystemExit)
91
+ end
92
+
93
+ it "should re-raise not found exception for non cloud" do
94
+ exception = Shelly::Client::NotFoundException.new({"resource" => "config"}, 404)
95
+ @client.stub(:apps).and_raise(exception)
96
+ lambda {
97
+ @runner.start
98
+ }.should raise_error(Shelly::Client::NotFoundException)
99
+ end
78
100
  end
79
101
 
80
102
  context "with --debug option (debug mode)" do
@@ -53,15 +53,6 @@ describe Shelly::CLI::User do
53
53
  invoke(@cli_user, :list)
54
54
  end
55
55
  end
56
-
57
- context "on failure" do
58
- it "should exit with 1 if user does not have access to cloud" do
59
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
60
- @client.stub(:collaborations).and_raise(exception)
61
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
62
- lambda { invoke(@cli_user, :list) }.should raise_error(SystemExit)
63
- end
64
- end
65
56
  end
66
57
 
67
58
  describe "#add" do
@@ -102,17 +93,6 @@ describe Shelly::CLI::User do
102
93
  invoke(@cli_user, :add, "megan@example.com")
103
94
  end
104
95
  end
105
-
106
- context "on failure" do
107
- it "should raise error if user doesnt have access to cloud" do
108
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
109
- @client.stub(:send_invitation).and_raise(exception)
110
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
111
- lambda {
112
- invoke(@cli_user, :add, "megan@example.com")
113
- }.should raise_error(SystemExit)
114
- end
115
- end
116
96
  end
117
97
 
118
98
  describe "#delete" do
@@ -164,15 +144,6 @@ describe Shelly::CLI::User do
164
144
  }.should raise_error(SystemExit)
165
145
  end
166
146
 
167
- it "should raise error if user doesnt have access to cloud" do
168
- exception = Shelly::Client::NotFoundException.new("resource" => "cloud")
169
- @client.stub(:delete_collaboration).and_raise(exception)
170
- $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
171
- lambda {
172
- invoke(@cli_user, :delete, "megan@example.com")
173
- }.should raise_error(SystemExit)
174
- end
175
-
176
147
  it "should show that user can't delete own collaboration" do
177
148
  exception = Shelly::Client::ConflictException.new("message" =>
178
149
  "Can't remove own collaboration")
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.1.9
4
+ version: 0.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-04 00:00:00.000000000 Z
12
+ date: 2012-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -291,6 +291,7 @@ files:
291
291
  - lib/shelly/cli/command.rb
292
292
  - lib/shelly/cli/config.rb
293
293
  - lib/shelly/cli/deploys.rb
294
+ - lib/shelly/cli/files.rb
294
295
  - lib/shelly/cli/main.rb
295
296
  - lib/shelly/cli/runner.rb
296
297
  - lib/shelly/cli/user.rb
@@ -316,6 +317,7 @@ files:
316
317
  - spec/shelly/cli/backup_spec.rb
317
318
  - spec/shelly/cli/config_spec.rb
318
319
  - spec/shelly/cli/deploys_spec.rb
320
+ - spec/shelly/cli/files_spec.rb
319
321
  - spec/shelly/cli/main_spec.rb
320
322
  - spec/shelly/cli/runner_spec.rb
321
323
  - spec/shelly/cli/user_spec.rb
@@ -359,6 +361,7 @@ test_files:
359
361
  - spec/shelly/cli/backup_spec.rb
360
362
  - spec/shelly/cli/config_spec.rb
361
363
  - spec/shelly/cli/deploys_spec.rb
364
+ - spec/shelly/cli/files_spec.rb
362
365
  - spec/shelly/cli/main_spec.rb
363
366
  - spec/shelly/cli/runner_spec.rb
364
367
  - spec/shelly/cli/user_spec.rb