dbget 0.2.2
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 +5 -0
- data/Gemfile +4 -0
- data/README +1 -0
- data/Rakefile +1 -0
- data/bin/dbget-adm +5 -0
- data/bin/dbget-serve +9 -0
- data/config/dbget.yml.sample +28 -0
- data/config/mask.yml +16 -0
- data/dbget.gemspec +26 -0
- data/lib/dbget/admin.rb +30 -0
- data/lib/dbget/binaries.rb +23 -0
- data/lib/dbget/config.rb +17 -0
- data/lib/dbget/constants.rb +7 -0
- data/lib/dbget/controller.rb +61 -0
- data/lib/dbget/dump.rb +150 -0
- data/lib/dbget/loaders/mongo.rb +77 -0
- data/lib/dbget/loaders/mysql.rb +55 -0
- data/lib/dbget/loaders.rb +6 -0
- data/lib/dbget/runner.rb +67 -0
- data/lib/dbget/utils.rb +65 -0
- data/lib/dbget/version.rb +3 -0
- data/lib/dbget.rb +26 -0
- metadata +80 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
initial commit for dbget
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/dbget-adm
ADDED
data/bin/dbget-serve
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
backups:
|
2
|
+
path: /opt/backups
|
3
|
+
cache: /tmp/dbget_backups
|
4
|
+
|
5
|
+
openssl:
|
6
|
+
passphrase: xxx
|
7
|
+
|
8
|
+
databases:
|
9
|
+
lmedi:
|
10
|
+
mongo: lmedi_production
|
11
|
+
clinic:
|
12
|
+
mysql: clinic_production
|
13
|
+
test:
|
14
|
+
mysql: test
|
15
|
+
|
16
|
+
users: ['poy', 'jan']
|
17
|
+
|
18
|
+
mysql:
|
19
|
+
host: localhost
|
20
|
+
port: 3306
|
21
|
+
username: root
|
22
|
+
password:
|
23
|
+
|
24
|
+
mongo:
|
25
|
+
host: localhost
|
26
|
+
port: 27017
|
27
|
+
username: root
|
28
|
+
password:
|
data/config/mask.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
people:
|
2
|
+
columns:
|
3
|
+
email: 'masked@caresharing.eu'
|
4
|
+
house_number: '01'
|
5
|
+
postal_code: '1234XX'
|
6
|
+
mobile_number: '123-4567'
|
7
|
+
phone_number: '123-4567'
|
8
|
+
firstname:
|
9
|
+
lastname:
|
10
|
+
street_name:
|
11
|
+
region:
|
12
|
+
birthplace:
|
13
|
+
city:
|
14
|
+
patient_list_displays:
|
15
|
+
columns:
|
16
|
+
name:
|
data/dbget.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'dbget/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dbget"
|
7
|
+
s.version = DBGet::VERSION
|
8
|
+
s.authors = ["Jan Mendoza"]
|
9
|
+
s.email = ["poymode@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Get an encrypted and compressed backup of a MySQL or mongoDB}
|
12
|
+
s.description = %q{This serves the backup}
|
13
|
+
|
14
|
+
s.rubyforge_project = "dbget"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'thor'
|
22
|
+
|
23
|
+
# specify any dependencies here; for example:
|
24
|
+
# s.add_development_dependency "rspec"
|
25
|
+
# s.add_runtime_dependency "rest-client"
|
26
|
+
end
|
data/lib/dbget/admin.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module DBGet
|
4
|
+
class Admin < Thor
|
5
|
+
desc "generate_authorized_keys", "generate authorized keys for access"
|
6
|
+
def generate_authorized_keys
|
7
|
+
if File.exist? File.join(Dir.pwd, 'keydir')
|
8
|
+
key_dir = File.join(Dir.pwd, 'keydir')
|
9
|
+
elsif ENV.include?('DBGET_KEYDIR_PATH')
|
10
|
+
key_dir = ENV['DBGET_KEYDIR_PATH']
|
11
|
+
else
|
12
|
+
key_dir = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
raise "Key directory 'keydir' not found." unless File.exists?(key_dir) and File.directory?(key_dir)
|
16
|
+
|
17
|
+
puts "### Generated by dbget, DO NOT EDIT"
|
18
|
+
|
19
|
+
keys = Dir["#{key_dir}/*.pub"]
|
20
|
+
keys.each do |pub_key|
|
21
|
+
bin_path = 'dbget-serve'
|
22
|
+
key_name = File.basename(pub_key, '.pub')
|
23
|
+
key_data = File.read(pub_key)
|
24
|
+
|
25
|
+
puts "command=\"#{bin_path} #{key_name}\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #{key_data}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DBGet
|
2
|
+
module Binaries
|
3
|
+
def self.get_binary(bin)
|
4
|
+
`which #{bin}`.chomp
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.mysql_cmd
|
8
|
+
get_binary('mysql')
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mongorestore_cmd
|
12
|
+
get_binary('mongorestore')
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_cmd
|
16
|
+
get_binary('find')
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.tar_cmd
|
20
|
+
get_binary('tar')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/dbget/config.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module DBGet
|
4
|
+
class Config < Hash
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def self.load_from_yml(yaml_path)
|
8
|
+
config = self.instance
|
9
|
+
config.clear
|
10
|
+
config.merge!(YAML.load_file(yaml_path))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.database(name)
|
14
|
+
self.instance['databases'][name]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DBGet
|
2
|
+
class Controller
|
3
|
+
def self.boot(options)
|
4
|
+
self.new(options).run!
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@dump = DBGet::Dump.new(options)
|
9
|
+
@config = DBGet::Config.instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def run!
|
13
|
+
user_allowed?
|
14
|
+
@dump.prepare
|
15
|
+
finalize_dump
|
16
|
+
load_dump
|
17
|
+
status_report
|
18
|
+
end
|
19
|
+
|
20
|
+
def user_allowed?
|
21
|
+
unless @config['users'].include?(@dump.user)
|
22
|
+
raise "User not allowed to dump"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def finalize_dump
|
28
|
+
if @dump.in_cache? @dump.cache_file
|
29
|
+
message = "Found cached file, no need to decrypt."
|
30
|
+
else
|
31
|
+
message = "Decrypting #{@dump.encrypted_dump}..."
|
32
|
+
end
|
33
|
+
|
34
|
+
Utils.say_with_time message do
|
35
|
+
@dump.decrypted_dump = @dump.decrypt_dump
|
36
|
+
end
|
37
|
+
|
38
|
+
@dump.set_final_db
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_dump
|
42
|
+
Utils.say_with_time "Dumping, this may take a while" do
|
43
|
+
case @dump.db_type
|
44
|
+
when 'mysql'
|
45
|
+
DBGet::Loaders::MySql.boot(@dump, @config).load!
|
46
|
+
when 'mongo'
|
47
|
+
DBGet::Loaders::Mongo.boot(@dump, @config).load!
|
48
|
+
else
|
49
|
+
raise "Dump is not supported!"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def status_report
|
56
|
+
Utils.say "Dump for #{@dump.db} done!"
|
57
|
+
Utils.say "Source: #{@dump.decrypted_dump}"
|
58
|
+
Utils.say "Target: #{@dump.target_db}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/dbget/dump.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module DBGet
|
4
|
+
class Dump
|
5
|
+
include Constants
|
6
|
+
include Utils
|
7
|
+
|
8
|
+
attr_reader :db_type, :user, :db
|
9
|
+
attr_reader :encrypted_dump
|
10
|
+
attr_reader :date, :clean, :verbose, :append_date
|
11
|
+
attr_accessor :backup_name, :collections, :target_db, :decrypted_dump
|
12
|
+
|
13
|
+
def initialize(opts)
|
14
|
+
@db = opts['db']
|
15
|
+
@db_type = opts['db_type']
|
16
|
+
@user = opts['user']
|
17
|
+
@server = opts['server']
|
18
|
+
@custom_name = opts['custom_name']
|
19
|
+
|
20
|
+
@collections = opts['collections']
|
21
|
+
@date = opts['date']
|
22
|
+
@clean = opts['clean']
|
23
|
+
@verbose = opts['verbose']
|
24
|
+
@append_date = opts['append_date']
|
25
|
+
|
26
|
+
@storage_path = File.join(DBGet.base_backups_path, @server, @db_type)
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare
|
30
|
+
@backup_name = get_backup_name
|
31
|
+
@encrypted_dump = get_encrypted_dump
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_final_db
|
35
|
+
@target_db = @custom_name || @backup_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def form_db_name
|
39
|
+
if !date.nil? and append_date
|
40
|
+
self.target_db = "#{self.user}_#{self.target_db}_#{Utils.get_converted_date(self.date)}"
|
41
|
+
else
|
42
|
+
self.target_db = "#{self.user}_#{self.target_db}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def clean?
|
47
|
+
@clean
|
48
|
+
end
|
49
|
+
|
50
|
+
def decrypt_dump
|
51
|
+
unless @encrypted_dump.nil?
|
52
|
+
if in_cache? cache_file
|
53
|
+
file_path = cache_file
|
54
|
+
elsif File.exists? @encrypted_dump
|
55
|
+
file_path = Utils.decompress_file(decrypt_file(copy_to_cache(@encrypted_dump)))
|
56
|
+
end
|
57
|
+
|
58
|
+
file_path
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def in_cache?(file)
|
63
|
+
File.exists? file
|
64
|
+
end
|
65
|
+
|
66
|
+
def cache_file
|
67
|
+
file = File.join(DBGet.cache_path, decrypted_file_name)
|
68
|
+
file.concat('.tar') if @db_type.eql? 'mongo'
|
69
|
+
|
70
|
+
file
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def latest?
|
76
|
+
@date.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def decrypted_file_name
|
80
|
+
File.basename(@encrypted_dump.split('.').first)
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_backup_name
|
84
|
+
if !@db.nil? and !@db_type.nil?
|
85
|
+
db = DBGet::Config.database(@db)
|
86
|
+
|
87
|
+
if db.nil?
|
88
|
+
raise "Database \'#{@db}\' not found in config!"
|
89
|
+
end
|
90
|
+
|
91
|
+
db[@db_type]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_encrypted_dump
|
96
|
+
monthly_dir_path = File.join(@storage_path, @backup_name)
|
97
|
+
|
98
|
+
unless File.exist?(monthly_dir_path)
|
99
|
+
raise "Database \'#{@backup_name}\' can't be found in #{@storage_path}!"
|
100
|
+
end
|
101
|
+
|
102
|
+
monthly_dirs = Utils.get_files(monthly_dir_path).sort
|
103
|
+
|
104
|
+
if !monthly_dirs.empty?
|
105
|
+
db_month = get_db_month(monthly_dirs)
|
106
|
+
db_dumps_path = File.join(monthly_dir_path.to_s, db_month.to_s)
|
107
|
+
db_dumps = Utils.get_files(db_dumps_path)
|
108
|
+
|
109
|
+
@encrypted_dump = File.join(db_dumps_path, get_db_file(db_dumps))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_db_month(monthly_dirs)
|
114
|
+
if latest?
|
115
|
+
File.basename(monthly_dirs.last)
|
116
|
+
else
|
117
|
+
@date.strftime("%Y%m")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_db_file(db_dumps)
|
122
|
+
if latest?
|
123
|
+
db_file = db_dumps.last
|
124
|
+
else
|
125
|
+
db_dumps.each do |filename|
|
126
|
+
if filename.include? "-#{@date.strftime("%Y%m%d")}"
|
127
|
+
db_file = filename
|
128
|
+
break
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
db_file
|
134
|
+
end
|
135
|
+
|
136
|
+
def copy_to_cache(file_path)
|
137
|
+
FileUtils.mkdir_p(DBGet.cache_path)
|
138
|
+
FileUtils.cp(file_path, DBGet.cache_path)
|
139
|
+
|
140
|
+
File.join(DBGet.cache_path, File.basename(file_path))
|
141
|
+
end
|
142
|
+
|
143
|
+
def decrypt_file(file_path)
|
144
|
+
if File.extname(file_path) == ".enc"
|
145
|
+
Utils.decode_file(file_path)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module DBGet
|
2
|
+
module Loaders
|
3
|
+
class Mongo
|
4
|
+
include Constants
|
5
|
+
|
6
|
+
def self.boot(dump, config)
|
7
|
+
self.new(dump, config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(dump, config)
|
11
|
+
@dump = dump
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def load!
|
16
|
+
temp_path = get_temp_path
|
17
|
+
|
18
|
+
FileUtils.mkdir(temp_path) if !File.exists?(temp_path)
|
19
|
+
|
20
|
+
@dump.form_db_name
|
21
|
+
extract_mongo_dump(temp_path)
|
22
|
+
prepare_bson_files(temp_path)
|
23
|
+
|
24
|
+
dump_files = Dir["#{temp_path}/*#{MONGO_FILE_EXT}"]
|
25
|
+
dump_files = specify_collections(dump_files, temp_path)
|
26
|
+
mongo_restore(dump_files)
|
27
|
+
remove_temp_path(temp_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def mongo_restore(dump_files)
|
31
|
+
dump_files.each do |file|
|
32
|
+
unless index?(file)
|
33
|
+
mongo_restore = Binaries.mongorestore_cmd
|
34
|
+
|
35
|
+
system "#{mongo_restore} -d #{@dump.target_db} #{file} --drop"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_temp_path
|
41
|
+
random = Utils.randomize(16)
|
42
|
+
decrypted_basename = File.basename(@dump.decrypted_dump, '.tar')
|
43
|
+
temp_path = File.join(DBGet.cache_path, "#{decrypted_basename}_#{random}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_temp_path(path)
|
47
|
+
FileUtils.rm_rf(path)
|
48
|
+
end
|
49
|
+
|
50
|
+
def index?(file)
|
51
|
+
File.basename(file) == "#{MONGO_INDEX_FILE}#{MONGO_FILE_EXT}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def specify_collections(dump_files, temp_path)
|
55
|
+
if !@dump.collections.empty?
|
56
|
+
@dump.collections = @dump.collections.collect do |c|
|
57
|
+
File.join(temp_path, c.concat(MONGO_FILE_EXT))
|
58
|
+
end
|
59
|
+
|
60
|
+
dump_files &= @dump.collections
|
61
|
+
end
|
62
|
+
|
63
|
+
dump_files
|
64
|
+
end
|
65
|
+
|
66
|
+
def extract_mongo_dump(temp_path)
|
67
|
+
`#{Binaries.tar_cmd} -C #{temp_path} -xf #{@dump.decrypted_dump} 2> /dev/null`
|
68
|
+
end
|
69
|
+
|
70
|
+
def prepare_bson_files(temp_path)
|
71
|
+
`#{Binaries.find_cmd} #{temp_path} -name '*#{MONGO_FILE_EXT}'`.each_line do |l|
|
72
|
+
FileUtils.mv(l.chomp!, File.join(temp_path, File.basename(l)))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module DBGet
|
2
|
+
module Loaders
|
3
|
+
class MySql
|
4
|
+
include Constants
|
5
|
+
include Binaries
|
6
|
+
|
7
|
+
def self.boot(dump, config)
|
8
|
+
self.new(dump, config)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(dump, config)
|
12
|
+
@dump = dump
|
13
|
+
@config = config
|
14
|
+
@date = @dump.date
|
15
|
+
@dump_command = form_dump_command
|
16
|
+
end
|
17
|
+
|
18
|
+
def load!
|
19
|
+
@dump.form_db_name
|
20
|
+
clean_dump if @dump.clean?
|
21
|
+
create_db_if_not_exist
|
22
|
+
dump_mysql
|
23
|
+
end
|
24
|
+
|
25
|
+
def form_dump_command
|
26
|
+
@dump_command = "#{Binaries.mysql_cmd} "
|
27
|
+
@dump_command += "-h#{@config['mysql']['host']} "
|
28
|
+
@dump_command += "-P#{@config['mysql']['port']} "
|
29
|
+
@dump_command += "-u#{@config['mysql']['username']} "
|
30
|
+
@dump_command += "-p#{@config['mysql']['password']} " if @config['mysql']['password']
|
31
|
+
@dump_command
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_converted_date
|
35
|
+
@dump.date.to_s.delete('-')
|
36
|
+
end
|
37
|
+
|
38
|
+
def clean_dump
|
39
|
+
puts "Dropping database..."
|
40
|
+
system "echo \"DROP DATABASE IF EXISTS #{@dump.target_db}\" | #{@dump_command}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_db_if_not_exist
|
44
|
+
system "echo \"CREATE DATABASE IF NOT EXISTS #{@dump.target_db}\" | #{@dump_command}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def dump_mysql
|
48
|
+
@dump_command += " #{@dump.target_db} "
|
49
|
+
|
50
|
+
out = system("#{@dump_command}< #{@dump.decrypted_dump}")
|
51
|
+
exit 1 unless out
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/dbget/runner.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module DBGet
|
2
|
+
class Runner
|
3
|
+
def self.boot(user, options)
|
4
|
+
self.new(parse_options(user, options)).run!
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.parse_options(user, options)
|
8
|
+
opts = {}
|
9
|
+
opts['user'] = user
|
10
|
+
|
11
|
+
options.each do |o|
|
12
|
+
k, v = o.split('=')
|
13
|
+
opts[k] = v
|
14
|
+
end
|
15
|
+
|
16
|
+
opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
def run!
|
24
|
+
init_config(get_dbget_path)
|
25
|
+
prepare_dump_options
|
26
|
+
dump
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare_dump_options
|
30
|
+
@options['collections'] = get_final_collection(@options['collections'])
|
31
|
+
@options['date'] = format_date(@options['date'])
|
32
|
+
@options['clean'] = Utils.to_bool(@options['clean'])
|
33
|
+
@options['verbose'] = Utils.to_bool(@options['verbose'])
|
34
|
+
@options['append_date'] = Utils.to_bool(@options['append_date'])
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_final_collection(collection)
|
38
|
+
unless collection == 'EMPTY'
|
39
|
+
collection.split(',')
|
40
|
+
else
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def format_date(date)
|
46
|
+
unless date == 'xxxx-xx-xx'
|
47
|
+
Date.strptime(date, "%Y-%m-%d")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump
|
52
|
+
Controller.boot(@options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_dbget_path
|
56
|
+
if ENV.include?('DBGET_PATH')
|
57
|
+
ENV['DBGET_PATH']
|
58
|
+
else
|
59
|
+
raise "DBGET_PATH not defined"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def init_config(dbget_path)
|
64
|
+
DBGet.read_config(dbget_path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/dbget/utils.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
module DBGet
|
5
|
+
module Utils
|
6
|
+
|
7
|
+
def self.get_files(path)
|
8
|
+
Dir.new(path).entries - %w{ . .. }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.decode_file(input_file)
|
12
|
+
output_file = input_file.sub(/\.enc$/, "")
|
13
|
+
pass_phrase = DBGet::Config.instance['openssl']['passphrase']
|
14
|
+
|
15
|
+
command = "openssl enc -d -aes-256-cbc -in #{input_file}"
|
16
|
+
command += " -pass pass:#{pass_phrase}"
|
17
|
+
command += " -out #{output_file}; rm #{input_file}"
|
18
|
+
system command
|
19
|
+
|
20
|
+
output_file
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.decompress_file(input_file)
|
24
|
+
command = "gzip -df #{input_file}"
|
25
|
+
system command
|
26
|
+
|
27
|
+
input_file.sub(/\.gz$/, "")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.compress_file(input_file)
|
31
|
+
command = "gzip #{input_file}"
|
32
|
+
system command
|
33
|
+
|
34
|
+
input_file.concat('.gz')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.say(message, subitem = false)
|
38
|
+
puts "#{subitem ? " ->" : "--"} #{message}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.say_with_time(message)
|
42
|
+
say(message)
|
43
|
+
result = nil
|
44
|
+
time = Benchmark.measure { result = yield }
|
45
|
+
say "%.4fs" % time.real, :subitem
|
46
|
+
say("#{result} rows", :subitem) if result.is_a?(Integer)
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.randomize(size)
|
51
|
+
chars = ('a'..'z').to_a + ('A'..'Z').to_a
|
52
|
+
(0...size).collect { chars[Kernel.rand(chars.length)] }.join
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.to_bool(string)
|
56
|
+
return true if string == true || string =~ (/(true|t|yes|y|1)$/i)
|
57
|
+
return false if string == false || string.empty? || string =~ (/(false|f|no|n|0)$/i)
|
58
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{string}\"")
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.get_converted_date(date)
|
62
|
+
date.to_s.delete('-')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/dbget.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module DBGet
|
4
|
+
autoload :Admin, File.join(File.dirname(__FILE__), 'dbget/admin')
|
5
|
+
autoload :Binaries, File.join(File.dirname(__FILE__), 'dbget/binaries')
|
6
|
+
autoload :Config, File.join(File.dirname(__FILE__), 'dbget/config')
|
7
|
+
autoload :Constants, File.join(File.dirname(__FILE__), 'dbget/constants')
|
8
|
+
autoload :Dump, File.join(File.dirname(__FILE__), 'dbget/dump')
|
9
|
+
autoload :Controller, File.join(File.dirname(__FILE__), 'dbget/controller')
|
10
|
+
autoload :Loaders, File.join(File.dirname(__FILE__), 'dbget/loaders')
|
11
|
+
autoload :Runner, File.join(File.dirname(__FILE__), 'dbget/runner')
|
12
|
+
autoload :Utils, File.join(File.dirname(__FILE__), 'dbget/utils')
|
13
|
+
|
14
|
+
def self.read_config(dbget_path)
|
15
|
+
config_file = File.join(dbget_path, Constants::CONFIG_PATH)
|
16
|
+
DBGet::Config.load_from_yml(config_file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.base_backups_path
|
20
|
+
DBGet::Config.instance['backups']['path']
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.cache_path
|
24
|
+
DBGet::Config.instance['backups']['cache']
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dbget
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jan Mendoza
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-27 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: &15915760 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *15915760
|
25
|
+
description: This serves the backup
|
26
|
+
email:
|
27
|
+
- poymode@gmail.com
|
28
|
+
executables:
|
29
|
+
- dbget-adm
|
30
|
+
- dbget-serve
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- bin/dbget-adm
|
39
|
+
- bin/dbget-serve
|
40
|
+
- config/dbget.yml.sample
|
41
|
+
- config/mask.yml
|
42
|
+
- dbget.gemspec
|
43
|
+
- lib/dbget.rb
|
44
|
+
- lib/dbget/admin.rb
|
45
|
+
- lib/dbget/binaries.rb
|
46
|
+
- lib/dbget/config.rb
|
47
|
+
- lib/dbget/constants.rb
|
48
|
+
- lib/dbget/controller.rb
|
49
|
+
- lib/dbget/dump.rb
|
50
|
+
- lib/dbget/loaders.rb
|
51
|
+
- lib/dbget/loaders/mongo.rb
|
52
|
+
- lib/dbget/loaders/mysql.rb
|
53
|
+
- lib/dbget/runner.rb
|
54
|
+
- lib/dbget/utils.rb
|
55
|
+
- lib/dbget/version.rb
|
56
|
+
homepage: ''
|
57
|
+
licenses: []
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project: dbget
|
76
|
+
rubygems_version: 1.8.10
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Get an encrypted and compressed backup of a MySQL or mongoDB
|
80
|
+
test_files: []
|