shelly 0.1.24.pre → 0.1.24.pre2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,4 @@
1
+ * [feature] `shelly check` checks gems based on Cloudfile
1
2
  * [feature] Option --help [-h] added to all tasks
2
3
 
3
4
  ## 0.1.23 / 2012-08-08
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :cli => '--color --format doc' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch('lib/shelly/helpers.rb') { "spec" }
4
+ watch(%r{^lib/shelly/(.+)\.rb$}) { |m| "spec/shelly/#{m[1]}_spec.rb" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ end
data/README.md CHANGED
@@ -13,3 +13,7 @@
13
13
  ## Running tests
14
14
 
15
15
  bundle exec rake
16
+
17
+ or
18
+
19
+ guard
data/lib/shelly.rb CHANGED
@@ -14,6 +14,7 @@ require "shelly/model"
14
14
  module Shelly
15
15
  autoload :App, "shelly/app"
16
16
  autoload :Cloudfile, "shelly/cloudfile"
17
+ autoload :Cloud, "shelly/cloud"
17
18
  autoload :Client, "shelly/client"
18
19
  autoload :StructureValidator, "shelly/structure_validator"
19
20
  autoload :User, "shelly/user"
data/lib/shelly/app.rb CHANGED
@@ -117,7 +117,7 @@ module Shelly
117
117
  guessed = nil
118
118
  cloudfile = Cloudfile.new
119
119
  if cloudfile.present?
120
- clouds = cloudfile.clouds
120
+ clouds = cloudfile.clouds.map(&:code_name)
121
121
  if clouds.grep(/staging/).present?
122
122
  guessed = "production"
123
123
  production_clouds = clouds.grep(/production/)
@@ -32,7 +32,7 @@ module Shelly
32
32
 
33
33
  say "Available backups:", :green
34
34
  say_new_line
35
- print_table(to_display, :indent => 2)
35
+ print_table(to_display, :ident => 2)
36
36
  else
37
37
  say "No database backups available"
38
38
  end
@@ -70,7 +70,7 @@ module Shelly
70
70
  say_error "Cloudfile must be present in current working directory or specify database kind with:", :with_exit => false
71
71
  say_error "`shelly backup create DB_KIND`"
72
72
  end
73
- app.request_backup(kind || cloudfile.backup_databases(app))
73
+ app.request_backup(kind || cloudfile.clouds.find { |c| c.code_name == app.to_s }.backup_databases)
74
74
  say "Backup requested. It can take up to several minutes for " +
75
75
  "the backup process to finish.", :green
76
76
  rescue Client::ValidationException => e
@@ -4,6 +4,7 @@ require "thor/thor"
4
4
  require "thor/group"
5
5
  require "thor/options"
6
6
  require "thor/arguments"
7
+ require "thor/basic"
7
8
 
8
9
  module Shelly
9
10
  module CLI
@@ -79,7 +79,8 @@ module Shelly
79
79
  end
80
80
 
81
81
  desc "delete PATH", "Delete configuration file"
82
- def delete(path)
82
+ def delete(path = nil)
83
+ say_error "No configuration file specified" unless path
83
84
  app = multiple_clouds(options[:cloud], "delete #{path}")
84
85
  answer = yes?("Are you sure you want to delete 'path' (yes/no): ")
85
86
  if answer
@@ -19,6 +19,7 @@ module Shelly
19
19
 
20
20
  check_unknown_options!(:except => :rake)
21
21
 
22
+ # FIXME: it should be possible to pass single symbol, instead of one element array
22
23
  before_hook :logged_in?, :only => [:add, :status, :list, :start, :stop, :logs, :delete, :info, :ip, :logout, :execute, :rake, :setup, :console, :dbconsole]
23
24
  before_hook :inside_git_repository?, :only => [:add, :setup, :check]
24
25
 
@@ -133,7 +134,7 @@ module Shelly
133
134
  end
134
135
  [app["code_name"], "| #{state.humanize}#{msg}"]
135
136
  end
136
- print_table(apps_table, :indent => 2)
137
+ print_table(apps_table, :ident => 2)
137
138
  else
138
139
  say "You have no clouds yet", :green
139
140
  end
@@ -148,21 +149,21 @@ module Shelly
148
149
  " (deployment log: `shelly deploys show last -c #{app}`)"
149
150
  end
150
151
  say "Cloud #{app}:", msg.present? ? :red : :green
151
- print_wrapped "State: #{app.state}#{msg}", :indent => 2
152
+ print_wrapped "State: #{app.state}#{msg}", :ident => 2
152
153
  say_new_line
153
- print_wrapped "Deployed commit sha: #{app.git_info["deployed_commit_sha"]}", :indent => 2
154
- print_wrapped "Deployed commit message: #{app.git_info["deployed_commit_message"]}", :indent => 2
155
- print_wrapped "Deployed by: #{app.git_info["deployed_push_author"]}", :indent => 2
154
+ print_wrapped "Deployed commit sha: #{app.git_info["deployed_commit_sha"]}", :ident => 2
155
+ print_wrapped "Deployed commit message: #{app.git_info["deployed_commit_message"]}", :ident => 2
156
+ print_wrapped "Deployed by: #{app.git_info["deployed_push_author"]}", :ident => 2
156
157
  say_new_line
157
- print_wrapped "Repository URL: #{app.git_info["repository_url"]}", :indent => 2
158
- print_wrapped "Web server IP: #{app.web_server_ip}", :indent => 2
158
+ print_wrapped "Repository URL: #{app.git_info["repository_url"]}", :ident => 2
159
+ print_wrapped "Web server IP: #{app.web_server_ip}", :ident => 2
159
160
  say_new_line
160
161
  if app.statistics.present?
161
- print_wrapped "Statistics:", :indent => 2
162
+ print_wrapped "Statistics:", :ident => 2
162
163
  app.statistics.each do |stat|
163
- print_wrapped "#{stat['name']}:", :indent => 4
164
- print_wrapped "Load average: 1m: #{stat['load']['avg01']}, 5m: #{stat['load']['avg05']}, 15m: #{stat['load']['avg15']}", :indent => 6
165
- print_wrapped "CPU: #{stat['cpu']['wait']}%, MEM: #{stat['memory']['percent']}%, SWAP: #{stat['swap']['percent']}%", :indent => 6
164
+ print_wrapped "#{stat['name']}:", :ident => 4
165
+ print_wrapped "Load average: 1m: #{stat['load']['avg01']}, 5m: #{stat['load']['avg05']}, 15m: #{stat['load']['avg15']}", :ident => 6
166
+ print_wrapped "CPU: #{stat['cpu']['wait']}%, MEM: #{stat['memory']['percent']}%, SWAP: #{stat['swap']['percent']}%", :ident => 6
166
167
  end
167
168
  end
168
169
  rescue Client::GatewayTimeoutException
@@ -384,6 +385,10 @@ We have been notified about it. We will be adding new resources shortly}
384
385
  "Gemfile.lock is missing in git repository",
385
386
  :show_fulfilled => verbose)
386
387
 
388
+ print_check(structure.config_ru?, "File config.ru is present",
389
+ "File config.ru is missing",
390
+ :show_fulfilled => verbose)
391
+
387
392
  print_check(structure.gem?("shelly-dependencies"),
388
393
  "Gem 'shelly-dependencies' is present",
389
394
  "Gem 'shelly-dependencies' is missing, we recommend to install it\n See more at https://shellycloud.com/documentation/requirements#shelly-dependencies",
@@ -395,9 +400,35 @@ We have been notified about it. We will be adding new resources shortly}
395
400
  print_check(structure.gem?("rake"), "Gem 'rake' is present",
396
401
  "Gem 'rake' is missing in the Gemfile", :show_fulfilled => verbose)
397
402
 
398
- print_check(structure.config_ru?, "File config.ru is present",
399
- "File config.ru is missing",
400
- :show_fulfilled => verbose)
403
+
404
+ print_check(structure.gem?("rake"), "Gem 'rake' is present",
405
+ "Gem 'rake' is missing in the Gemfile", :show_fulfilled => verbose)
406
+
407
+ cloudfile = Cloudfile.new
408
+ if cloudfile.present?
409
+ cloudfile.clouds.each do |cloud|
410
+ if cloud.databases.include?('postgresql')
411
+ print_check(structure.gem?("pg") || structure.gem?("postgres"),
412
+ "Postgresql driver is present for '#{cloud}' cloud",
413
+ "Postgresql driver is missing in the Gemfile for '#{cloud}' cloud,\n we recommend adding 'pg' gem to Gemfile",
414
+ :show_fulfilled => verbose)
415
+ end
416
+
417
+ if cloud.delayed_job?
418
+ print_check(structure.gem?("delayed_job"),
419
+ "Gem 'delayed_job' is present for '#{cloud}' cloud",
420
+ "Gem 'delayed_job' is missing in the Gemfile for '#{cloud}' cloud",
421
+ :show_fulfilled => verbose)
422
+ end
423
+
424
+ if cloud.whenever?
425
+ print_check(structure.gem?("whenever"),
426
+ "Gem 'whenever' is present for '#{cloud}' cloud",
427
+ "Gem 'whenever' is missing in the Gemfile for '#{cloud}' cloud",
428
+ :show_fulfilled => verbose)
429
+ end
430
+ end
431
+ end
401
432
 
402
433
  print_check(!structure.gem?("mysql") && !structure.gem?("mysql2"),"",
403
434
  "mysql driver present in the Gemfile (not supported on Shelly Cloud)",
@@ -0,0 +1,49 @@
1
+ require "yaml"
2
+
3
+ module Shelly
4
+ class Cloud < Model
5
+ attr_accessor :code_name, :content
6
+
7
+ def initialize(attributes = {})
8
+ @code_name = attributes["code_name"]
9
+ @content = attributes["content"]
10
+ end
11
+
12
+ # Public: Return databases for given Cloud in Cloudfile
13
+ # Returns Array of databases
14
+ def databases
15
+ content["servers"].map do |server, settings|
16
+ settings["databases"]
17
+ end.flatten.uniq
18
+ end
19
+
20
+ # Public: Delayed job enabled?
21
+ # Returns true if delayed job is present
22
+ def delayed_job?
23
+ option?("delayed_job")
24
+ end
25
+
26
+ # Public: Whenever enabled?
27
+ # Returns true if whenever is present
28
+ def whenever?
29
+ option?("whenever")
30
+ end
31
+
32
+ # Public: Return databases to backup for given Cloud in Cloudfile
33
+ # Returns Array of databases, except redis db
34
+ def backup_databases
35
+ databases - ['redis']
36
+ end
37
+
38
+ def to_s
39
+ code_name
40
+ end
41
+
42
+ private
43
+
44
+ # Internal: Checks if specified option is present
45
+ def option?(option)
46
+ content["servers"].any? {|_, settings| settings.has_key?(option)}
47
+ end
48
+ end
49
+ end
@@ -16,7 +16,10 @@ module Shelly
16
16
  # Returns Array of clouds names from Cloudfile
17
17
  # nil if there is no cloudfile
18
18
  def clouds
19
- content.keys.sort if content
19
+ content.keys.sort.map do |code_name|
20
+ Shelly::Cloud.new("code_name" => code_name,
21
+ "content" => content[code_name.to_s])
22
+ end if content
20
23
  end
21
24
 
22
25
  # Public: Generate example Cloudfile based on object attributes
@@ -35,22 +38,6 @@ module Shelly
35
38
  File.open(path, "a+") { |f| f << generate }
36
39
  end
37
40
 
38
- # Public: Return databases for given Cloud in Cloudfile
39
- # Returns Array of databases
40
- def databases(cloud)
41
- content[cloud.to_s]["servers"].map do |server, settings|
42
- settings["databases"]
43
- end.flatten.uniq
44
- end
45
-
46
- # Public: Return databases to backup for given Cloud in Cloudfile
47
- # Returns Array of databases, except redis db
48
- def backup_databases(cloud)
49
- databases(cloud) - ['redis']
50
- end
51
-
52
- private
53
-
54
41
  # Internal: Load and parse Cloudfile
55
42
  def content
56
43
  return unless present?
@@ -61,7 +61,11 @@ module Shelly
61
61
  end
62
62
 
63
63
  def inside_git_repository?
64
- say_error "Must be run inside your project git repository" unless App.inside_git_repository?
64
+ unless App.inside_git_repository?
65
+ say_error %q{Current directory is not a git repository.
66
+ You need to initialize repository with `git init`.
67
+ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository}
68
+ end
65
69
  end
66
70
 
67
71
  def cloudfile_present?
@@ -112,7 +116,7 @@ module Shelly
112
116
  end
113
117
 
114
118
  app = Shelly::App.new
115
- app.code_name = cloud || clouds.first
119
+ app.code_name = cloud || clouds.first.code_name
116
120
  app
117
121
  end
118
122
 
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.1.24.pre"
2
+ VERSION = "0.1.24.pre2"
3
3
  end
data/lib/thor/basic.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Thor
2
+ module Shell
3
+
4
+ def print_wrapped(*args)
5
+ shell.print_wrapped(*args)
6
+ end
7
+
8
+ end
9
+ end
data/lib/thor/options.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  class Thor
2
2
  class Options < Arguments
3
+
3
4
  def check_unknown!
4
- unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ }
5
5
  raise UnknownArgumentError, "shelly: unrecognized option '#{@unknown.join(', ')}'\n" +
6
6
  "Usage: shelly [COMMAND]... [OPTIONS]\n" +
7
- "Try 'shelly --help' for more information" unless unknown.empty?
7
+ "Try 'shelly --help' for more information" unless @unknown.empty?
8
8
  end
9
+
9
10
  end
10
11
  end
data/lib/thor/thor.rb CHANGED
@@ -2,7 +2,7 @@ class Thor
2
2
  class << self
3
3
  def before_hook(method, options = {})
4
4
  @hook = {} unless @hook
5
- @hook[method] = {:only => Array(options[:only])}
5
+ @hook[method] = options
6
6
  end
7
7
 
8
8
  def hooks
@@ -28,46 +28,12 @@ class Thor
28
28
  rescue Thor::Error => e
29
29
  ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
30
30
  exit(1) if exit_on_failure?
31
- rescue Errno::EPIPE
32
- # This happens if a thor task is piped to something like `head`,
33
- # which closes the pipe when it's done reading. This will also
34
- # mean that if the pipe is closed, further unnecessary
35
- # computation will not occur.
36
- exit(0)
37
31
  end
38
32
 
39
- # We overwrite this method so namespace is shown
33
+ # We overwrite this method so namespace is show
40
34
  # shelly *backup* restore FILENAME
41
- def handle_argument_error(task, error, arity = nil)
42
- banner = self.banner(task, nil, self.to_s != 'Shelly::CLI::Main')
43
- raise InvocationError, "#{task.name.inspect} was called incorrectly. Call as `#{banner}`"
44
- end
45
-
46
- protected
47
- # this has to overwritten so that in tests args are passed correctly
48
- # only change is the commented line
49
- # its for some edge cases when boolean options are passed in some
50
- # strange order
51
- def dispatch(meth, given_args, given_opts, config) #:nodoc:
52
- meth ||= retrieve_task_name(given_args)
53
- task = all_tasks[normalize_task_name(meth)]
54
-
55
- if task
56
- args, opts = Thor::Options.split(given_args)
57
- else
58
- args, opts = given_args, nil
59
- task = Thor::DynamicTask.new(meth)
60
- end
61
-
62
- opts = given_opts || opts || []
63
- config.merge!(:current_task => task, :task_options => task.options)
64
-
65
- instance = new(args, opts, config)
66
- yield instance if block_given?
67
- # args = instance.args
68
- trailing = args[Range.new(arguments.size, -1)]
69
-
70
- instance.invoke_task(task, trailing || [])
35
+ def handle_argument_error(task, error)
36
+ raise InvocationError, "#{task.name.inspect} was called incorrectly. Call as #{self.banner(task, nil, self.to_s != 'Shelly::CLI::Main').inspect}."
71
37
  end
72
38
  end
73
39
  end
data/shelly.gemspec CHANGED
@@ -14,6 +14,8 @@ Gem::Specification.new do |s|
14
14
  s.rubyforge_project = "shelly"
15
15
  s.add_development_dependency "rspec", "~> 2.11.0"
16
16
  s.add_development_dependency "rake"
17
+ s.add_development_dependency "guard"
18
+ s.add_development_dependency "guard-rspec"
17
19
  s.add_development_dependency "simplecov"
18
20
  if RUBY_PLATFORM =~ /darwin/
19
21
  s.add_development_dependency "ruby_gntp"
@@ -21,7 +23,7 @@ Gem::Specification.new do |s|
21
23
  end
22
24
  s.add_development_dependency "fakefs"
23
25
  s.add_development_dependency "fakeweb"
24
- s.add_runtime_dependency "thor", "~> 0.15.4"
26
+ s.add_runtime_dependency "wijet-thor", "~> 0.14.7"
25
27
  s.add_runtime_dependency "rest-client"
26
28
  s.add_runtime_dependency "json"
27
29
  s.add_runtime_dependency "progressbar"
@@ -135,7 +135,9 @@ describe Shelly::CLI::Backup do
135
135
  FileUtils.mkdir_p("/projects/foo")
136
136
  Dir.chdir("/projects/foo")
137
137
  $stdout.stub(:puts)
138
- @cloudfile = mock(:backup_databases => ['postgresql', 'mongodb'], :clouds => ['foo-staging'])
138
+ @cloud = mock(:backup_databases => ['postgresql', 'mongodb'], :code_name => "foo-staging")
139
+ Shelly::Cloud.stub(:new).and_return(@cloud)
140
+ @cloudfile = mock(:present? => true, :clouds => [@cloud])
139
141
  Shelly::Cloudfile.stub(:new).and_return(@cloudfile)
140
142
  end
141
143
 
@@ -29,6 +29,7 @@ describe Shelly::CLI::Files do
29
29
 
30
30
  it "should exit if rsync isn't installed" do
31
31
  FakeFS::File.stub(:executable?).and_return(false)
32
+
32
33
  $stdout.should_receive(:puts).with(red "You need to install rsync in order to upload and download files")
33
34
  lambda { invoke(@cli_files, :upload, "some/path") }.should raise_error(SystemExit)
34
35
  end
@@ -299,7 +299,9 @@ describe Shelly::CLI::Main do
299
299
  # This spec tests inside_git_repository? hook
300
300
  it "should exit with message if command run outside git repository" do
301
301
  Shelly::App.stub(:inside_git_repository?).and_return(false)
302
- $stdout.should_receive(:puts).with("\e[31mMust be run inside your project git repository\e[0m")
302
+ $stdout.should_receive(:puts).with("\e[31mCurrent directory is not a git repository.
303
+ You need to initialize repository with `git init`.
304
+ More info at http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository\e[0m")
303
305
  lambda {
304
306
  fake_stdin(["", ""]) do
305
307
  invoke(@main, :add)
@@ -1273,7 +1275,7 @@ We have been notified about it. We will be adding new resources shortly")
1273
1275
  before do
1274
1276
  Shelly::App.stub(:inside_git_repository?).and_return(true)
1275
1277
  Bundler::Definition.stub_chain(:build, :specs, :map) \
1276
- .and_return(["thin"])
1278
+ .and_return(["thin", "pg", "delayed_job", "whenever"])
1277
1279
  Shelly::StructureValidator.any_instance.stub(:repo_paths) \
1278
1280
  .and_return(["config.ru", "Gemfile", "Gemfile.lock"])
1279
1281
  end
@@ -1342,6 +1344,62 @@ We have been notified about it. We will be adding new resources shortly")
1342
1344
  end
1343
1345
  end
1344
1346
 
1347
+ context "cloudfile" do
1348
+ before do
1349
+ cloud = mock(:code_name => "foo-staging", :databases => ["postgresql"],
1350
+ :whenever? => true, :delayed_job? => true, :to_s => "foo-staging")
1351
+ cloudfile = mock(:clouds => [cloud])
1352
+
1353
+ Shelly::Cloudfile.stub(:new).and_return(cloudfile)
1354
+ end
1355
+
1356
+ context "whenever is enabled" do
1357
+ it "should show that necessary gem doesn't exist" do
1358
+ Bundler::Definition.stub_chain(:build, :specs, :map).and_return([])
1359
+ $stdout.should_receive(:puts).with(" #{red("✗")} Gem 'whenever' is missing in the Gemfile for 'foo-staging' cloud")
1360
+ invoke(@main, :check)
1361
+ end
1362
+
1363
+ it "should show that necessary gem exists" do
1364
+ $stdout.should_receive(:puts).with(" #{green("✓")} Gem 'whenever' is present for 'foo-staging' cloud")
1365
+ invoke(@main, :check)
1366
+ end
1367
+ end
1368
+
1369
+ context "delayed_job is enabled" do
1370
+ it "should show that necessary gem doesn't exist" do
1371
+ Bundler::Definition.stub_chain(:build, :specs, :map).and_return([])
1372
+ $stdout.should_receive(:puts).with(" #{red("✗")} Gem 'delayed_job' is missing in the Gemfile for 'foo-staging' cloud")
1373
+ invoke(@main, :check)
1374
+ end
1375
+
1376
+ it "should show that necessary gem exists" do
1377
+ $stdout.should_receive(:puts).with(" #{green("✓")} Gem 'delayed_job' is present for 'foo-staging' cloud")
1378
+ invoke(@main, :check)
1379
+ end
1380
+ end
1381
+
1382
+ context "postgresql is enabled" do
1383
+ it "should show that necessary gem doesn't exist" do
1384
+ Bundler::Definition.stub_chain(:build, :specs, :map).and_return([])
1385
+ $stdout.should_receive(:puts).with(" #{red("✗")} Postgresql driver is missing in the Gemfile for 'foo-staging' cloud,\n we recommend adding 'pg' gem to Gemfile")
1386
+ invoke(@main, :check)
1387
+ end
1388
+
1389
+ it "should show that necessary gem exists - postgres" do
1390
+ Bundler::Definition.stub_chain(:build, :specs, :map).and_return(["postgres"])
1391
+ $stdout.should_receive(:puts).with(" #{green("✓")} Postgresql driver is present for 'foo-staging' cloud")
1392
+ invoke(@main, :check)
1393
+ end
1394
+
1395
+ it "should show that necessary gem exists - pg" do
1396
+ Bundler::Definition.stub_chain(:build, :specs, :map).and_return(["pg"])
1397
+ $stdout.should_receive(:puts).with(" #{green("✓")} Postgresql driver is present for 'foo-staging' cloud")
1398
+ invoke(@main, :check)
1399
+ end
1400
+ end
1401
+ end
1402
+
1345
1403
  context "when mysql gem exists" do
1346
1404
  it "should show that mysql gem is not supported by Shelly Cloud" do
1347
1405
  Bundler::Definition.stub_chain(:build, :specs, :map).and_return(["mysql"])
@@ -8,7 +8,6 @@ describe Shelly::CLI::User do
8
8
  Shelly::CLI::User.stub(:new).and_return(@cli_user)
9
9
  @client = mock
10
10
  Shelly::Client.stub(:new).and_return(@client)
11
- Shelly::User.stub(:guess_email).and_return("")
12
11
  $stdout.stub(:puts)
13
12
  $stdout.stub(:print)
14
13
  @client.stub(:token).and_return("abc")
@@ -16,6 +15,8 @@ describe Shelly::CLI::User do
16
15
  Dir.chdir("/projects/foo")
17
16
  @app = Shelly::App.new("foo-staging")
18
17
  File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
18
+ @cloud = Shelly::Cloud.new("code_name" => 'foo-staging')
19
+ Shelly::Cloud.stub(:new).and_return(@cloud)
19
20
  end
20
21
 
21
22
  describe "#help" do
@@ -47,7 +48,7 @@ describe Shelly::CLI::User do
47
48
  context "on success" do
48
49
  it "should display clouds and users" do
49
50
  @client.stub(:collaborations).and_return(response)
50
- $stdout.should_receive(:puts).with("Cloud foo-staging:")
51
+ $stdout.should_receive(:puts).with("Cloud #{@cloud}:")
51
52
  $stdout.should_receive(:puts).with(" user@example.com")
52
53
  $stdout.should_receive(:puts).with(" auser2@example2.com (invited)")
53
54
  invoke(@cli_user, :list)
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+ require "shelly/cloudfile"
3
+ require "shelly/cloud"
4
+
5
+ describe Shelly::Cloud do
6
+ before do
7
+ FileUtils.mkdir_p("/projects/foo")
8
+ Dir.chdir("/projects/foo")
9
+ @client = mock
10
+ Shelly::Client.stub(:new).and_return(@client)
11
+ @cloud = Shelly::Cloud.new("code_name" => "foo-staging", "content" => {})
12
+ end
13
+
14
+ describe "#databases" do
15
+ before do
16
+ content = {"servers" => {"app1" => {"databases" => ["postgresql", "redis"]},
17
+ "app2" => {"databases" => ["mongodb"]}}}
18
+ @cloud.stub(:content).and_return(content)
19
+ end
20
+
21
+ it "should return databases in cloudfile" do
22
+ @cloud.databases.should =~ ['redis', 'mongodb', 'postgresql']
23
+ end
24
+
25
+ it "should return databases except for redis" do
26
+ @cloud.backup_databases.should =~ ['postgresql', 'mongodb']
27
+ end
28
+ end
29
+
30
+ describe "#delayed_job?" do
31
+ it "should return true if present" do
32
+ content = {"servers" => {"app1" => {"delayed_job" => 1}}}
33
+ @cloud.stub(:content).and_return(content)
34
+ @cloud.delayed_job?.should be_true
35
+ end
36
+
37
+ it "should retrun false if not present" do
38
+ content = {"servers" => {"app1" => {"size" => "small"}}}
39
+ @cloud.stub(:content).and_return(content)
40
+ @cloud.delayed_job?.should be_false
41
+ end
42
+ end
43
+
44
+ describe "#whenever?" do
45
+ it "should return true if present" do
46
+ content = {"servers" => {"app1" => {"whenever" => true}}}
47
+ @cloud.stub(:content).and_return(content)
48
+ @cloud.whenever?.should be_true
49
+ end
50
+
51
+ it "should return false if not present" do
52
+ content = {"servers" => {"app1" => {"size" => "small"}}}
53
+ @cloud.stub(:content).and_return(content)
54
+ @cloud.whenever?.should be_false
55
+ end
56
+ end
57
+ end
@@ -5,7 +5,6 @@ describe Shelly::Cloudfile do
5
5
  before do
6
6
  FileUtils.mkdir_p("/projects/foo")
7
7
  Dir.chdir("/projects/foo")
8
- @hash = {:code_name => {:code => "test"}}
9
8
  @client = mock
10
9
  Shelly::Client.stub(:new).and_return(@client)
11
10
  @cloudfile = Shelly::Cloudfile.new
@@ -22,6 +21,68 @@ describe Shelly::Cloudfile do
22
21
  yaml.should == {"domains" => ["*.example.com", "example.com"]}
23
22
  end
24
23
 
24
+ describe "#content" do
25
+ it "should fetch and parse file content" do
26
+ content = <<-config
27
+ foo-staging:
28
+ ruby_version: 1.9.3
29
+ environment: production
30
+ monitoring_email: bob@example.com
31
+ domains:
32
+ - foo-staging.winniecloud.com
33
+ servers:
34
+ app1:
35
+ size: small
36
+ thin: 2
37
+ whenever: on
38
+ delayed_job: 1
39
+ databases:
40
+ - postgresql
41
+ config
42
+ File.open("/projects/foo/Cloudfile", "w") { |f| f << content }
43
+ @cloudfile.content.should == {"foo-staging" => {
44
+ "ruby_version" => "1.9.3",
45
+ "environment" => "production",
46
+ "monitoring_email" => "bob@example.com",
47
+ "domains" => ["foo-staging.winniecloud.com"],
48
+ "servers" => { "app1" =>
49
+ {"size" => "small",
50
+ "thin" => 2,
51
+ "whenever" => true,
52
+ "delayed_job" => 1,
53
+ "databases" => ["postgresql"]}
54
+ }
55
+ }
56
+ }
57
+ end
58
+ end
59
+
60
+ describe "#clouds" do
61
+ it "should create Cloud objects" do
62
+ content = <<-config
63
+ foo-staging:
64
+ ruby_version: 1.9.3
65
+ servers:
66
+ app1:
67
+ size: small
68
+ foo-production:
69
+ environment: production
70
+ servers:
71
+ app1:
72
+ thin: 2
73
+ config
74
+ File.open("/projects/foo/Cloudfile", "w") { |f| f << content }
75
+ cloud1 = Shelly::Cloud.should_receive(:new).with({"code_name"=>"foo-staging",
76
+ "content"=>{"ruby_version"=>"1.9.3",
77
+ "servers"=>{"app1"=>{"size"=>"small"}}}})
78
+ cloud2 = Shelly::Cloud.should_receive(:new).with({"code_name"=>"foo-production",
79
+ "content"=>{"environment"=>"production",
80
+ "servers"=>{"app1"=>{"thin"=>2}}}})
81
+
82
+ @cloudfile.clouds
83
+ end
84
+ end
85
+
25
86
  describe "#generate" do
26
87
  before do
27
88
  @cloudfile.code_name = "foo-staging"
@@ -88,31 +149,6 @@ config
88
149
  end
89
150
  end
90
151
 
91
- describe "#databases" do
92
- before do
93
- content = <<-config
94
- foo-staging:
95
- servers:
96
- app1:
97
- databases:
98
- - postgresql
99
- - redis
100
- app2:
101
- databases:
102
- - mongodb
103
- config
104
- File.open("Cloudfile", 'w') {|f| f.write(content) }
105
- end
106
-
107
- it "should return databases in cloudfile" do
108
- @cloudfile.databases("foo-staging").should =~ ['redis', 'mongodb', 'postgresql']
109
- end
110
-
111
- it "should return databases except for redis" do
112
- @cloudfile.backup_databases("foo-staging").should =~ ['postgresql', 'mongodb']
113
- end
114
- end
115
-
116
152
  describe "#create" do
117
153
  before do
118
154
  @cloudfile.stub(:generate).and_return("foo-staging:")
data/spec/spec_helper.rb CHANGED
@@ -9,6 +9,7 @@ require "helpers"
9
9
  require "input_faker"
10
10
  require "fakefs/spec_helpers"
11
11
  require "fakeweb"
12
+ require "launchy"
12
13
 
13
14
  ENV['THOR_COLUMNS'] = "180"
14
15
  FakeWeb.allow_net_connect = false
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.24.pre
4
+ version: 0.1.24.pre2
5
5
  prerelease: 7
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-08-14 00:00:00.000000000 Z
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -43,6 +43,38 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: simplecov
48
80
  requirement: !ruby/object:Gem::Requirement
@@ -124,13 +156,13 @@ dependencies:
124
156
  - !ruby/object:Gem::Version
125
157
  version: '0'
126
158
  - !ruby/object:Gem::Dependency
127
- name: thor
159
+ name: wijet-thor
128
160
  requirement: !ruby/object:Gem::Requirement
129
161
  none: false
130
162
  requirements:
131
163
  - - ~>
132
164
  - !ruby/object:Gem::Version
133
- version: 0.15.4
165
+ version: 0.14.7
134
166
  type: :runtime
135
167
  prerelease: false
136
168
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,7 +170,7 @@ dependencies:
138
170
  requirements:
139
171
  - - ~>
140
172
  - !ruby/object:Gem::Version
141
- version: 0.15.4
173
+ version: 0.14.7
142
174
  - !ruby/object:Gem::Dependency
143
175
  name: rest-client
144
176
  requirement: !ruby/object:Gem::Requirement
@@ -247,6 +279,7 @@ files:
247
279
  - .travis.yml
248
280
  - CHANGELOG.md
249
281
  - Gemfile
282
+ - Guardfile
250
283
  - README.md
251
284
  - Rakefile
252
285
  - bin/shelly
@@ -265,6 +298,7 @@ files:
265
298
  - lib/shelly/cli/runner.rb
266
299
  - lib/shelly/cli/user.rb
267
300
  - lib/shelly/client.rb
301
+ - lib/shelly/cloud.rb
268
302
  - lib/shelly/cloudfile.rb
269
303
  - lib/shelly/download_progress_bar.rb
270
304
  - lib/shelly/helpers.rb
@@ -274,6 +308,7 @@ files:
274
308
  - lib/shelly/user.rb
275
309
  - lib/shelly/version.rb
276
310
  - lib/thor/arguments.rb
311
+ - lib/thor/basic.rb
277
312
  - lib/thor/options.rb
278
313
  - lib/thor/thor.rb
279
314
  - scrolls/shellycloud.rb
@@ -290,6 +325,7 @@ files:
290
325
  - spec/shelly/cli/runner_spec.rb
291
326
  - spec/shelly/cli/user_spec.rb
292
327
  - spec/shelly/client_spec.rb
328
+ - spec/shelly/cloud_spec.rb
293
329
  - spec/shelly/cloudfile_spec.rb
294
330
  - spec/shelly/download_progress_bar_spec.rb
295
331
  - spec/shelly/model_spec.rb
@@ -334,6 +370,7 @@ test_files:
334
370
  - spec/shelly/cli/runner_spec.rb
335
371
  - spec/shelly/cli/user_spec.rb
336
372
  - spec/shelly/client_spec.rb
373
+ - spec/shelly/cloud_spec.rb
337
374
  - spec/shelly/cloudfile_spec.rb
338
375
  - spec/shelly/download_progress_bar_spec.rb
339
376
  - spec/shelly/model_spec.rb