siba-source-mysql 0.0.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/Guardfile +9 -0
- data/LICENSE +22 -0
- data/README.md +23 -0
- data/Rakefile +28 -0
- data/lib/siba-source-mysql/db.rb +172 -0
- data/lib/siba-source-mysql/init.rb +62 -0
- data/lib/siba-source-mysql/options.yml +17 -0
- data/lib/siba-source-mysql/version.rb +9 -0
- data/lib/siba-source-mysql.rb +11 -0
- data/siba-source-mysql.gemspec +25 -0
- data/test/helper/require_integration.rb +5 -0
- data/test/helper/require_unit.rb +4 -0
- data/test/integration/i9n_init.rb +95 -0
- data/test/unit/test_db.rb +208 -0
- data/test/unit/test_init.rb +73 -0
- data/test/unit/yml/valid.yml +15 -0
- metadata +109 -0
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'minitest', :notify=>false do
|
5
|
+
watch(%r|^test/unit/(.*\/)*test_(.*)\.rb|)
|
6
|
+
watch(%r|^lib/siba-source-mysql/(.*\/)*([^/]+)\.rb|) do |m|
|
7
|
+
"test/unit/#{m[1]}test_#{m[2]}.rb" unless m[2][0] == '.'
|
8
|
+
end
|
9
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2012 Evgeny Neumerzhitskiy
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
This is a plugin for [SIBA backup and restore utility](https://github.com/evgenyneu/siba). It allows to back and restore MySQL database.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
$ gem install siba-source-mysql
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
1. Create a configuration file:
|
12
|
+
|
13
|
+
$ siba generate mybak
|
14
|
+
|
15
|
+
2. Backup:
|
16
|
+
|
17
|
+
$ siba backup mybak
|
18
|
+
|
19
|
+
3. Restore:
|
20
|
+
|
21
|
+
$ siba restore mybak
|
22
|
+
|
23
|
+
Run `siba` command without arguments to see the list of all available options.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
namespace "test" do
|
5
|
+
desc "Run all unit tests"
|
6
|
+
Rake::TestTask.new("unit") do |t|
|
7
|
+
t.pattern = "test/unit/**/test*.rb"
|
8
|
+
t.libs << 'test'
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Run all integration tests"
|
12
|
+
Rake::TestTask.new("integration") do |t|
|
13
|
+
t.pattern = "test/integration/**/i9n_*.rb"
|
14
|
+
t.libs << 'test'
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run all integration tests"
|
18
|
+
task :i9n => ["test:integration"] do
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Run all unit tests"
|
23
|
+
task :test => ["test:unit"] do
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Run tests"
|
27
|
+
task :default => "test:unit"
|
28
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Siba::Source
|
4
|
+
module Mysql
|
5
|
+
class Db
|
6
|
+
HIDE_PASSWORD_TEXT = "****p7d****"
|
7
|
+
BACKUP_FILE_NAME = "mysql_dump"
|
8
|
+
include Siba::FilePlug
|
9
|
+
include Siba::LoggerPlug
|
10
|
+
|
11
|
+
attr_accessor :options
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
|
16
|
+
if !tables.nil? && !tables.empty? &&
|
17
|
+
(databases.nil? || (!databases.nil? && databases.size != 1))
|
18
|
+
raise Siba::CheckError, "When 'tables' option is set there must be a single database specified in 'databases' option."
|
19
|
+
end
|
20
|
+
|
21
|
+
Siba::Source::Mysql::Db.check_spaces_in_arrays databases, 'databases'
|
22
|
+
Siba::Source::Mysql::Db.check_spaces_in_arrays tables, 'tables'
|
23
|
+
Siba::Source::Mysql::Db.check_spaces_in_arrays ignore_tables, 'ignore_tables'
|
24
|
+
|
25
|
+
check_installed
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def check_installed
|
30
|
+
msg = "utility is not found. Please make sure MySQL is installed and its bin directory is added to your PATH."
|
31
|
+
raise Siba::Error, "'mysqldump' #{msg}" unless siba_file.shell_ok? "mysqldump --help"
|
32
|
+
raise Siba::Error, "'mysql' #{msg}" unless siba_file.shell_ok? "mysql --help"
|
33
|
+
logger.debug "Mysql backup utilities verified"
|
34
|
+
end
|
35
|
+
|
36
|
+
def backup(dest_dir)
|
37
|
+
unless Siba::FileHelper.dir_empty? dest_dir
|
38
|
+
raise Siba::Error, "Failed to backup MySQL: output directory is not empty: #{dest_dir}"
|
39
|
+
end
|
40
|
+
|
41
|
+
path_to_backup = File.join dest_dir, BACKUP_FILE_NAME
|
42
|
+
command_without_password = %(mysqldump #{get_mysqldump_params} --routines --result-file="#{path_to_backup}")
|
43
|
+
command = command_without_password
|
44
|
+
unless password.nil?
|
45
|
+
command = command_without_password.gsub HIDE_PASSWORD_TEXT, password
|
46
|
+
end
|
47
|
+
logger.debug command_without_password
|
48
|
+
output = siba_file.run_shell command, "failed to backup MySQL: #{command_without_password}"
|
49
|
+
raise Siba::Error, "failed to backup MySQL: #{output}" if output =~ /ERROR:/
|
50
|
+
|
51
|
+
unless siba_file.file_file? path_to_backup
|
52
|
+
raise Siba::Error, "Failed to backup MySQL: backup file was not created"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def restore(from_dir)
|
57
|
+
path_to_backup = File.join from_dir, BACKUP_FILE_NAME
|
58
|
+
unless siba_file.file_file? path_to_backup
|
59
|
+
raise Siba::Error, "Failed to restore MySQL: backup file does not exist: #{path_to_backup}"
|
60
|
+
end
|
61
|
+
|
62
|
+
command_without_password = %(mysql -e "source #{path_to_backup}" --silent #{get_mysql_params})
|
63
|
+
command = command_without_password
|
64
|
+
unless password.nil?
|
65
|
+
command = command_without_password.gsub HIDE_PASSWORD_TEXT, password
|
66
|
+
end
|
67
|
+
logger.debug command_without_password
|
68
|
+
output = siba_file.run_shell command, "failed to restore MySQL: #{command_without_password}"
|
69
|
+
raise Siba::Error, "Failed to restore MySQL: #{output}" if output =~ /ERROR/
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_mysqldump_params
|
73
|
+
params = []
|
74
|
+
OPTION_NAMES.each do |name|
|
75
|
+
val = options[name]
|
76
|
+
next if val.nil? && name != :databases
|
77
|
+
if MULTIPLE_CHOISES.include? name
|
78
|
+
case name
|
79
|
+
when :databases
|
80
|
+
if val.nil? || val.empty?
|
81
|
+
params << "--all-databases"
|
82
|
+
else
|
83
|
+
params << "--databases #{val.join(" ")}"
|
84
|
+
end
|
85
|
+
when :tables
|
86
|
+
params << "--tables #{val.join(" ")}"
|
87
|
+
when :ignore_tables
|
88
|
+
val.each do |ignore_table|
|
89
|
+
params << %(--ignore-table=#{ignore_table})
|
90
|
+
end
|
91
|
+
end
|
92
|
+
elsif name == :custom_parameters
|
93
|
+
params << val
|
94
|
+
else
|
95
|
+
params << Siba::Source::Mysql::Db.format_mysql_parameter(name, val)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
params.join " "
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_mysql_params
|
102
|
+
params = []
|
103
|
+
LOGIN_PARAMETERS.each do |name|
|
104
|
+
val = options[name]
|
105
|
+
next if val.nil?
|
106
|
+
params << Siba::Source::Mysql::Db.format_mysql_parameter(name, val)
|
107
|
+
end
|
108
|
+
params.join " "
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.format_mysql_parameter(name, val)
|
112
|
+
val = HIDE_PASSWORD_TEXT if name == :password
|
113
|
+
val = escape_for_shell val
|
114
|
+
%(--#{name.to_s}="#{val}")
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.escape_for_shell(str)
|
118
|
+
str.gsub "\"", "\\\""
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.check_spaces_in_arrays(array, option_name)
|
122
|
+
unless array.nil? || array.empty?
|
123
|
+
array.each do |value|
|
124
|
+
value.strip!
|
125
|
+
if value.gsub(/[,;]/," ").split(" ").size > 1
|
126
|
+
raise Siba::CheckError, "'#{option_name}' value can not contain spaces or commas. If you need to specify multiple values please use YAML array sytax instead:
|
127
|
+
- one
|
128
|
+
- two
|
129
|
+
- three"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def method_missing(meth, *args, &block)
|
136
|
+
if method_defined? meth
|
137
|
+
options[meth]
|
138
|
+
else
|
139
|
+
super
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def respond_to?(meth)
|
144
|
+
if method_defined? meth
|
145
|
+
true
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def method_defined?(meth)
|
152
|
+
OPTION_NAMES.include? meth.to_sym
|
153
|
+
end
|
154
|
+
|
155
|
+
def db_and_table_names
|
156
|
+
names = []
|
157
|
+
unless databases.nil? || databases.empty?
|
158
|
+
names << "DB#{databases.size > 1 ? "s": ""}: #{databases.join(", ")}"
|
159
|
+
else
|
160
|
+
names << "all databases"
|
161
|
+
end
|
162
|
+
|
163
|
+
unless tables.nil? || tables.empty?
|
164
|
+
names << "table#{tables.size > 1 ? "s": ""}: #{tables.join(", ")}"
|
165
|
+
end
|
166
|
+
out = names.join(", ")
|
167
|
+
out = " (#{out})" unless out.empty?
|
168
|
+
out
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "siba-source-mysql/db"
|
4
|
+
|
5
|
+
module Siba::Source
|
6
|
+
module Mysql
|
7
|
+
OPTION_NAMES = [
|
8
|
+
:host,
|
9
|
+
:port,
|
10
|
+
:protocol,
|
11
|
+
:socket,
|
12
|
+
:user,
|
13
|
+
:password,
|
14
|
+
:databases,
|
15
|
+
:tables,
|
16
|
+
:ignore_tables,
|
17
|
+
:custom_parameters
|
18
|
+
]
|
19
|
+
|
20
|
+
MULTIPLE_CHOISES = [:databases, :tables, :ignore_tables]
|
21
|
+
LOGIN_PARAMETERS = [:host, :port, :protocol, :socket, :user, :password]
|
22
|
+
ENV_PREFIX = "SIBA_MYSQL_"
|
23
|
+
|
24
|
+
class Init
|
25
|
+
include Siba::LoggerPlug
|
26
|
+
|
27
|
+
attr_accessor :db
|
28
|
+
|
29
|
+
def initialize(options)
|
30
|
+
parsed_options = {}
|
31
|
+
OPTION_NAMES.each do |option_name|
|
32
|
+
if MULTIPLE_CHOISES.include? option_name
|
33
|
+
value = Siba::SibaCheck.options_string_array options, option_name.to_s, true
|
34
|
+
else
|
35
|
+
value = Siba::SibaCheck.options_string options, option_name.to_s, true
|
36
|
+
if value.nil?
|
37
|
+
# try get the setting from environment variable
|
38
|
+
value = ENV["#{ENV_PREFIX}#{option_name.to_s.upcase}"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
parsed_options[option_name] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
@db = Siba::Source::Mysql::Db.new parsed_options
|
45
|
+
end
|
46
|
+
|
47
|
+
# Collect source files and put them into dest_dir
|
48
|
+
# No return value is expected
|
49
|
+
def backup(dest_dir)
|
50
|
+
logger.info "Dumping MySQL#{db.db_and_table_names}"
|
51
|
+
@db.backup dest_dir
|
52
|
+
end
|
53
|
+
|
54
|
+
# Restore source files from_dir
|
55
|
+
# No return value is expected
|
56
|
+
def restore(from_dir)
|
57
|
+
logger.info "Restoring MySQL#{db.db_and_table_names}"
|
58
|
+
@db.restore from_dir
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
host:
|
2
|
+
port:
|
3
|
+
protocol: # TCP|SOCKET|PIPE|MEMORY
|
4
|
+
socket:
|
5
|
+
user:
|
6
|
+
password:
|
7
|
+
databases: # backup all databases if empty
|
8
|
+
- db1
|
9
|
+
tables: # backup all tables if empty
|
10
|
+
- table1
|
11
|
+
- table2
|
12
|
+
ignore_tables:
|
13
|
+
- db1.table1
|
14
|
+
- db1.table2
|
15
|
+
custom_parameters: # additional parameters passed to mysqldump utility
|
16
|
+
|
17
|
+
# Note: all above mysql options are optional (except type)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "siba-source-mysql/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "siba-source-mysql"
|
7
|
+
s.version = Siba::Source::Mysql::VERSION
|
8
|
+
s.authors = ["Evgeny Neumerzhitskiy"]
|
9
|
+
s.email = ["sausageskin@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/evgenyneu/siba-source-mysql"
|
11
|
+
s.license = "MIT"
|
12
|
+
s.summary = %q{MySQL backup and restore extention for SIBA utility}
|
13
|
+
s.description = %q{An extension for SIBA utility. It allows to backup and restore MySQL database.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'siba', '~>0.5'
|
21
|
+
|
22
|
+
s.add_development_dependency 'minitest', '~>2.10'
|
23
|
+
s.add_development_dependency 'rake', '~>0.9'
|
24
|
+
s.add_development_dependency 'guard-minitest', '~>0.4'
|
25
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'helper/require_integration'
|
4
|
+
require 'siba-source-mysql/init'
|
5
|
+
|
6
|
+
describe Siba::Source::Mysql::Init do
|
7
|
+
TEST_DB_NAME = "siba_test_mysql_0992"
|
8
|
+
TEST_VALUE = rand 100000
|
9
|
+
include Siba::FilePlug
|
10
|
+
|
11
|
+
before do
|
12
|
+
@cls = Siba::Source::Mysql::Init
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should backup and restore" do
|
16
|
+
puts "
|
17
|
+
------------------
|
18
|
+
Note: to run integration tests on your MySQL database, please set required access parameters in environment variables: SIBA_MYSQL_USER, SIBA_MYSQL_PASSWORD, SIBA_MYSQL_HOST etc.
|
19
|
+
------------------
|
20
|
+
"
|
21
|
+
begin
|
22
|
+
# insert test data into db
|
23
|
+
@obj = @cls.new({"databases" => [TEST_DB_NAME]})
|
24
|
+
drop_db
|
25
|
+
create_db
|
26
|
+
create_table
|
27
|
+
insert_row
|
28
|
+
count_rows.must_equal 1
|
29
|
+
|
30
|
+
# backup
|
31
|
+
out_dir = mkdir_in_tmp_dir "mysql"
|
32
|
+
@obj.backup out_dir
|
33
|
+
path_to_backup = File.join(out_dir, Siba::Source::Mysql::Db::BACKUP_FILE_NAME)
|
34
|
+
File.file?(path_to_backup).must_equal true
|
35
|
+
|
36
|
+
# add another row after backup
|
37
|
+
insert_row
|
38
|
+
count_rows.must_equal 2
|
39
|
+
|
40
|
+
# restore
|
41
|
+
@obj.restore out_dir
|
42
|
+
count_rows.must_equal 1, "Should restore db to one row"
|
43
|
+
ensure
|
44
|
+
drop_db rescue nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def drop_db
|
49
|
+
sql("drop database if exists #{TEST_DB_NAME}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_db
|
53
|
+
sql("create database #{TEST_DB_NAME}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_table
|
57
|
+
sqldb("create table sibatest (id INT)")
|
58
|
+
end
|
59
|
+
|
60
|
+
def insert_row
|
61
|
+
sqldb(%(insert into sibatest values (123)))
|
62
|
+
end
|
63
|
+
|
64
|
+
def count_rows
|
65
|
+
sqldb(%(select count(*) from sibatest)).to_i
|
66
|
+
end
|
67
|
+
|
68
|
+
def sqldb(sql)
|
69
|
+
sql("#{use_database}#{sql}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def sql(sql)
|
73
|
+
siba_file.run_shell(%(mysql --silent #{get_mysql_params} -e "#{sql}"))
|
74
|
+
end
|
75
|
+
|
76
|
+
def use_database
|
77
|
+
"use #{TEST_DB_NAME}; "
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_mysql_params
|
81
|
+
params = @obj.db.get_mysql_params
|
82
|
+
unless @obj.db.password.nil?
|
83
|
+
params.gsub! Siba::Source::Mysql::Db::HIDE_PASSWORD_TEXT, @obj.db.password
|
84
|
+
end
|
85
|
+
params
|
86
|
+
end
|
87
|
+
|
88
|
+
def insert_value
|
89
|
+
siba_file.run_shell(%(mongo #{TEST_DB_NAME} --quiet --eval "db.foo.save({a: #{TEST_VALUE}})"))
|
90
|
+
end
|
91
|
+
|
92
|
+
def count_values
|
93
|
+
siba_file.run_shell(%(mongo #{TEST_DB_NAME} --quiet --eval "db.foo.count({a: #{TEST_VALUE}})")).to_i
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'helper/require_unit'
|
4
|
+
require 'siba-source-mysql/init'
|
5
|
+
|
6
|
+
describe Siba::Source::Mysql::Db do
|
7
|
+
before do
|
8
|
+
@cls = Siba::Source::Mysql::Db
|
9
|
+
@fmock = mock_file :shell_ok?, true, [String]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize" do
|
13
|
+
options = {a: "b"}
|
14
|
+
@obj = @cls.new options
|
15
|
+
@obj.options.must_equal options
|
16
|
+
end
|
17
|
+
|
18
|
+
it "init should raise error when table are specified with no databases" do
|
19
|
+
->{@cls.new({tables: ["table"]})}.must_raise Siba::CheckError
|
20
|
+
end
|
21
|
+
|
22
|
+
it "init should raise error when table are specified with empty databases" do
|
23
|
+
->{@cls.new({tables: ["table"], databases: []})}.must_raise Siba::CheckError
|
24
|
+
end
|
25
|
+
|
26
|
+
it "init should raise error when table are specified with more than one database" do
|
27
|
+
->{@cls.new({tables: ["table"], databases: ["one", "two"]})}.must_raise Siba::CheckError
|
28
|
+
end
|
29
|
+
|
30
|
+
it "init should raise no error when table are specified with one database" do
|
31
|
+
@cls.new({tables: ["table"], databases: ["one"]})
|
32
|
+
end
|
33
|
+
|
34
|
+
it "init should raise error if databases contain spaces" do
|
35
|
+
->{@cls.new({tables: ["table"], databases: ["with space"]})}.must_raise Siba::CheckError
|
36
|
+
end
|
37
|
+
|
38
|
+
it "init should raise error if tables contain spaces" do
|
39
|
+
->{@cls.new({tables: ["table1 table2"], databases: ["data"]})}.must_raise Siba::CheckError
|
40
|
+
end
|
41
|
+
|
42
|
+
it "init should raise error if ignore_tables contains spaces" do
|
43
|
+
->{@cls.new({ignore_tables: ["table1 table2"], databases: ["data"]})}.must_raise Siba::CheckError
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should call db_and_table_names" do
|
47
|
+
@obj = @cls.new({})
|
48
|
+
@obj.db_and_table_names.must_equal " (all databases)"
|
49
|
+
|
50
|
+
@obj = @cls.new({databases: ["one"]})
|
51
|
+
@obj.db_and_table_names.must_equal " (DB: one)"
|
52
|
+
|
53
|
+
@obj = @cls.new({databases: ["one", "two"]})
|
54
|
+
@obj.db_and_table_names.must_equal " (DBs: one, two)"
|
55
|
+
|
56
|
+
|
57
|
+
@obj = @cls.new({tables: ["table"], databases: ["one"]})
|
58
|
+
@obj.db_and_table_names.must_equal " (DB: one, table: table)"
|
59
|
+
|
60
|
+
@obj = @cls.new({tables: ["table1", "table2"], databases: ["one"]})
|
61
|
+
@obj.db_and_table_names.must_equal " (DB: one, tables: table1, table2)"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "must call check_spaces_in_arrays" do
|
65
|
+
@cls.check_spaces_in_arrays ["hi"], "name"
|
66
|
+
@cls.check_spaces_in_arrays [" hi "], "name"
|
67
|
+
@cls.check_spaces_in_arrays ["hi", "ho"], "name"
|
68
|
+
@cls.check_spaces_in_arrays nil, "name"
|
69
|
+
@cls.check_spaces_in_arrays [], "name"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "check_spaces_in_arrays should fail" do
|
73
|
+
->{@cls.check_spaces_in_arrays ["with space"], "name"}.must_raise Siba::CheckError
|
74
|
+
->{@cls.check_spaces_in_arrays ["hi", "with space"], "name"}.must_raise Siba::CheckError
|
75
|
+
->{@cls.check_spaces_in_arrays ["hi", "with,comma"], "name"}.must_raise Siba::CheckError
|
76
|
+
->{@cls.check_spaces_in_arrays ["hi", "with, comma"], "name"}.must_raise Siba::CheckError
|
77
|
+
->{@cls.check_spaces_in_arrays ["hi", "with;comma"], "name"}.must_raise Siba::CheckError
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should call get_mysqldump_params" do
|
81
|
+
settings = {
|
82
|
+
host: "myhost",
|
83
|
+
port: "123",
|
84
|
+
protocol: "myTCP",
|
85
|
+
socket: "mysock",
|
86
|
+
user: "uname",
|
87
|
+
password: "my password"}
|
88
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
89
|
+
params.must_include %( --host="myhost")
|
90
|
+
params.must_include %( --port="123")
|
91
|
+
params.must_include %( --protocol="myTCP")
|
92
|
+
params.must_include %( --socket="mysock")
|
93
|
+
params.must_include %( --user="uname")
|
94
|
+
params.must_include %( --password="#{@cls::HIDE_PASSWORD_TEXT}")
|
95
|
+
params.must_include %( --all-databases)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "get_mysqldump_params should contain database" do
|
99
|
+
settings = {
|
100
|
+
databases: ["db1"]
|
101
|
+
}
|
102
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
103
|
+
params.must_include %( --databases db1)
|
104
|
+
params.wont_include %( --all-databases)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "get_mysqldump_params should contain databases" do
|
108
|
+
settings = {
|
109
|
+
databases: ["db1", "db2"]
|
110
|
+
}
|
111
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
112
|
+
params.must_include %( --databases db1 db2)
|
113
|
+
params.wont_include %( --all-databases)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "get_mysqldump_params should contain table" do
|
117
|
+
settings = {
|
118
|
+
databases: ["db1"],
|
119
|
+
tables: ["table1"]
|
120
|
+
}
|
121
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
122
|
+
params.must_include %( --tables table1)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "get_mysqldump_params should contain tables" do
|
126
|
+
settings = {
|
127
|
+
databases: ["db1"],
|
128
|
+
tables: ["table1", "table2"]
|
129
|
+
}
|
130
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
131
|
+
params.must_include %( --tables table1 table2)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "get_mysqldump_params should contain ignore-table" do
|
135
|
+
settings = {
|
136
|
+
ignore_tables: ["ig1","ig2"]
|
137
|
+
}
|
138
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
139
|
+
params.must_include %( --ignore-table=ig1)
|
140
|
+
params.must_include %( --ignore-table=ig2)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "get_mysqldump_params should contain databases" do
|
144
|
+
settings = {
|
145
|
+
databases: ["db1", "db2"]
|
146
|
+
}
|
147
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
148
|
+
params.must_include %( --databases db1 db2)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "get_mysqldump_params should contain databases" do
|
152
|
+
custom_text = "this is a cutom text"
|
153
|
+
settings = {
|
154
|
+
custom_parameters: custom_text
|
155
|
+
}
|
156
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
157
|
+
params.must_include %( #{custom_text})
|
158
|
+
end
|
159
|
+
|
160
|
+
it "get_mysqldump_params should escape double quotes" do
|
161
|
+
settings = {
|
162
|
+
user: %(user"name)
|
163
|
+
}
|
164
|
+
params = " " + @cls.new(settings).get_mysqldump_params
|
165
|
+
params.must_include %( --user="user\\"name")
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should call get_mysql_params" do
|
169
|
+
settings = {
|
170
|
+
host: "myhost",
|
171
|
+
port: "123",
|
172
|
+
protocol: "myTCP",
|
173
|
+
socket: "mysock",
|
174
|
+
user: "uname",
|
175
|
+
password: "my password"}
|
176
|
+
params = " " + @cls.new(settings).get_mysql_params
|
177
|
+
params.must_include %( --host="myhost")
|
178
|
+
params.must_include %( --port="123")
|
179
|
+
params.must_include %( --protocol="myTCP")
|
180
|
+
params.must_include %( --socket="mysock")
|
181
|
+
params.must_include %( --user="uname")
|
182
|
+
params.must_include %( --password="#{@cls::HIDE_PASSWORD_TEXT}")
|
183
|
+
params.wont_include %( --all-databases)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should espace for shell" do
|
187
|
+
@cls.escape_for_shell("hi\"").must_equal "hi\\\""
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should call format_mysql_parameter" do
|
191
|
+
@cls.format_mysql_parameter(:name,%(val"val)).must_equal %(--name="val\\"val")
|
192
|
+
@cls.format_mysql_parameter(:password,%(pwd)).must_equal %(--password="#{@cls::HIDE_PASSWORD_TEXT}")
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should run backup" do
|
196
|
+
@fmock.expect :run_this, true, []
|
197
|
+
@fmock.expect :dir_entries, [], [String]
|
198
|
+
@fmock.expect :run_shell, nil, [String, String]
|
199
|
+
@fmock.expect :file_file?, true, [String]
|
200
|
+
@cls.new({}).backup "/dest/dir"
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should run restore" do
|
204
|
+
@fmock.expect :file_file?, true, [String]
|
205
|
+
@fmock.expect :run_shell, nil, [String, String]
|
206
|
+
@cls.new({}).restore "/from/dir"
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'helper/require_unit'
|
4
|
+
require 'siba-source-mysql/init'
|
5
|
+
|
6
|
+
describe Siba::Source::Mysql::Init do
|
7
|
+
before do
|
8
|
+
@yml_path = File.expand_path('../yml', __FILE__)
|
9
|
+
options_hash = load_options "valid"
|
10
|
+
@fmock = mock_file :shell_ok?, true, [String]
|
11
|
+
@plugin = Siba::Source::Mysql::Init.new options_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should load plugin" do
|
15
|
+
@plugin.must_be_instance_of Siba::Source::Mysql::Init
|
16
|
+
@plugin.db.must_be_instance_of Siba::Source::Mysql::Db
|
17
|
+
opt = @plugin.db.options
|
18
|
+
opt[:host].must_equal "myhost"
|
19
|
+
opt[:port].must_equal "123"
|
20
|
+
opt[:protocol].must_equal "TCP"
|
21
|
+
opt[:socket].must_equal "/tmp/mysql.sock"
|
22
|
+
|
23
|
+
opt[:user].must_equal "myuser"
|
24
|
+
opt[:password].must_equal "mypassword"
|
25
|
+
|
26
|
+
opt[:databases].must_equal ["db1"]
|
27
|
+
opt[:tables].must_equal ["table1", "table2"]
|
28
|
+
opt[:ignore_tables].must_equal ["db1.table1", "db1.table2"]
|
29
|
+
opt[:custom_parameters].must_equal "--parameters"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should load plugin with empty options" do
|
33
|
+
Siba::Source::Mysql::Init.new({})
|
34
|
+
end
|
35
|
+
|
36
|
+
it "plugin should load options from environment variables" do
|
37
|
+
begin
|
38
|
+
env_user = ENV[env_var_name("USER")]
|
39
|
+
env_password = ENV[env_var_name("PASSWORD")]
|
40
|
+
env_host = ENV[env_var_name("HOST")]
|
41
|
+
|
42
|
+
ENV[env_var_name("USER")] = "myuser"
|
43
|
+
ENV[env_var_name("PASSWORD")] = "mypassword"
|
44
|
+
ENV[env_var_name("HOST")] = "myhost"
|
45
|
+
@plugin = Siba::Source::Mysql::Init.new({"host"=> "thishost"})
|
46
|
+
@plugin.db.user.must_equal "myuser"
|
47
|
+
@plugin.db.password.must_equal "mypassword"
|
48
|
+
@plugin.db.host.must_equal "thishost" # this is specified, do not get from environment
|
49
|
+
ensure
|
50
|
+
ENV[env_var_name("USER")] = env_user
|
51
|
+
ENV[env_var_name("PASSWORD")] = env_password
|
52
|
+
ENV[env_var_name("HOST")] = env_host
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def env_var_name(name)
|
57
|
+
"#{Siba::Source::Mysql::ENV_PREFIX}#{name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should call backup" do
|
61
|
+
@fmock.expect :run_this, true, []
|
62
|
+
@fmock.expect :dir_entries, [], [String]
|
63
|
+
@fmock.expect :run_shell, nil, [String, String]
|
64
|
+
@fmock.expect :file_file?, true, [String]
|
65
|
+
@plugin.backup "/dest/dir"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should call restore" do
|
69
|
+
@fmock.expect :file_file?, true, [String]
|
70
|
+
@fmock.expect :run_shell, nil, [String, String]
|
71
|
+
@plugin.restore "/from_dir"
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: siba-source-mysql
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Evgeny Neumerzhitskiy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: siba
|
16
|
+
requirement: &76126290 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.5'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *76126290
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: minitest
|
27
|
+
requirement: &76126050 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.10'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *76126050
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &76125820 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.9'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *76125820
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: guard-minitest
|
49
|
+
requirement: &76125590 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *76125590
|
58
|
+
description: An extension for SIBA utility. It allows to backup and restore MySQL
|
59
|
+
database.
|
60
|
+
email:
|
61
|
+
- sausageskin@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- Gemfile
|
68
|
+
- Guardfile
|
69
|
+
- LICENSE
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- lib/siba-source-mysql.rb
|
73
|
+
- lib/siba-source-mysql/db.rb
|
74
|
+
- lib/siba-source-mysql/init.rb
|
75
|
+
- lib/siba-source-mysql/options.yml
|
76
|
+
- lib/siba-source-mysql/version.rb
|
77
|
+
- siba-source-mysql.gemspec
|
78
|
+
- test/helper/require_integration.rb
|
79
|
+
- test/helper/require_unit.rb
|
80
|
+
- test/integration/i9n_init.rb
|
81
|
+
- test/unit/test_db.rb
|
82
|
+
- test/unit/test_init.rb
|
83
|
+
- test/unit/yml/valid.yml
|
84
|
+
homepage: https://github.com/evgenyneu/siba-source-mysql
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.11
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: MySQL backup and restore extention for SIBA utility
|
109
|
+
test_files: []
|