dbmanager 0.0.2.alpha
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME].png)](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:
|