shelly 0.1.24.pre → 0.1.24.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +1 -0
- data/Guardfile +6 -0
- data/README.md +4 -0
- data/lib/shelly.rb +1 -0
- data/lib/shelly/app.rb +1 -1
- data/lib/shelly/cli/backup.rb +2 -2
- data/lib/shelly/cli/command.rb +1 -0
- data/lib/shelly/cli/config.rb +2 -1
- data/lib/shelly/cli/main.rb +45 -14
- data/lib/shelly/cloud.rb +49 -0
- data/lib/shelly/cloudfile.rb +4 -17
- data/lib/shelly/helpers.rb +6 -2
- data/lib/shelly/version.rb +1 -1
- data/lib/thor/basic.rb +9 -0
- data/lib/thor/options.rb +3 -2
- data/lib/thor/thor.rb +4 -38
- data/shelly.gemspec +3 -1
- data/spec/shelly/cli/backup_spec.rb +3 -1
- data/spec/shelly/cli/files_spec.rb +1 -0
- data/spec/shelly/cli/main_spec.rb +60 -2
- data/spec/shelly/cli/user_spec.rb +3 -2
- data/spec/shelly/cloud_spec.rb +57 -0
- data/spec/shelly/cloudfile_spec.rb +62 -26
- data/spec/spec_helper.rb +1 -0
- metadata +42 -5
data/CHANGELOG.md
CHANGED
data/Guardfile
ADDED
data/README.md
CHANGED
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/)
|
data/lib/shelly/cli/backup.rb
CHANGED
@@ -32,7 +32,7 @@ module Shelly
|
|
32
32
|
|
33
33
|
say "Available backups:", :green
|
34
34
|
say_new_line
|
35
|
-
print_table(to_display, :
|
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
|
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
|
data/lib/shelly/cli/command.rb
CHANGED
data/lib/shelly/cli/config.rb
CHANGED
@@ -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
|
data/lib/shelly/cli/main.rb
CHANGED
@@ -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, :
|
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}", :
|
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"]}", :
|
154
|
-
print_wrapped "Deployed commit message: #{app.git_info["deployed_commit_message"]}", :
|
155
|
-
print_wrapped "Deployed by: #{app.git_info["deployed_push_author"]}", :
|
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"]}", :
|
158
|
-
print_wrapped "Web server IP: #{app.web_server_ip}", :
|
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:", :
|
162
|
+
print_wrapped "Statistics:", :ident => 2
|
162
163
|
app.statistics.each do |stat|
|
163
|
-
print_wrapped "#{stat['name']}:", :
|
164
|
-
print_wrapped "Load average: 1m: #{stat['load']['avg01']}, 5m: #{stat['load']['avg05']}, 15m: #{stat['load']['avg15']}", :
|
165
|
-
print_wrapped "CPU: #{stat['cpu']['wait']}%, MEM: #{stat['memory']['percent']}%, SWAP: #{stat['swap']['percent']}%", :
|
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
|
-
|
399
|
-
|
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)",
|
data/lib/shelly/cloud.rb
ADDED
@@ -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
|
data/lib/shelly/cloudfile.rb
CHANGED
@@ -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
|
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?
|
data/lib/shelly/helpers.rb
CHANGED
@@ -61,7 +61,11 @@ module Shelly
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def inside_git_repository?
|
64
|
-
|
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
|
|
data/lib/shelly/version.rb
CHANGED
data/lib/thor/basic.rb
ADDED
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] =
|
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
|
33
|
+
# We overwrite this method so namespace is show
|
40
34
|
# shelly *backup* restore FILENAME
|
41
|
-
def handle_argument_error(task, error
|
42
|
-
|
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.
|
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
|
-
@
|
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[
|
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
|
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
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.
|
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-
|
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.
|
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.
|
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
|