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