shelly 0.1.9 → 0.1.10

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