shelly 0.1.21 → 0.1.22

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ## 0.1.22 / 2012-08-06
2
+
3
+ * [feature] Add dbconsole to access 'rails dbconsole' on Shelly Cloud.
4
+
5
+ * [feature] Limit backups list to 10 backups, --all option to list all backups.
6
+
7
+ Usage: ```shelly backup list --all```
8
+
9
+ ## 0.1.21 / 2012-08-06
10
+
11
+ * [refactoring] Adjusted shelly console to match new API.
data/lib/shelly/app.rb CHANGED
@@ -176,6 +176,10 @@ module Shelly
176
176
  ssh_command("rake_runner \"#{task}\"")
177
177
  end
178
178
 
179
+ def dbconsole
180
+ ssh_command("dbconsole")
181
+ end
182
+
179
183
  def attributes
180
184
  @attributes ||= shelly.app(code_name)
181
185
  end
@@ -244,7 +248,7 @@ module Shelly
244
248
  end
245
249
 
246
250
  def ssh_command(command = "")
247
- exec "ssh #{ssh_options} #{ssh['host']} #{command}"
251
+ exec "ssh #{ssh_options} -t #{ssh['host']} #{command}"
248
252
  end
249
253
 
250
254
  def ssh_options
data/lib/shelly/backup.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  module Shelly
2
2
  class Backup < Model
3
+ LIMIT = 10
3
4
  attr_reader :filename, :size, :human_size, :code_name, :kind, :state
4
5
 
5
6
  def initialize(attributes = {})
@@ -12,13 +12,21 @@ module Shelly
12
12
 
13
13
  class_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
14
14
 
15
+ method_option :all, :type => :boolean, :aliases => "-a",
16
+ :desc => "Show all backups"
15
17
  desc "list", "List available database backups"
16
18
  def list
17
19
  app = multiple_clouds(options[:cloud], "backup list")
18
20
  backups = app.database_backups
19
21
  if backups.present?
22
+ limit = -1
23
+ unless options[:all] || backups.count < (Shelly::Backup::LIMIT + 1)
24
+ limit = Shelly::Backup::LIMIT - 1
25
+ say "Limiting the number of backups to #{Shelly::Backup::LIMIT}."
26
+ say "Use --all or -a option to list all backups."
27
+ end
20
28
  to_display = [["Filename", "| Size", "| State"]]
21
- backups.each do |backup|
29
+ backups[0..limit].each do |backup|
22
30
  to_display << [backup.filename, "| #{backup.human_size}", "| #{backup.state.humanize}"]
23
31
  end
24
32
 
@@ -20,7 +20,7 @@ module Shelly
20
20
  check_unknown_options!(:except => :rake)
21
21
 
22
22
  # FIXME: it should be possible to pass single symbol, instead of one element array
23
- before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :info, :ip, :logout, :execute, :rake, :setup, :console]
23
+ before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :info, :ip, :logout, :execute, :rake, :setup, :console, :dbconsole]
24
24
  before_hook :inside_git_repository?, :only => [:add, :setup, :check]
25
25
 
26
26
  map %w(-v --version) => :version
@@ -318,6 +318,15 @@ We have been notified about it. We will be adding new resources shortly}
318
318
  say_error "Cloud #{app} is not running. Cannot run rake task."
319
319
  end
320
320
 
321
+ desc "dbconsole", "Run rails dbconsole"
322
+ method_option :cloud, :type => :string, :aliases => "-c", :desc => "Specify cloud"
323
+ def dbconsole(task = nil)
324
+ app = multiple_clouds(options[:cloud], "dbconsole")
325
+ app.dbconsole
326
+ rescue Client::ConflictException
327
+ say_error "Cloud #{app} is not running. Cannot run dbconsole."
328
+ end
329
+
321
330
  desc "redeploy", "Redeploy application"
322
331
  method_option :cloud, :type => :string, :aliases => "-c",
323
332
  :desc => "Specify which cloud to redeploy application for"
data/lib/shelly/client.rb CHANGED
@@ -147,9 +147,7 @@ module Shelly
147
147
  end
148
148
 
149
149
  def application_logs(cloud, options = {})
150
- query = "?" + options.map { |k, v|
151
- URI.escape(k.to_s) + "=" + URI.escape(v.to_s) }.join("&")
152
- get("/apps/#{cloud}/application_logs#{query}")
150
+ get("/apps/#{cloud}/application_logs#{query(options)}")
153
151
  end
154
152
 
155
153
  def database_backups(code_name)
@@ -176,6 +174,11 @@ module Shelly
176
174
  post("/apps/#{cloud}/deploys")
177
175
  end
178
176
 
177
+ def query(options = {})
178
+ "?" + options.map { |k, v|
179
+ URI.escape(k.to_s) + "=" + URI.escape(v.to_s) }.join("&")
180
+ end
181
+
179
182
  def post(path, params = {})
180
183
  request(path, :post, params)
181
184
  end
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.1.21"
2
+ VERSION = "0.1.22"
3
3
  end
data/lib/thor/thor.rb CHANGED
@@ -12,6 +12,7 @@ class Thor
12
12
  def send(*args)
13
13
  if args.first == :dispatch && !args[2].empty?
14
14
  running_task = args[2].first
15
+
15
16
  @hook.each do |method, options|
16
17
  if options[:only].include?(running_task.to_sym)
17
18
  new.send(method)
data/shelly.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.description = %q{Tool for managing applications and clouds at shellycloud.com}
13
13
 
14
14
  s.rubyforge_project = "shelly"
15
- s.add_development_dependency "rspec", "~> 2.8.0"
15
+ s.add_development_dependency "rspec", "~> 2.11.0"
16
16
  s.add_development_dependency "rake"
17
17
  s.add_development_dependency "guard"
18
18
  s.add_development_dependency "guard-rspec"
@@ -253,6 +253,14 @@ describe Shelly::App do
253
253
  end
254
254
  end
255
255
 
256
+ describe "#database_backups" do
257
+ it "should add limit parameter" do
258
+ @client.stub_chain(:database_backups, :map)
259
+ @client.should_receive(:database_backups).with("foo-staging")
260
+ @app.database_backups
261
+ end
262
+ end
263
+
256
264
  describe "#database_backup" do
257
265
  before do
258
266
  @description = {
@@ -312,11 +320,20 @@ describe Shelly::App do
312
320
  it "should return result of rake task" do
313
321
  @client.stub(:console).and_return(
314
322
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
315
- @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo console.example.com rake_runner \"test\"")
323
+ @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com rake_runner \"test\"")
316
324
  @app.rake("test")
317
325
  end
318
326
  end
319
327
 
328
+ describe "#dbconsole" do
329
+ it "should return result of dbconsole" do
330
+ @client.stub(:console).and_return(
331
+ {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
332
+ @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com dbconsole")
333
+ @app.dbconsole
334
+ end
335
+ end
336
+
320
337
  describe "#to_s" do
321
338
  it "should return code_name" do
322
339
  @app.to_s.should == "foo-staging"
@@ -342,7 +359,7 @@ describe Shelly::App do
342
359
  it "should run ssh with all parameters" do
343
360
  @client.stub(:console).and_return(
344
361
  {"host" => "console.example.com", "port" => "40010", "user" => "foo"})
345
- @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo console.example.com ")
362
+ @app.should_receive(:exec).with("ssh -o StrictHostKeyChecking=no -p 40010 -l foo -t console.example.com ")
346
363
  @app.console
347
364
  end
348
365
  end
@@ -31,23 +31,39 @@ describe Shelly::CLI::Backup do
31
31
 
32
32
  # multiple_clouds is tested in main_spec.rb in describe "#start" block
33
33
  it "should ensure multiple_clouds check" do
34
- @client.should_receive(:database_backups).with("foo-staging").and_return([{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb", "size" => 12345, "state" => "completed"}])
34
+ @client.should_receive(:database_backups).with("foo-staging").and_return(
35
+ [{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb",
36
+ "size" => 12345, "state" => "completed"}])
35
37
  @backup.should_receive(:multiple_clouds).and_return(@app)
36
38
  invoke(@backup, :list)
37
39
  end
38
40
 
39
41
  it "should take cloud from command line for which to show backups" do
42
+ stub_const("Shelly::Backup::LIMIT", 1)
40
43
  @client.should_receive(:database_backups).with("foo-staging").and_return(
41
44
  [{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb",
42
45
  "size" => 12345, "state" => "completed"},
43
46
  {"filename" => "backup.mongo.tar.gz", "human_size" => "22kb",
44
47
  "size" => 333, "state" => "in_progress"}])
48
+ $stdout.should_not_receive(:puts).with("Limiting the number of backups to 1.")
45
49
  $stdout.should_receive(:puts).with(green "Available backups:")
46
50
  $stdout.should_receive(:puts).with("\n")
47
51
  $stdout.should_receive(:puts).with(" Filename | Size | State")
48
52
  $stdout.should_receive(:puts).with(" backup.postgre.tar.gz | 10kb | completed")
49
53
  $stdout.should_receive(:puts).with(" backup.mongo.tar.gz | 22kb | in progress")
50
- @backup.options = {:cloud => "foo-staging"}
54
+ @backup.options = {:cloud => "foo-staging", :all => true}
55
+ invoke(@backup, :list)
56
+ end
57
+
58
+ it "should show --all option if not present" do
59
+ stub_const("Shelly::Backup::LIMIT", 1)
60
+ $stdout.should_receive(:puts).with("Limiting the number of backups to 1.")
61
+ $stdout.should_receive(:puts).with("Use --all or -a option to list all backups.")
62
+ @client.should_receive(:database_backups).with("foo-staging").and_return(
63
+ [{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb",
64
+ "size" => 12345, "state" => "completed"},
65
+ {"filename" => "backup.mongo.tar.gz", "human_size" => "22kb",
66
+ "size" => 333, "state" => "in_progress"}])
51
67
  invoke(@backup, :list)
52
68
  end
53
69
 
@@ -9,6 +9,7 @@ describe Shelly::CLI::Main do
9
9
  @main = Shelly::CLI::Main.new
10
10
  Shelly::CLI::Main.stub(:new).and_return(@main)
11
11
  @client = mock
12
+ @client.stub(:token).and_return("abc")
12
13
  Shelly::Client.stub(:new).and_return(@client)
13
14
  Shelly::User.stub(:guess_email).and_return("")
14
15
  $stdout.stub(:puts)
@@ -31,6 +32,7 @@ Tasks:
31
32
  shelly check # Check if application fulfills Shelly Cloud requirements
32
33
  shelly config <command> # Manage application configuration files
33
34
  shelly console # Open application console
35
+ shelly dbconsole # Run rails dbconsole
34
36
  shelly delete # Delete the cloud
35
37
  shelly deploys <command> # View deploy logs
36
38
  shelly execute CODE # Run code on one of application servers
@@ -563,16 +565,10 @@ OUT
563
565
 
564
566
  describe "#start" do
565
567
  before do
566
- @user = Shelly::User.new
567
- @client.stub(:token).and_return("abc")
568
- FileUtils.mkdir_p("/projects/foo")
569
- Dir.chdir("/projects/foo")
570
- File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
571
- Shelly::User.stub(:new).and_return(@user)
572
- @client.stub(:apps).and_return([{"code_name" => "foo-production", "state" => "running"},
573
- {"code_name" => "foo-staging", "state" => "no_code"}])
574
- @app = Shelly::App.new
575
- Shelly::App.stub(:new).and_return(@app)
568
+ setup_project
569
+ @client.stub(:apps).and_return([
570
+ {"code_name" => "foo-production", "state" => "running"},
571
+ {"code_name" => "foo-staging", "state" => "no_code"}])
576
572
  end
577
573
 
578
574
  it "should ensure user has logged in" do
@@ -1074,16 +1070,7 @@ We have been notified about it. We will be adding new resources shortly")
1074
1070
 
1075
1071
  describe "#logs" do
1076
1072
  before do
1077
- @user = Shelly::User.new
1078
- @client.stub(:token).and_return("abc")
1079
- FileUtils.mkdir_p("/projects/foo")
1080
- Dir.chdir("/projects/foo")
1081
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
1082
- Shelly::User.stub(:new).and_return(@user)
1083
- @client.stub(:apps).and_return([{"code_name" => "foo-production"},
1084
- {"code_name" => "foo-staging"}])
1085
- @app = Shelly::App.new
1086
- Shelly::App.stub(:new).and_return(@app)
1073
+ setup_project
1087
1074
  @sample_logs = {"entries" => [['app1', 'log1'], ['app1', 'log2']]}
1088
1075
  end
1089
1076
 
@@ -1123,14 +1110,7 @@ We have been notified about it. We will be adding new resources shortly")
1123
1110
 
1124
1111
  describe "#rake" do
1125
1112
  before do
1126
- FileUtils.mkdir_p("/projects/foo")
1127
- Dir.chdir("/projects/foo")
1128
- File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
1129
- @user = Shelly::User.new
1130
- @user.stub(:token)
1131
- Shelly::User.stub(:new).and_return(@user)
1132
- @app = Shelly::App.new("foo-production")
1133
- Shelly::App.stub(:new).and_return(@app)
1113
+ setup_project
1134
1114
  @main.stub(:rake_args).and_return(%w(db:migrate))
1135
1115
  end
1136
1116
 
@@ -1167,13 +1147,7 @@ We have been notified about it. We will be adding new resources shortly")
1167
1147
 
1168
1148
  describe "#redeploy" do
1169
1149
  before do
1170
- @user = Shelly::User.new
1171
- @client.stub(:token).and_return("abc")
1172
- @app = Shelly::App.new("foo-production")
1173
- Shelly::App.stub(:new).and_return(@app)
1174
- FileUtils.mkdir_p("/projects/foo")
1175
- Dir.chdir("/projects/foo")
1176
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
1150
+ setup_project
1177
1151
  end
1178
1152
 
1179
1153
  # multiple_clouds is tested in main_spec.rb in describe "#start" block
@@ -1229,14 +1203,8 @@ We have been notified about it. We will be adding new resources shortly")
1229
1203
 
1230
1204
  describe "#open" do
1231
1205
  before do
1232
- @user = Shelly::User.new
1233
- @client.stub(:token).and_return("abc")
1234
- @app = Shelly::App.new("foo-production")
1206
+ setup_project
1235
1207
  @app.stub(:open)
1236
- Shelly::App.stub(:new).and_return(@app)
1237
- FileUtils.mkdir_p("/projects/foo")
1238
- Dir.chdir("/projects/foo")
1239
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
1240
1208
  end
1241
1209
 
1242
1210
  # multiple_clouds is tested in main_spec.rb in describe "#start" block
@@ -1254,12 +1222,7 @@ We have been notified about it. We will be adding new resources shortly")
1254
1222
 
1255
1223
  describe "#console" do
1256
1224
  before do
1257
- @client.stub(:token).and_return("abc")
1258
- @app = Shelly::App.new("foo-production")
1259
- Shelly::App.stub(:new).and_return(@app)
1260
- FileUtils.mkdir_p("/projects/foo")
1261
- Dir.chdir("/projects/foo")
1262
- File.open("Cloudfile", 'w') { |f| f.write("foo-production:\n") }
1225
+ setup_project
1263
1226
  end
1264
1227
 
1265
1228
  it "should ensure user has logged in" do
@@ -1282,6 +1245,31 @@ We have been notified about it. We will be adding new resources shortly")
1282
1245
  end
1283
1246
  end
1284
1247
 
1248
+ describe "#dbconsole" do
1249
+ before do
1250
+ setup_project
1251
+ end
1252
+
1253
+ it "should ensure user has logged in" do
1254
+ hooks(@main, :dbconsole).should include(:logged_in?)
1255
+ end
1256
+
1257
+ it "should execute ssh command" do
1258
+ @app.should_receive(:dbconsole)
1259
+ invoke(@main, :dbconsole)
1260
+ end
1261
+
1262
+ context "Instances are not running" do
1263
+ it "should display error" do
1264
+ @client.stub(:console).and_raise(Shelly::Client::ConflictException)
1265
+ $stdout.should_receive(:puts).with(red "Cloud foo-production is not running. Cannot run dbconsole.")
1266
+ lambda {
1267
+ invoke(@main, :dbconsole)
1268
+ }.should raise_error(SystemExit)
1269
+ end
1270
+ end
1271
+ end
1272
+
1285
1273
  describe "#check" do
1286
1274
  before do
1287
1275
  Shelly::App.stub(:inside_git_repository?).and_return(true)
@@ -1390,4 +1378,12 @@ We have been notified about it. We will be adding new resources shortly")
1390
1378
  @main.check(false)
1391
1379
  end
1392
1380
  end
1381
+
1382
+ def setup_project(code_name = "foo")
1383
+ @app = Shelly::App.new("#{code_name}-production")
1384
+ Shelly::App.stub(:new).and_return(@app)
1385
+ FileUtils.mkdir_p("/projects/#{code_name}")
1386
+ Dir.chdir("/projects/#{code_name}")
1387
+ File.open("Cloudfile", 'w') { |f| f.write("#{code_name}-production:\n") }
1388
+ end
1393
1389
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.21
4
+ version: 0.1.22
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.8.0
21
+ version: 2.11.0
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 2.8.0
29
+ version: 2.11.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -277,6 +277,7 @@ extra_rdoc_files: []
277
277
  files:
278
278
  - .gitignore
279
279
  - .travis.yml
280
+ - CHANGELOG.md
280
281
  - Gemfile
281
282
  - Guardfile
282
283
  - README.md
@@ -342,18 +343,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
342
343
  - - ! '>='
343
344
  - !ruby/object:Gem::Version
344
345
  version: '0'
345
- segments:
346
- - 0
347
- hash: 2910498490410578861
348
346
  required_rubygems_version: !ruby/object:Gem::Requirement
349
347
  none: false
350
348
  requirements:
351
349
  - - ! '>='
352
350
  - !ruby/object:Gem::Version
353
351
  version: '0'
354
- segments:
355
- - 0
356
- hash: 2910498490410578861
357
352
  requirements: []
358
353
  rubyforge_project: shelly
359
354
  rubygems_version: 1.8.24