dbmanager 0.0.2.alpha
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/.gitignore +4 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE +18 -0
- data/README.md +90 -0
- data/Rakefile +8 -0
- data/dbmanager.gemspec +26 -0
- data/lib/dbmanager/adapters/mysql.rb +87 -0
- data/lib/dbmanager/dumper.rb +31 -0
- data/lib/dbmanager/importer.rb +22 -0
- data/lib/dbmanager/runner.rb +43 -0
- data/lib/dbmanager/version.rb +3 -0
- data/lib/dbmanager/yml_parser.rb +50 -0
- data/lib/dbmanager.rb +41 -0
- data/lib/tasks/dbmanager.rake +11 -0
- data/rails_generators/dbmanager/USAGE +6 -0
- data/rails_generators/dbmanager/dbmanager_generator.rb +37 -0
- data/spec/fixtures/adapter_sample.rb +21 -0
- data/spec/fixtures/config/database.yml +46 -0
- data/spec/fixtures/config/dbmanager_override.yml +6 -0
- data/spec/lib/adapters/mysql_spec.rb +124 -0
- data/spec/lib/dbmanager_spec.rb +38 -0
- data/spec/lib/dumper_spec.rb +28 -0
- data/spec/lib/importer_spec.rb +24 -0
- data/spec/lib/runner_spec.rb +63 -0
- data/spec/lib/yml_parser_spec.rb +51 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/std_stub.rb +6 -0
- metadata +125 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2012 Andrea Longhi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
## Dbmanager
|
2
|
+
|
3
|
+
[](http://travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME])
|
4
|
+
|
5
|
+
This gem will add some convenience rake tasks that will help you manage database
|
6
|
+
dumps and imports. At the moment only the mysql adapter is available.
|
7
|
+
|
8
|
+
The gems works both on rails 2.x and 3.x applications, but due to rails 2.x
|
9
|
+
limitations you have to run a generator, see the usage section
|
10
|
+
|
11
|
+
|
12
|
+
### Usage
|
13
|
+
|
14
|
+
Add the gem to your gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'dbmanager', :git => 'git://github.com/spaghetticode/dbmanager.git'
|
18
|
+
```
|
19
|
+
|
20
|
+
If you're on a rails 2.x application you also need to run:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
script/generate dbmanager
|
24
|
+
```
|
25
|
+
that will copy the gem rake tasks file into the lib/tasks directory.
|
26
|
+
|
27
|
+
|
28
|
+
#### Database Dumps
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
rake db:dump
|
32
|
+
```
|
33
|
+
|
34
|
+
You will be prompted to choose the target dir (defaults to tmp) and the sql file
|
35
|
+
name (sql extension will be added automatically). If the file already exists, it
|
36
|
+
will be overwritten.
|
37
|
+
|
38
|
+
|
39
|
+
#### Database Imports
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
rake db:import
|
43
|
+
```
|
44
|
+
|
45
|
+
You will be prompted to choose the source and the target environment db, and the
|
46
|
+
source db will be imported into the target db. All environments containing the
|
47
|
+
string 'production' in their name are protected by default, which means you cannot
|
48
|
+
overwrite them unless you explicitly override this setting in the override file
|
49
|
+
(see next section for more info).
|
50
|
+
|
51
|
+
#### BEWARE
|
52
|
+
|
53
|
+
import process is destructive, be careful on what environment you choose to
|
54
|
+
overwite. I take no responsibility for misuse or bugs in the code ;-)
|
55
|
+
|
56
|
+
|
57
|
+
#### Override database.yml
|
58
|
+
|
59
|
+
Since some settings may be specific to the server environment (ie. host could
|
60
|
+
be a private ip not reachable from anywhere) you can overwrite the settings in
|
61
|
+
database.yml by adding a dbmanager_override.yml file in your rails config dir.
|
62
|
+
Another use is to set some environments as protected, or vice versa allow to
|
63
|
+
overwrite production env.
|
64
|
+
For example if we want to override the following setting, and make the database
|
65
|
+
protected from overwriting:
|
66
|
+
|
67
|
+
```yaml
|
68
|
+
beta:
|
69
|
+
host: 192.168.0.1
|
70
|
+
```
|
71
|
+
we should put in dbmanager_override.yml this:
|
72
|
+
|
73
|
+
```yaml
|
74
|
+
beta:
|
75
|
+
host: 234.234.234.234
|
76
|
+
protected: true
|
77
|
+
```
|
78
|
+
|
79
|
+
Instead, if we want to make the production env writable we should add this:
|
80
|
+
|
81
|
+
```yaml
|
82
|
+
production:
|
83
|
+
protected: false
|
84
|
+
```
|
85
|
+
|
86
|
+
|
87
|
+
### TODO
|
88
|
+
|
89
|
+
* Add more db adapters
|
90
|
+
* remove views from mysql dumps so they don't interfere in the import process
|
data/Rakefile
ADDED
data/dbmanager.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dbmanager/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dbmanager"
|
7
|
+
s.version = Dbmanager::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["andrea longhi"]
|
10
|
+
s.email = ["andrea.longhi@mikamai.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{database manager}
|
13
|
+
s.description = %q{helps manage db dumps and imports via rake tasks}
|
14
|
+
|
15
|
+
s.rubyforge_project = "dbmanager"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency 'activesupport'
|
23
|
+
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_development_dependency 'rake'
|
26
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Dbmanager
|
4
|
+
module Adapters
|
5
|
+
module Mysql
|
6
|
+
class EnvironmentProtectedError < StandardError
|
7
|
+
def initialize(message=nil)
|
8
|
+
super message || 'sorry the environment is protected from writing'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Connection
|
13
|
+
attr_reader :environment
|
14
|
+
|
15
|
+
delegate :host, :adapter, :database, :username, :password, :port, :encoding, :protected, :name, :to => :environment
|
16
|
+
|
17
|
+
def initialize(environment)
|
18
|
+
@environment = environment
|
19
|
+
end
|
20
|
+
|
21
|
+
def params
|
22
|
+
"-u#{username} #{flag :password, :p} #{flag :host, :h} #{flag :port, :P} #{database}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def flag(name, flag)
|
26
|
+
send(name).present? ? "-#{flag}#{send(name)}" : ''
|
27
|
+
end
|
28
|
+
|
29
|
+
def protected?
|
30
|
+
if name =~ /production/
|
31
|
+
protected != false
|
32
|
+
else
|
33
|
+
protected == true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Dumper
|
39
|
+
attr_reader :source, :filename
|
40
|
+
|
41
|
+
def initialize(source, filename)
|
42
|
+
@source = source
|
43
|
+
@filename = filename
|
44
|
+
end
|
45
|
+
|
46
|
+
def run
|
47
|
+
Dbmanager.execute! dump_command
|
48
|
+
end
|
49
|
+
|
50
|
+
def dump_command
|
51
|
+
"mysqldump #{source.params} > #{filename}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Importer
|
56
|
+
attr_reader :source, :target
|
57
|
+
|
58
|
+
def initialize(source, target)
|
59
|
+
@source = source
|
60
|
+
@target = target
|
61
|
+
end
|
62
|
+
|
63
|
+
def run
|
64
|
+
Dumper.new(source, temp_file).run
|
65
|
+
Dbmanager.execute! import_command
|
66
|
+
remove_temp_file
|
67
|
+
end
|
68
|
+
|
69
|
+
def import_command
|
70
|
+
unless target.protected?
|
71
|
+
"mysql #{target.params} < #{temp_file}"
|
72
|
+
else
|
73
|
+
raise EnvironmentProtectedError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def remove_temp_file
|
78
|
+
Dbmanager.execute "rm #{temp_file}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def temp_file
|
82
|
+
@temp_file ||= "/tmp/#{Time.now.strftime '%y%m%d%H%M%S'}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dbmanager
|
2
|
+
class Dumper < Runner
|
3
|
+
attr_reader :filename
|
4
|
+
|
5
|
+
def initialize(input=STDIN, output=STDOUT)
|
6
|
+
super
|
7
|
+
@filename = set_filename
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
adapter::Dumper.new(source, filename).run
|
12
|
+
output.puts "Database Dump completed to #{filename}"
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_filename
|
18
|
+
output.puts "\nPlease choose target file (defaults to #{default_filename})\n\n"
|
19
|
+
get_filename
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_filename
|
23
|
+
"#{Dbmanager.rails_root.join 'tmp', "#{source.database}.sql"}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_filename
|
27
|
+
filename = input.gets.chomp
|
28
|
+
filename.blank? ? default_filename : Dbmanager.rails_root.join(filename)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Dbmanager
|
2
|
+
class Importer < Runner
|
3
|
+
attr_reader :target
|
4
|
+
|
5
|
+
def initialize(input=STDIN, output=STDOUT)
|
6
|
+
super
|
7
|
+
@target = adapter::Connection.new(set_target)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
adapter::Importer.new(source, target).run
|
12
|
+
output.puts 'Database Import completed.'
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_target
|
18
|
+
output.puts "\nPlease choose target db:\n\n"
|
19
|
+
get_env
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Dbmanager
|
2
|
+
class Runner
|
3
|
+
attr_reader :input, :output, :environments, :source, :adapter
|
4
|
+
|
5
|
+
def self.run
|
6
|
+
new.run
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(input, output)
|
10
|
+
@input = input
|
11
|
+
@output = output
|
12
|
+
@environments = YmlParser.environments
|
13
|
+
@adapter = set_adapter
|
14
|
+
@source = adapter::Connection.new(set_source)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_adapter
|
18
|
+
adapters = environments.map {|name, env| env.adapter}.uniq
|
19
|
+
if adapters.size > 1
|
20
|
+
raise AdapterError
|
21
|
+
else
|
22
|
+
Dbmanager::Adapters.const_get adapters.first.capitalize
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_source
|
27
|
+
output.puts "\nPlease choose source db:\n\n"
|
28
|
+
get_env
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_env
|
32
|
+
environments.keys.each_with_index do |name, i|
|
33
|
+
output.puts "#{i+1}) #{name}"
|
34
|
+
end
|
35
|
+
output.puts
|
36
|
+
pos = ''
|
37
|
+
until (1..environments.size).include? pos
|
38
|
+
pos = input.gets.chomp.to_i
|
39
|
+
end
|
40
|
+
environments.values[pos-1]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'active_support/core_ext/hash'
|
5
|
+
|
6
|
+
module Dbmanager
|
7
|
+
module YmlParser
|
8
|
+
class Environment < OpenStruct; end
|
9
|
+
|
10
|
+
extend self
|
11
|
+
attr_writer :config
|
12
|
+
|
13
|
+
def config
|
14
|
+
@config ||= yml_load(db_config_file).deep_merge(override_config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def override_config
|
18
|
+
File.file?(db_override_file) ? yml_load(db_override_file) : {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload_config
|
22
|
+
@config = nil
|
23
|
+
config
|
24
|
+
end
|
25
|
+
|
26
|
+
def environments
|
27
|
+
@environments ||= begin
|
28
|
+
config.select do |key, value|
|
29
|
+
value.has_key?('adapter')
|
30
|
+
end.each_with_object(ActiveSupport::OrderedHash.new) do |arr, hash|
|
31
|
+
hash[arr[0]] = Environment.new arr[1].merge(:name => arr[0])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def yml_load(path)
|
39
|
+
YAML.load ERB.new(File.read(path)).result
|
40
|
+
end
|
41
|
+
|
42
|
+
def db_config_file
|
43
|
+
File.join Dbmanager.rails_root, 'config', 'database.yml'
|
44
|
+
end
|
45
|
+
|
46
|
+
def db_override_file
|
47
|
+
File.join Dbmanager.rails_root, 'config', 'dbmanager_override.yml'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/dbmanager.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Dbmanager
|
2
|
+
class AdapterError < StandardError
|
3
|
+
def initialize(message=nil)
|
4
|
+
super message || 'You cannot mix different adapters!'
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class CommandError < StandardError
|
9
|
+
def initialize(message=nil)
|
10
|
+
super message || 'Could not execute command!'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if defined? Rails and Rails.version.to_f >= 3
|
15
|
+
class Engine < Rails::Engine; end
|
16
|
+
end
|
17
|
+
|
18
|
+
extend self
|
19
|
+
|
20
|
+
def rails_root
|
21
|
+
Rails.root
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute(command, output=STDOUT)
|
25
|
+
output.puts %(executing "#{command}")
|
26
|
+
system command
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute!(command)
|
30
|
+
execute(command) or raise CommandError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'active_support/deprecation'
|
35
|
+
require 'active_support/core_ext/module'
|
36
|
+
require 'active_support/ordered_hash'
|
37
|
+
require 'active_support/core_ext/enumerable'
|
38
|
+
|
39
|
+
%w[yml_parser adapters/mysql runner importer dumper].each do |string|
|
40
|
+
require File.expand_path "../dbmanager/#{string}", __FILE__
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class DbmanagerGenerator < Rails::Generator::Base
|
2
|
+
RAKE_FILENAME = 'dbmanager.rake'
|
3
|
+
RAKE_FILE_PATH = File.expand_path "../../../lib/tasks/#{RAKE_FILENAME}", __FILE__
|
4
|
+
|
5
|
+
def manifest
|
6
|
+
record do |m|
|
7
|
+
contents = File.readlines(RAKE_FILE_PATH).unshift(lib_requires)
|
8
|
+
File.open(rails_rake_file, 'w') {|f| f.puts contents.join}
|
9
|
+
print_message
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def rails_rake_file
|
16
|
+
Rails.root.join 'lib/tasks', RAKE_FILENAME
|
17
|
+
end
|
18
|
+
|
19
|
+
def lib_requires
|
20
|
+
"require 'dbmanager.rb'\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def print_message
|
24
|
+
message = "Rake file copied to #{rails_rake_file}"
|
25
|
+
puts "*"*message.size
|
26
|
+
puts message
|
27
|
+
puts "*"*message.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def banner
|
31
|
+
<<-EOS
|
32
|
+
Adds dbmanager rake file to yout rails 2.x application
|
33
|
+
|
34
|
+
USAGE: #{$0} #{spec.name}
|
35
|
+
EOS
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dbmanager
|
2
|
+
module Adapters
|
3
|
+
module SomeAdapter
|
4
|
+
class Connection
|
5
|
+
def initialize(*args); end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Dumper
|
9
|
+
def initialize(*args); end
|
10
|
+
|
11
|
+
def run; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Importer
|
15
|
+
def initialize(*args); end
|
16
|
+
|
17
|
+
def run; end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
development:
|
2
|
+
adapter: mysql
|
3
|
+
database: demo_development
|
4
|
+
encoding: utf8
|
5
|
+
username: root
|
6
|
+
password: devil
|
7
|
+
|
8
|
+
# ale i tuoi settaggi specifici devi metterli in config/dbloginyml, non qui
|
9
|
+
# socket: /Applications/MAMP/tmp/mysql/mysql.sock
|
10
|
+
|
11
|
+
beta:
|
12
|
+
adapter: mysql
|
13
|
+
database: demo_beta
|
14
|
+
username: beta_username
|
15
|
+
password: asdasd
|
16
|
+
port: 3306
|
17
|
+
host: 123.123.123.123
|
18
|
+
encoding: utf8
|
19
|
+
|
20
|
+
production:
|
21
|
+
adapter: mysql
|
22
|
+
database: demo_production
|
23
|
+
username: production_username
|
24
|
+
password: asdasd
|
25
|
+
port: 3306
|
26
|
+
host: 123.123.123.123
|
27
|
+
encoding: utf8
|
28
|
+
|
29
|
+
test:
|
30
|
+
adapter: mysql
|
31
|
+
database: demo_test
|
32
|
+
encoding: utf8
|
33
|
+
port: 3306
|
34
|
+
host: 345.345.345.345
|
35
|
+
username: root
|
36
|
+
password: devil
|
37
|
+
|
38
|
+
shop:
|
39
|
+
adapter: mysql
|
40
|
+
database: demo_shop
|
41
|
+
username: demo_username
|
42
|
+
password: asdasd
|
43
|
+
adapter: mysql
|
44
|
+
port: 3306
|
45
|
+
host: 123.123.123.123
|
46
|
+
encoding: utf8
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Dbmanager
|
4
|
+
module Adapters
|
5
|
+
module Mysql
|
6
|
+
describe Connection do
|
7
|
+
before { stub_rails_root }
|
8
|
+
|
9
|
+
describe 'a mysql adapter instance' do
|
10
|
+
subject { Connection.new Dbmanager::YmlParser.environments['test'] }
|
11
|
+
|
12
|
+
it 'delegates to environment object' do
|
13
|
+
subject.host.should == subject.environment.host
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#params' do
|
17
|
+
it 'returns expected string' do
|
18
|
+
subject.params.should == '-uroot -pdevil -h345.345.345.345 -P3306 demo_test'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#protected?' do
|
23
|
+
it 'is false by default' do
|
24
|
+
subject.should_not be_protected
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when name matches production string' do
|
28
|
+
it 'is true by default ' do
|
29
|
+
subject.stub! :name => 'production-merge'
|
30
|
+
subject.should be_protected
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when protected is set to false' do
|
34
|
+
it 'is false' do
|
35
|
+
subject.stub! :name => 'production', :protected => false
|
36
|
+
subject.should_not be_protected
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#flag' do
|
43
|
+
context 'when requested flag has a value' do
|
44
|
+
it 'returns expected string' do
|
45
|
+
subject.flag(:password, :p).should == '-pdevil'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when requested flag has no value' do
|
50
|
+
it 'returns a blank string' do
|
51
|
+
subject.stub!(:password => nil)
|
52
|
+
subject.flag(:password, :p).should == ''
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Importer do
|
60
|
+
describe 'an importer instance' do
|
61
|
+
before { Time.stub! :now => Time.parse('2012/03/23 12:30:32') }
|
62
|
+
let(:target) { mock :params => 'target-params', :protected? => false, :name => 'beta' }
|
63
|
+
let(:source) { mock :params => 'source-params', :protected? => false, :name => 'development' }
|
64
|
+
subject { Importer.new source, target }
|
65
|
+
|
66
|
+
it 'has target and source attribute methods' do
|
67
|
+
%w[source target].each { |m| subject.should respond_to(m) }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'has a timestamped temporary file' do
|
71
|
+
subject.temp_file.should == '/tmp/120323123032'
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#import_command' do
|
75
|
+
context 'when environment is not protected' do
|
76
|
+
it 'returns expected command' do
|
77
|
+
subject.import_command.should == 'mysql target-params < /tmp/120323123032'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when environment is protected' do
|
82
|
+
it 'raises EnvironmentProtectedError' do
|
83
|
+
target.stub! :protected? => true
|
84
|
+
expect { subject.import_command }.to raise_error(EnvironmentProtectedError)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#remove_temp_file' do
|
90
|
+
it 'tries to remove the temporary file' do
|
91
|
+
Dbmanager.should_receive(:execute).with("rm #{subject.temp_file}")
|
92
|
+
subject.remove_temp_file
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#run' do
|
97
|
+
it 'dumps the db' do
|
98
|
+
Dbmanager.stub!(:execute! => nil)
|
99
|
+
Dumper.should_receive(:new).and_return(mock.as_null_object)
|
100
|
+
subject.run
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'imports the db' do
|
104
|
+
Dumper.stub! :new => mock.as_null_object
|
105
|
+
subject.stub!(:remove_temp_file => true)
|
106
|
+
Dbmanager.should_receive(:execute!).with(subject.import_command)
|
107
|
+
subject.run
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe Dumper do
|
114
|
+
subject { Dumper.new mock(:params => 'source-params'), '/tmp/dump_file.sql' }
|
115
|
+
|
116
|
+
describe '#dump_command' do
|
117
|
+
it 'returns expected command' do
|
118
|
+
subject.dump_command.should == 'mysqldump source-params > /tmp/dump_file.sql'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dbmanager do
|
4
|
+
describe '#rails_root' do
|
5
|
+
it 'should wrap Rails.root' do
|
6
|
+
Rails = mock unless defined? Rails
|
7
|
+
Rails.should_receive :root
|
8
|
+
Dbmanager.rails_root
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#execute' do
|
13
|
+
it 'execute a system command' do
|
14
|
+
Dbmanager.should_receive(:system)
|
15
|
+
Dbmanager.execute('echo')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'outputs the command that is executing' do
|
19
|
+
output = STDStub.new
|
20
|
+
Dbmanager.execute('echo', output)
|
21
|
+
output.content.should include 'executing "echo"'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#execute!' do
|
26
|
+
it 'wraps a call to #execute' do
|
27
|
+
Dbmanager.should_receive(:execute).and_return(true)
|
28
|
+
Dbmanager.execute!('echo')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'raises an error when not successful' do
|
32
|
+
Dbmanager.stub!(:system => false)
|
33
|
+
expect do
|
34
|
+
Dbmanager.execute!('echo')
|
35
|
+
end.to raise_error(Dbmanager::CommandError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/adapter_sample'
|
3
|
+
|
4
|
+
module Dbmanager
|
5
|
+
describe Dumper do
|
6
|
+
describe '#run' do
|
7
|
+
let(:input) { STDStub.new }
|
8
|
+
let(:output) { STDStub.new }
|
9
|
+
|
10
|
+
subject { Dumper.new(input, output) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_rails_root
|
14
|
+
input.stub!(:gets => mock.as_null_object)
|
15
|
+
Dumper.any_instance.stub(
|
16
|
+
:set_source => nil,
|
17
|
+
:adapter => Adapters::SomeAdapter,
|
18
|
+
:default_filename => 'default_filename'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'dumps a db' do
|
23
|
+
Adapters::SomeAdapter::Dumper.should_receive(:new).and_return(mock(:run => nil))
|
24
|
+
subject.run
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/adapter_sample'
|
3
|
+
|
4
|
+
module Dbmanager
|
5
|
+
describe Importer do
|
6
|
+
describe '#run' do
|
7
|
+
let(:input) { STDStub.new }
|
8
|
+
let(:output) { STDStub.new }
|
9
|
+
|
10
|
+
subject { Importer.new(input, output) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_rails_root
|
14
|
+
input.stub!(:gets => "1\n")
|
15
|
+
Importer.any_instance.stub(:adapter => Adapters::SomeAdapter)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'imports a db' do
|
19
|
+
Adapters::SomeAdapter::Importer.should_receive(:new).and_return(mock(:run => nil))
|
20
|
+
subject.run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/adapter_sample'
|
3
|
+
|
4
|
+
module Dbmanager
|
5
|
+
describe Runner do
|
6
|
+
let(:input) { STDStub.new }
|
7
|
+
let(:output) { STDStub.new }
|
8
|
+
|
9
|
+
describe '#initialize' do
|
10
|
+
let(:envs) { [mock] }
|
11
|
+
|
12
|
+
subject { Runner.new(input, output) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
YmlParser.stub!(:environments => envs)
|
16
|
+
Runner.any_instance.stub(:set_adapter => Adapters::SomeAdapter, :set_source => nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'sets expected attributes' do
|
20
|
+
subject.input.should == input
|
21
|
+
subject.output.should == output
|
22
|
+
subject.environments.should == envs
|
23
|
+
subject.adapter.should == Adapters::SomeAdapter
|
24
|
+
subject.source.should be_a(Adapters::SomeAdapter::Connection)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#set_adapter' do
|
29
|
+
subject { Runner.new(input, output) }
|
30
|
+
|
31
|
+
before { Runner.any_instance.stub(:set_source => nil) }
|
32
|
+
|
33
|
+
context 'when different adapters are mixed' do
|
34
|
+
it 'raises an error' do
|
35
|
+
envs = {:beta => mock(:adapter => 'Mysql'), :development => mock(:adapter => 'Sqlite3')}
|
36
|
+
subject.stub!(:environments => envs)
|
37
|
+
expect { subject.set_adapter }.to raise_error(AdapterError)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when there is only one kind of adapter' do
|
42
|
+
it 'returns an adapter class' do
|
43
|
+
envs = {:beta => mock(:adapter => 'Mysql'), :development => mock(:adapter => 'Mysql')}
|
44
|
+
subject.instance_variable_set '@environments', envs
|
45
|
+
Dbmanager::Adapters.should_receive(:const_get).and_return(Adapters::SomeAdapter)
|
46
|
+
subject.set_adapter.should == Adapters::SomeAdapter
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#set_source' do
|
52
|
+
subject { Runner.new(input, output) }
|
53
|
+
|
54
|
+
before { Runner.any_instance.stub(:set_adapter => Adapters::SomeAdapter) }
|
55
|
+
|
56
|
+
it 'outputs expected message' do
|
57
|
+
Runner.any_instance.stub(:get_env => nil)
|
58
|
+
subject.set_source
|
59
|
+
output.content.should include('Please choose source db:')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Dbmanager
|
4
|
+
describe YmlParser do
|
5
|
+
before do
|
6
|
+
stub_rails_root
|
7
|
+
YmlParser.config = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#config' do
|
11
|
+
it 'loads a yml file with erb code inside' do
|
12
|
+
YmlParser.config.should be_a(Hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'caches the result' do
|
16
|
+
YmlParser.stub :override_config => {}
|
17
|
+
YmlParser.should_receive(:yml_load).once.and_return({:some => :conf})
|
18
|
+
YmlParser.config
|
19
|
+
YmlParser.config
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#reload_config' do
|
24
|
+
it 'reloads the yml file' do
|
25
|
+
YmlParser.stub :override_config => {}
|
26
|
+
YmlParser.should_receive(:yml_load).twice.and_return({:some => :conf})
|
27
|
+
YmlParser.config
|
28
|
+
YmlParser.reload_config
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#environments' do
|
33
|
+
it 'is an hash of environments' do
|
34
|
+
YmlParser.environments.should be_a(Hash)
|
35
|
+
YmlParser.environments.values.should be_all do |item|
|
36
|
+
item.is_a?(Environment)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when there is a dbmanager_override file' do
|
42
|
+
it 'overrides regular settings' do
|
43
|
+
YmlParser.config['beta']['host'].should == '345.345.345.345'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'removes old unchanged settings' do
|
47
|
+
YmlParser.config['beta']['username'].should == 'beta_username'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../../lib/dbmanager', __FILE__)
|
2
|
+
require 'support/std_stub'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.color_enabled = true
|
6
|
+
config.formatter = 'documentation'
|
7
|
+
end
|
8
|
+
|
9
|
+
def fixture_path
|
10
|
+
File.expand_path('../fixtures', __FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
def stub_rails_root
|
14
|
+
Dbmanager.stub! :rails_root => fixture_path
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dbmanager
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 0.0.2.alpha
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- andrea longhi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-03-31 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
description: helps manage db dumps and imports via rake tasks
|
49
|
+
email:
|
50
|
+
- andrea.longhi@mikamai.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- CHANGELOG.md
|
60
|
+
- Gemfile
|
61
|
+
- LICENSE
|
62
|
+
- README.md
|
63
|
+
- Rakefile
|
64
|
+
- dbmanager.gemspec
|
65
|
+
- lib/dbmanager.rb
|
66
|
+
- lib/dbmanager/adapters/mysql.rb
|
67
|
+
- lib/dbmanager/dumper.rb
|
68
|
+
- lib/dbmanager/importer.rb
|
69
|
+
- lib/dbmanager/runner.rb
|
70
|
+
- lib/dbmanager/version.rb
|
71
|
+
- lib/dbmanager/yml_parser.rb
|
72
|
+
- lib/tasks/dbmanager.rake
|
73
|
+
- rails_generators/dbmanager/USAGE
|
74
|
+
- rails_generators/dbmanager/dbmanager_generator.rb
|
75
|
+
- spec/fixtures/adapter_sample.rb
|
76
|
+
- spec/fixtures/config/database.yml
|
77
|
+
- spec/fixtures/config/dbmanager_override.yml
|
78
|
+
- spec/lib/adapters/mysql_spec.rb
|
79
|
+
- spec/lib/dbmanager_spec.rb
|
80
|
+
- spec/lib/dumper_spec.rb
|
81
|
+
- spec/lib/importer_spec.rb
|
82
|
+
- spec/lib/runner_spec.rb
|
83
|
+
- spec/lib/yml_parser_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
- spec/support/std_stub.rb
|
86
|
+
homepage: ""
|
87
|
+
licenses: []
|
88
|
+
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">"
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 1.3.1
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project: dbmanager
|
109
|
+
rubygems_version: 1.8.15
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: database manager
|
113
|
+
test_files:
|
114
|
+
- spec/fixtures/adapter_sample.rb
|
115
|
+
- spec/fixtures/config/database.yml
|
116
|
+
- spec/fixtures/config/dbmanager_override.yml
|
117
|
+
- spec/lib/adapters/mysql_spec.rb
|
118
|
+
- spec/lib/dbmanager_spec.rb
|
119
|
+
- spec/lib/dumper_spec.rb
|
120
|
+
- spec/lib/importer_spec.rb
|
121
|
+
- spec/lib/runner_spec.rb
|
122
|
+
- spec/lib/yml_parser_spec.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
- spec/support/std_stub.rb
|
125
|
+
has_rdoc:
|