dbget_client 0.1.4 → 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/bin/dbget CHANGED
@@ -3,4 +3,4 @@
3
3
  DBGET_LIB_PATH = File.join(File.dirname(__FILE__), '../lib')
4
4
  require File.join(DBGET_LIB_PATH, 'dbget')
5
5
 
6
- DBGet::Runner.boot(ARGV, 'mysql')
6
+ DBGet::Runner.new.run!(ARGV, 'mysql')
@@ -3,4 +3,4 @@
3
3
  DBGET_LIB_PATH = File.join(File.dirname(__FILE__), '../lib')
4
4
  require File.join(DBGET_LIB_PATH, 'dbget')
5
5
 
6
- DBGet::Runner.boot(ARGV, 'mongo')
6
+ DBGet::Runner.new.run!(ARGV, 'mongo')
@@ -1,17 +1,15 @@
1
1
  require 'fileutils'
2
2
  require 'yaml'
3
- require 'zlib'
4
3
  require 'optparse'
5
4
 
6
5
  DBGET_LIB_ROOT = File.expand_path('../dbget', __FILE__)
7
6
  require File.join(DBGET_LIB_ROOT, 'version')
8
7
 
9
8
  module DBGet
10
- autoload :Initializer, File.join(DBGET_LIB_ROOT, 'initializer')
11
- autoload :DBDump, File.join(DBGET_LIB_ROOT, 'db_dump')
12
- autoload :Loaders, File.join(DBGET_LIB_ROOT, 'loaders')
9
+ autoload :Config, File.join(DBGET_LIB_ROOT, 'config')
10
+ autoload :Connector, File.join(DBGET_LIB_ROOT, 'connector')
13
11
  autoload :Constants, File.join(DBGET_LIB_ROOT, 'constants')
14
- autoload :ConfigLoader, File.join(DBGET_LIB_ROOT, 'config_loader')
12
+ autoload :Controller, File.join(DBGET_LIB_ROOT, 'controller')
15
13
  autoload :Runner, File.join(DBGET_LIB_ROOT, 'runner')
16
14
  autoload :Utils, File.join(DBGET_LIB_ROOT, 'utils')
17
15
  end
@@ -0,0 +1,14 @@
1
+ require 'singleton'
2
+
3
+ module DBGet
4
+ class Config < Hash
5
+ include Singleton
6
+
7
+ def self.load_from_yaml(yaml_path)
8
+ config = self.instance
9
+ config.clear
10
+ config.merge!(YAML.load_file(yaml_path))
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,57 @@
1
+ require 'net/ssh'
2
+
3
+ module DBGet
4
+ class Connector
5
+ include Utils
6
+ include Constants
7
+
8
+ attr_accessor :collections
9
+ attr_reader :db, :db_path
10
+ attr_reader :clean, :verbose
11
+
12
+ def initialize(database, config, options)
13
+ @db = database
14
+ @options = Utils.stringify(options)
15
+ @config = config.merge!(@options)
16
+ @login = @config['login']
17
+ @db_type = @options['db_type']
18
+ @server = @config['server']
19
+ @date = @config['date']
20
+ @clean = @config['clean']
21
+ @verbose = @config['verbose']
22
+ @collections = @config['collections']
23
+ @custom_name = @config['name']
24
+ @append_date = @config['append_date']
25
+ @ssh_params = init_ssh_params
26
+ end
27
+
28
+ def send_data!
29
+ user, host = @config['login'].split('@')
30
+
31
+ Net::SSH.start(host, user) do |ssh|
32
+
33
+ channel = ssh.open_channel do |ch|
34
+ ch.exec(@ssh_params) do |ch, success|
35
+ raise "SSH connection failure." unless success
36
+
37
+ ch.on_data do |c,data|
38
+ $stdout.puts data
39
+ end
40
+
41
+ ch.on_extended_data do |c, type, data|
42
+ $stderr.print data
43
+ end
44
+
45
+ end
46
+ channel.wait
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ def init_ssh_params
53
+ "%s db=%s db_type=%s server=%s date=%s clean=%s verbose=%s collections=%s custom_name=%s append_date=%s" %
54
+ [@login, @db, @db_type, @server, @date, @clean, @verbose, @collections, @custom_name, @append_date]
55
+ end
56
+ end
57
+ end
@@ -1,6 +1,5 @@
1
1
  module DBGet
2
2
  module Constants
3
3
  DBGET_CONFIG_FILE = 'dbget.yml'
4
- MONGO_FILE_EXT = '.bson'
5
4
  end
6
5
  end
@@ -0,0 +1,43 @@
1
+ module DBGet
2
+ class Controller
3
+ include Constants
4
+
5
+ attr_reader :connector, :config, :databases, :options
6
+
7
+ def initialize(databases, options)
8
+ @databases = databases
9
+ @options = options
10
+ @connections = []
11
+ end
12
+
13
+ def boot
14
+ load_dbget_config
15
+ @config = DBGet::Config.instance
16
+ store_connections
17
+ end
18
+
19
+ def store_connections
20
+ @databases.each do |database|
21
+ @connections << Connector.new(database, @config, @options)
22
+ end
23
+ end
24
+
25
+ def send_data!
26
+ @connections.each do |connection|
27
+ connection.send_data!
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def load_dbget_config
34
+ config_path = File.join(@options[:dbget_path], DBGET_CONFIG_FILE)
35
+
36
+ if File.exists?(config_path)
37
+ DBGet::Config.load_from_yaml(config_path)
38
+ else
39
+ raise "Cannot find #{config_path}!"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,58 +1,47 @@
1
1
  module DBGet
2
2
  class Runner
3
- def self.boot(args, dbtype)
4
- DBGet::Constants.const_set("MYSQL_CMD", `which mysql 2>/dev/null`.strip)
5
- DBGet::Constants.const_set("SSH_CMD", `which ssh 2>/dev/null`.strip)
6
- DBGet::Constants.const_set("MONGORESTORE_CMD", `which mongorestore 2>/dev/null`.strip)
7
- DBGet::Constants.const_set("FIND_CMD", `which find 2>/dev/null`.strip)
8
- DBGet::Constants.const_set("TAR_CMD", `which tar 2>/dev/null`.strip)
9
-
10
- self.new(args, dbtype)
3
+ def initialize
4
+ @options = {}
5
+ set_default_options
6
+ @optparse = init_option_parser
7
+ @args = nil
11
8
  end
12
9
 
13
- def initialize(args, dbtype)
14
- options = {}
15
- options[:append_date] = false
16
- options[:verbose] = false
17
-
10
+ def init_option_parser
18
11
  optparse = OptionParser.new do |opts|
19
12
  opts.banner = "Usage: dbget [options] db1 db2 ...\n"
20
13
  opts.separator "Options:"
21
14
 
22
15
  opts.on('-d', '--date DATE', 'Date of database dump (yyyy-mm-dd).') do |date|
23
- options[:date] = date
16
+ @options[:date] = date
24
17
  end
25
18
 
26
19
  opts.on('-c', '--clean', 'Drops the database before dumping') do
27
- options[:clean] = true
28
- end
29
-
30
- opts.on('-f', '--force', 'Force the use of dbget in production.') do
31
- options[:force] = true
20
+ @options[:clean] = true
32
21
  end
33
22
 
34
- opts.on('-n', '--name NAME', 'Explicitly declare a database name for dumping.') do |name|
35
- options[:opt_db_name] = name
36
- end
37
-
38
- opts.on('-i', '--key KEY', 'Specify ssh connection key') do |key|
39
- options[:key] = key
23
+ opts.on('-k', '--key KEY', 'Specify ssh connection key') do |key|
24
+ @options[:key] = key
40
25
  end
41
26
 
42
27
  opts.on('-s', '--server SERVER', 'Specify the server that contained the database.') do |server|
43
- options[:server] = server
28
+ @options[:server] = server
44
29
  end
45
30
 
46
31
  opts.on('-a', '--append-date', 'Append the given date as suffix') do
47
- options[:append_date] = true
32
+ @options[:append_date] = true
48
33
  end
49
34
 
50
- opts.on('--collections COLLECTION', Array, 'Only dump specific mongodb collections separated by comma') do |collection|
51
- options[:collections] = collection
35
+ opts.on('--collections COLLECTION', 'Only dump specific mongodb collections separated by comma') do |collection|
36
+ @options[:collections] = collection
37
+ end
38
+
39
+ opts.on('--n', '--name NAME', 'Specify a custom name/key for databases') do |name|
40
+ @options[:name] = name
52
41
  end
53
42
 
54
43
  opts.on('-v', '--verbose', 'Execute NERD mode!') do
55
- options[:verbose] = true
44
+ @options[:verbose] = true
56
45
  end
57
46
 
58
47
  opts.on('-V', '--version', 'Version') do
@@ -66,37 +55,47 @@ module DBGet
66
55
  end
67
56
  end
68
57
 
69
- optparse.parse!
58
+ optparse
59
+ end
70
60
 
71
- if args.length == 0
72
- puts optparse.help
73
- else
74
- options[:dbtype] = dbtype
75
- options[:databases] = args.dup
61
+ def set_default_options
62
+ @options[:append_date] = false
63
+ @options[:verbose] = false
64
+ @options[:clean] = false
65
+ @options[:date] = 'xxxx-xx-xx'
66
+ @options[:collections] = 'EMPTY'
67
+ end
68
+
69
+ def run!(args, type)
70
+ check_path
71
+ @args = args
72
+ has_arguments?
76
73
 
77
- run(options)
74
+ @optparse.parse!
75
+ @options[:db_type] = type
76
+
77
+ controller
78
+ end
79
+
80
+ def controller
81
+ controller = DBGet::Controller.new(@args, @options)
82
+ controller.boot
83
+ controller.send_data!
84
+ end
85
+
86
+ def has_arguments?
87
+ if @args.length == 0
88
+ puts @optparse.help
89
+ exit
78
90
  end
79
91
  end
80
92
 
81
- def run(opts)
93
+ def check_path
82
94
  if ENV.include?('DBGET_PATH')
83
- opts[:dbget_path] = ENV['DBGET_PATH']
95
+ @options[:dbget_path] = ENV['DBGET_PATH']
84
96
  else
85
97
  raise "Cannot find DBGET_PATH!"
86
98
  end
87
-
88
- # lets turn off opt_db_name if we have more arguments
89
- # this feature is not supported at the moment
90
- if opts[:databases].count > 1 and opts.include?(:opt_db_name)
91
- raise "You cannot use -n with multiple databases!"
92
- end
93
-
94
- # check if -a switch is give but no -d
95
- if opts[:append_date] and !opts.include?(:date)
96
- raise "You cannnot use -a without -d!"
97
- end
98
-
99
- DBGet::Initializer.boot(opts)
100
99
  end
101
100
  end
102
101
  end
@@ -19,5 +19,12 @@ module DBGet
19
19
  chars = ('a'..'z').to_a + ('A'..'Z').to_a
20
20
  (0...size).collect { chars[Kernel.rand(chars.length)] }.join
21
21
  end
22
+
23
+ def self.stringify(hash)
24
+ hash.inject({}) do |options, (key, value)|
25
+ options[key.to_s] = value.to_s
26
+ options
27
+ end
28
+ end
22
29
  end
23
30
  end
@@ -1,3 +1,3 @@
1
1
  module DBGet
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbget_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.2
5
5
  prerelease:
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-02-20 00:00:00.000000000Z
12
+ date: 2012-08-27 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: Decrypts and uncompress MySQL and MongoDB backups from dbget server
15
15
  email:
@@ -28,13 +28,10 @@ files:
28
28
  - bin/mongoget
29
29
  - dbget_client.gemspec
30
30
  - lib/dbget.rb
31
- - lib/dbget/config_loader.rb
31
+ - lib/dbget/config.rb
32
+ - lib/dbget/connector.rb
32
33
  - lib/dbget/constants.rb
33
- - lib/dbget/db_dump.rb
34
- - lib/dbget/initializer.rb
35
- - lib/dbget/loaders.rb
36
- - lib/dbget/loaders/mongodb.rb
37
- - lib/dbget/loaders/mysql.rb
34
+ - lib/dbget/controller.rb
38
35
  - lib/dbget/runner.rb
39
36
  - lib/dbget/utils.rb
40
37
  - lib/dbget/version.rb
@@ -1,19 +0,0 @@
1
- module DBGet
2
- class ConfigLoader
3
-
4
- def initialize(dbget_config, options = {})
5
- @dbget_config = dbget_config
6
- @options = options
7
- end
8
-
9
- def get_config(db_dump)
10
- @db_dump = db_dump
11
-
12
- if @dbget_config['mapping'].include?(db_dump.db)
13
- @dbget_config
14
- else
15
- raise "#{db_dump.db} is not found in your dbget.yml!"
16
- end
17
- end
18
- end
19
- end
@@ -1,124 +0,0 @@
1
- module DBGet
2
- class DBDump
3
- include Utils
4
- include Constants
5
-
6
- attr_accessor :dump_path, :collections
7
- attr_reader :db, :database, :db_path
8
- attr_reader :host, :port, :username, :password
9
- attr_reader :clean, :verbose
10
-
11
- def initialize(options)
12
- @db = options[:db]
13
- @date = options[:date]
14
- @key = options[:key]
15
- @dbtype = options[:dbtype]
16
- @server = options[:server]
17
- @opt_db_name = options[:opt_db_name]
18
- @verbose = options[:verbose]
19
- @append_date = options[:append_date]
20
- @clean = options[:clean]
21
- @collections = options[:collections] || []
22
- @header = {}
23
- end
24
-
25
- def load!(db_config)
26
- @server ||= db_config['source']['server']
27
- @key ||= db_config['key']
28
- @database = @opt_db_name || db_config['mapping'][@db][@dbtype]
29
- @host = db_config['target'][@dbtype]['host']
30
- @port = db_config['target'][@dbtype]['port']
31
- @username = db_config['target'][@dbtype]['username']
32
- @password = db_config['target'][@dbtype]['password']
33
- @dump_path = db_config['source']['dump_path']
34
- @db_path = File.join(@dump_path, "#{@db}")
35
-
36
- if @append_date
37
- @database = @database.concat("_#{@date.delete('-')}")
38
- end
39
-
40
- get_dump(db_config)
41
-
42
- if @header[:status] == 'SUCCESS'
43
- if !@database.nil?
44
- Utils.say "Dump info of #{@db} to #{@dbtype} using connection: \n" +
45
- " host: #{@host}\n" +
46
- " port: #{@port}\n" +
47
- " user: #{@username}\n" +
48
- " database: #{@database}\n"
49
-
50
- if @dbtype == 'mysql'
51
- Loaders::MySQL.new(self).load!
52
- else
53
- Loaders::MongoDB.new(self).load!
54
- end
55
- else
56
- raise "Database #{@db} for #{@dbtype} is not found on #{DBGET_CONFIG_FILE}!"
57
- end
58
- else
59
- raise "There was a problem fetching the database from the server!"
60
- end
61
- end
62
-
63
- protected
64
-
65
- def get_dump(db_config)
66
- user = db_config['source']['user']
67
- host = db_config['source']['host']
68
-
69
- unless File.exist? @dump_path
70
- FileUtils.mkdir_p(@dump_path)
71
- end
72
-
73
- ssh_params = "#{user}@#{host} db=#{@db} date=#{@date} " +
74
- "dbtype=#{@dbtype} server=#{@server}"
75
-
76
- if !@key.nil?
77
- ssh_cmd = "#{SSH_CMD} -i #{@key} #{ssh_params}"
78
- else
79
- ssh_cmd = "#{SSH_CMD} #{ssh_params}"
80
- end
81
-
82
- Utils.say "Fetching..."
83
-
84
- io_handle = IO.popen(ssh_cmd)
85
-
86
- parse_header(io_handle)
87
-
88
- if !io_handle.eof?
89
- File.open(@db_path, "w+") do |f|
90
- gz = Zlib::GzipReader.new(io_handle)
91
-
92
- while !io_handle.eof?
93
- g = gz.read(16*1024)
94
- f.write(g)
95
- end
96
-
97
- f.write(gz.read)
98
-
99
- gz.close
100
- f.close
101
- end
102
- end
103
- end
104
-
105
- def parse_header(io_handle)
106
- while (s = io_handle.readline) != "\r\n"
107
- s = s.split(': ')
108
- @header[s.first.to_sym] = s.last.chomp
109
- end
110
-
111
- print_header if @verbose
112
-
113
- if @header[:status] != "SUCCESS"
114
- raise "Server returned #{@header[:status]}!"
115
- end
116
- end
117
-
118
- def print_header
119
- @header.each do |k, v|
120
- puts ">> #{k.capitalize}: #{v}"
121
- end
122
- end
123
- end
124
- end
@@ -1,53 +0,0 @@
1
- module DBGet
2
- class Initializer
3
- include Constants
4
-
5
- def self.boot(options)
6
- self.new(options).init
7
- end
8
-
9
- def initialize(options)
10
- @options = options
11
- end
12
-
13
- def init
14
- load_dbget_config
15
-
16
- @options[:databases].each do |d|
17
- @options[:db] = d
18
-
19
- db_dump = DBGet::DBDump.new(@options)
20
-
21
- load_db_dumps(db_dump)
22
- end
23
- end
24
-
25
- protected
26
-
27
- def load_dbget_config
28
- config_path = File.join(@options[:dbget_path], DBGET_CONFIG_FILE)
29
-
30
- if File.exists?(config_path)
31
- @dbget_config = YAML.load_file(config_path)
32
- else
33
- raise "Cannot find #{config_path}!"
34
- end
35
- end
36
-
37
- def load_db_dumps(db_dump)
38
- if !@dbget_config.empty?
39
- config_loader = DBGet::ConfigLoader.new(@dbget_config, @options)
40
- else
41
- raise "Your dbget.yml is empty!"
42
- end
43
-
44
- db_dump.load!(config_loader.get_config(db_dump))
45
- end
46
-
47
- def cleanup_db_dumps(db_dumps)
48
- db_dumps.each do |db_dump|
49
- db_dump.clean_up!
50
- end
51
- end
52
- end
53
- end
@@ -1,6 +0,0 @@
1
- module DBGet
2
- module Loaders
3
- autoload :MongoDB, File.join(DBGET_LIB_ROOT, 'loaders/mongodb')
4
- autoload :MySQL, File.join(DBGET_LIB_ROOT, 'loaders/mysql')
5
- end
6
- end
@@ -1,69 +0,0 @@
1
- module DBGet
2
- module Loaders
3
- class MongoDB
4
- include Utils
5
- include Constants
6
-
7
- def self.boot(dump)
8
- # some boot here
9
-
10
- self.new(dump)
11
- end
12
-
13
- def initialize(dump)
14
- @dump = dump
15
- end
16
-
17
- def load!
18
- temp_path = File.join(@dump.dump_path, "#{@dump.db}_#{Utils.randomize(16)}")
19
-
20
- if !File.exists?(temp_path)
21
- FileUtils.mkdir(temp_path)
22
-
23
- Utils.say_with_time "Extracting archive..." do
24
- `#{TAR_CMD} -C #{temp_path} -xf #{File.join(@dump.dump_path, @dump.db)} 2> /dev/null`
25
- end
26
-
27
- Utils.say_with_time "Moving mongo files..." do
28
- `#{FIND_CMD} #{temp_path} -name '*.#{MONGO_FILE_EXT}'`.each_line do |l|
29
- FileUtils.mv(l.chomp!, File.join(temp_path, File.basename(l)))
30
- end
31
- end
32
- end
33
-
34
- dump_files = Dir["#{temp_path}/*#{MONGO_FILE_EXT}"]
35
-
36
- if !@dump.collections.empty?
37
- @dump.collections = @dump.collections.collect do |c|
38
- File.join(temp_path, c.concat(MONGO_FILE_EXT))
39
- end
40
-
41
- dump_files &= @dump.collections
42
- end
43
-
44
- dump_files.each do |d|
45
- # do not include indexes
46
- if File.basename(d) != "system.indexes#{MONGO_FILE_EXT}"
47
- Utils.say_with_time "Dumping #{d}..." do
48
- if !@dump.verbose
49
- `#{MONGORESTORE_CMD} -d #{@dump.database} #{d} --drop`
50
- else
51
- system "#{MONGORESTORE_CMD} -d #{@dump.database} #{d} --drop"
52
- end
53
- end
54
- end
55
- end
56
-
57
- Utils.say "Hooray! Dump for #{@dump.db} done!"
58
-
59
- if FileUtils.rm_rf(File.join(@dump.dump_path, @dump.db))
60
- Utils.say "Dump file removed!"
61
- end
62
-
63
- if FileUtils.rm_rf(temp_path)
64
- Utils.say "Temp directory removed!"
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,50 +0,0 @@
1
- module DBGet
2
- module Loaders
3
- class MySQL
4
- include Utils
5
- include Constants
6
-
7
- def self.boot(dump)
8
- # some boot here
9
-
10
- self.new(dump)
11
- end
12
-
13
- def initialize(dump)
14
- @dump = dump
15
- end
16
-
17
- def load!
18
- command = "#{MYSQL_CMD} "
19
- command += "-h#{@dump.host} "
20
- command += "-P#{@dump.port} "
21
- command += "-u#{@dump.username} "
22
- command += "-p#{@dump.password} " if @dump.password
23
-
24
- if @dump.clean
25
- Utils.say_with_time "Dropping database..." do
26
- system "echo \"DROP DATABASE IF EXISTS #{@dump.database}\" | #{command}"
27
- end
28
- end
29
-
30
- system "echo \"CREATE DATABASE IF NOT EXISTS #{@dump.database}\" | #{command}"
31
-
32
- if File.exist?(@dump.db_path) and !File.size?(@dump.db_path).nil?
33
- command += " #{@dump.database} "
34
-
35
- Utils.say_with_time "Dumping #{@dump.db}..." do
36
- system "#{command}< #{File.join(@dump.dump_path, @dump.db)}"
37
- end
38
-
39
- if FileUtils.rm_rf(File.join(@dump.dump_path, @dump.db))
40
- Utils.say "Cleaned temporary file!"
41
- end
42
- else
43
- raise "Dump for #{@dump.db} not found!"
44
- end
45
-
46
- Utils.say "Hooray! Dump for #{@dump.db} done!"
47
- end
48
- end
49
- end
50
- end