siba 0.4.3
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 +7 -0
- data/Gemfile +4 -0
- data/Guardfile +18 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +27 -0
- data/bin/siba +5 -0
- data/lib/siba.rb +27 -0
- data/lib/siba/backup.rb +31 -0
- data/lib/siba/console.rb +196 -0
- data/lib/siba/errors.rb +8 -0
- data/lib/siba/generator.rb +115 -0
- data/lib/siba/globals.rb +19 -0
- data/lib/siba/helpers/encoding_helper.rb +38 -0
- data/lib/siba/helpers/file_helper.rb +89 -0
- data/lib/siba/helpers/gem_helper.rb +22 -0
- data/lib/siba/helpers/password_strength.rb +94 -0
- data/lib/siba/helpers/security_helper.rb +30 -0
- data/lib/siba/helpers/string_helper.rb +32 -0
- data/lib/siba/helpers/test/extend_test.rb +114 -0
- data/lib/siba/helpers/test/file_mock.rb +38 -0
- data/lib/siba/helpers/test/helper.rb +55 -0
- data/lib/siba/helpers/test/kernel_mock.rb +44 -0
- data/lib/siba/helpers/test/removable_constants.rb +18 -0
- data/lib/siba/helpers/test/require.rb +12 -0
- data/lib/siba/logger_plug.rb +36 -0
- data/lib/siba/options_backup.rb +37 -0
- data/lib/siba/options_loader.rb +38 -0
- data/lib/siba/plugins/archive/tar/archive.rb +117 -0
- data/lib/siba/plugins/archive/tar/init.rb +38 -0
- data/lib/siba/plugins/archive/tar/options.yml +1 -0
- data/lib/siba/plugins/destination/dir/dest_dir.rb +77 -0
- data/lib/siba/plugins/destination/dir/init.rb +31 -0
- data/lib/siba/plugins/destination/dir/options.yml +2 -0
- data/lib/siba/plugins/encryption/gpg/encryption.rb +140 -0
- data/lib/siba/plugins/encryption/gpg/init.rb +45 -0
- data/lib/siba/plugins/encryption/gpg/options.yml +2 -0
- data/lib/siba/plugins/installed_plugins.rb +77 -0
- data/lib/siba/plugins/plugin_loader.rb +100 -0
- data/lib/siba/plugins/plugins.rb +57 -0
- data/lib/siba/plugins/plugins.yml +9 -0
- data/lib/siba/plugins/source/files/files.rb +166 -0
- data/lib/siba/plugins/source/files/init.rb +33 -0
- data/lib/siba/plugins/source/files/options.yml +11 -0
- data/lib/siba/restore.rb +113 -0
- data/lib/siba/scaffold.rb +166 -0
- data/lib/siba/siba_check.rb +75 -0
- data/lib/siba/siba_file.rb +89 -0
- data/lib/siba/siba_kernel.rb +37 -0
- data/lib/siba/siba_logger.rb +172 -0
- data/lib/siba/tasks/siba_task.rb +42 -0
- data/lib/siba/tasks/siba_tasks.rb +120 -0
- data/lib/siba/test_files.rb +76 -0
- data/lib/siba/test_files/a_file +1 -0
- data/lib/siba/test_files/files_and_dirs/.hidden +1 -0
- data/lib/siba/test_files/files_and_dirs/.hidden_dir/file10 +1 -0
- data/lib/siba/test_files/files_and_dirs/File With Spaces +1 -0
- data/lib/siba/test_files/files_and_dirs/dir1/file10 +1 -0
- data/lib/siba/test_files/files_and_dirs/dir1/sub-dir/file111.txt +1 -0
- data/lib/siba/test_files/files_and_dirs/file1 +1 -0
- data/lib/siba/test_files/files_and_dirs/file2.txt +1 -0
- data/lib/siba/tmp_dir.rb +94 -0
- data/lib/siba/version.rb +5 -0
- data/scaffolds/archive.rb +26 -0
- data/scaffolds/destination.rb +20 -0
- data/scaffolds/encryption.rb +26 -0
- data/scaffolds/project/.gitignore +5 -0
- data/scaffolds/project/Gemfile +4 -0
- data/scaffolds/project/Guardfile +9 -0
- data/scaffolds/project/LICENSE +22 -0
- data/scaffolds/project/README.md +33 -0
- data/scaffolds/project/Rakefile +28 -0
- data/scaffolds/project/lib/siba-c6y-demo.rb +11 -0
- data/scaffolds/project/lib/siba-c6y-demo/options.yml +2 -0
- data/scaffolds/project/lib/siba-c6y-demo/version.rb +9 -0
- data/scaffolds/project/siba-c6y-demo.gemspec +26 -0
- data/scaffolds/project/test/helper/require_integration.rb +5 -0
- data/scaffolds/project/test/helper/require_unit.rb +4 -0
- data/scaffolds/project/test/integration/i9n_init.rb +35 -0
- data/scaffolds/project/test/unit/test_init.rb +43 -0
- data/scaffolds/project/test/unit/yml/valid.yml +8 -0
- data/scaffolds/shared/examples.rb +47 -0
- data/scaffolds/shared/init_example.rb +13 -0
- data/scaffolds/source.rb +25 -0
- data/siba.gemspec +30 -0
- data/test/helper/require_integration.rb +4 -0
- data/test/helper/require_unit.rb +4 -0
- data/test/integration/helpers/i9n_file_helper.rb +50 -0
- data/test/integration/i9n_backup.rb +53 -0
- data/test/integration/i9n_console.rb +16 -0
- data/test/integration/i9n_generator.rb +29 -0
- data/test/integration/i9n_options_backup.rb +22 -0
- data/test/integration/i9n_scaffold.rb +27 -0
- data/test/integration/i9n_siba_file.rb +30 -0
- data/test/integration/i9n_test_unicode_files.rb +40 -0
- data/test/integration/i9n_tmp_dir.rb +44 -0
- data/test/integration/plugins/archive/tar/i9n_archive.rb +18 -0
- data/test/integration/plugins/destination/dir/i9n_dest_dir.rb +52 -0
- data/test/integration/plugins/encryption/gpg/i9n_encryption.rb +87 -0
- data/test/integration/plugins/i9n_installed_plugins.rb +13 -0
- data/test/integration/plugins/source/files/i9n_files.rb +146 -0
- data/test/integration/tasks/i9n_siba_tasks.rb +30 -0
- data/test/integration/yml/valid.yml +16 -0
- data/test/unit/helpers/test_encoding_helper.rb +17 -0
- data/test/unit/helpers/test_gem_helper.rb +17 -0
- data/test/unit/helpers/test_security_helper.rb +21 -0
- data/test/unit/helpers/test_string_helper.rb +35 -0
- data/test/unit/plugins/archive/tar/test_archive.rb +41 -0
- data/test/unit/plugins/archive/tar/test_init.rb +36 -0
- data/test/unit/plugins/archive/tar/yml/archive/check_installed.yml +2 -0
- data/test/unit/plugins/archive/tar/yml/init/default_compression.yml +1 -0
- data/test/unit/plugins/archive/tar/yml/init/invalid_compression.yml +2 -0
- data/test/unit/plugins/archive/tar/yml/init/valid.yml +2 -0
- data/test/unit/plugins/destination/dir/test_dest_dir.rb +41 -0
- data/test/unit/plugins/destination/dir/test_init.rb +36 -0
- data/test/unit/plugins/destination/dir/yml/init/valid.yml +2 -0
- data/test/unit/plugins/encryption/gpg/test_encryption.rb +70 -0
- data/test/unit/plugins/encryption/gpg/test_init.rb +47 -0
- data/test/unit/plugins/source/files/test_files.rb +44 -0
- data/test/unit/plugins/source/files/test_init.rb +48 -0
- data/test/unit/plugins/source/files/test_path_match.rb +140 -0
- data/test/unit/plugins/source/files/yml/ignore_list.yml +8 -0
- data/test/unit/plugins/source/files/yml/ignore_not_array.yml +5 -0
- data/test/unit/plugins/source/files/yml/include_not_array.yml +3 -0
- data/test/unit/plugins/source/files/yml/include_subdirs_false.yml +6 -0
- data/test/unit/plugins/source/files/yml/include_subdirs_missing.yml +5 -0
- data/test/unit/plugins/source/files/yml/no_ignore.yml +4 -0
- data/test/unit/plugins/source/files/yml/no_include.yml +1 -0
- data/test/unit/plugins/source/files/yml/valid.yml +9 -0
- data/test/unit/plugins/test_installed_plugins.rb +32 -0
- data/test/unit/plugins/test_plugin_loader.rb +27 -0
- data/test/unit/plugins/test_plugins.rb +44 -0
- data/test/unit/tasks/test_siba_task.rb +30 -0
- data/test/unit/tasks/test_siba_tasks.rb +84 -0
- data/test/unit/tasks/yml/task/invalid.yml +4 -0
- data/test/unit/tasks/yml/task/valid.yml +7 -0
- data/test/unit/test_backup.rb +18 -0
- data/test/unit/test_console.rb +166 -0
- data/test/unit/test_generator.rb +21 -0
- data/test/unit/test_globals.rb +34 -0
- data/test/unit/test_log_message.rb +26 -0
- data/test/unit/test_logger_plug.rb +49 -0
- data/test/unit/test_options_backup.rb +21 -0
- data/test/unit/test_options_loader.rb +72 -0
- data/test/unit/test_password_strength.rb +76 -0
- data/test/unit/test_restore.rb +18 -0
- data/test/unit/test_scaffold.rb +26 -0
- data/test/unit/test_siba_check.rb +118 -0
- data/test/unit/test_siba_logger.rb +174 -0
- data/test/unit/test_tmp_dir.rb +21 -0
- data/test/unit/yml/options_loader/array.yml +2 -0
- data/test/unit/yml/options_loader/empty.yml +0 -0
- data/test/unit/yml/options_loader/invalid.yml +4 -0
- data/test/unit/yml/options_loader/string.yml +1 -0
- data/test/unit/yml/options_loader/utf8_with_bom.yml +2 -0
- data/test/unit/yml/options_loader/valid.yml +12 -0
- data/test/unit/yml/siba_options_backup.yml +20 -0
- data/test/unit/yml/valid.yml +18 -0
- metadata +240 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class SibaCheck
|
|
5
|
+
class << self
|
|
6
|
+
def options_bool(options, key_name, is_optional = false, default_value=false)
|
|
7
|
+
check_options options, key_name, [TrueClass, FalseClass], is_optional, default_value
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def options_hash(options, key_name, is_optional = false, default_value=nil)
|
|
11
|
+
check_options options, key_name, Hash, is_optional, default_value
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def options_string(options, key_name, is_optional = false, default_value=nil)
|
|
15
|
+
check_options(options, key_name, String, is_optional, default_value)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def options_string_array(options, key_name, is_optional = false, default_value=nil)
|
|
19
|
+
value = options[key_name]
|
|
20
|
+
if value.nil?
|
|
21
|
+
return default_value if is_optional
|
|
22
|
+
raise Siba::CheckError, "'#{key_name}' option is not defined"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
if value.is_a? Array
|
|
27
|
+
value.each_index do |i|
|
|
28
|
+
value[i] = try_to_s value[i], key_name
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
value = [ try_to_s(value, key_name) ]
|
|
32
|
+
end
|
|
33
|
+
rescue Exception
|
|
34
|
+
raise Siba::CheckError, "'#{key_name}' option should be string or an array of strings"
|
|
35
|
+
end
|
|
36
|
+
value
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def hash(obj, name, is_optional=false)
|
|
40
|
+
if obj.nil?
|
|
41
|
+
return nil if is_optional
|
|
42
|
+
raise Siba::CheckError, "'#{name}' option is not defined"
|
|
43
|
+
end
|
|
44
|
+
raise Siba::CheckError, "'#{name}' option should be of [Hash] type" unless obj.is_a? Hash
|
|
45
|
+
obj
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Tries to conver value to string
|
|
49
|
+
def try_to_s(value, key_name)
|
|
50
|
+
raise Siba::CheckError, "'#{key_name}' option should be string" if [Array, Hash].any?{|a| value.is_a?(a)}
|
|
51
|
+
value = value.to_s.strip
|
|
52
|
+
raise Siba::CheckError, "'#{key_name}' option should not be empty" if value.empty?
|
|
53
|
+
value
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def check_options(options, key_name, item_type, is_optional = false, default_value = nil)
|
|
59
|
+
value = options[key_name]
|
|
60
|
+
if value.nil?
|
|
61
|
+
raise Siba::CheckError, "'#{key_name}' option is not defined" unless is_optional
|
|
62
|
+
return default_value
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if item_type == String
|
|
66
|
+
value = try_to_s value, key_name
|
|
67
|
+
else
|
|
68
|
+
item_type = [item_type] unless item_type.is_a?(Array)
|
|
69
|
+
raise Siba::CheckError, "'#{key_name}' option should be of #{item_type.to_s} type" if item_type.none? {|i| value.is_a? i }
|
|
70
|
+
end
|
|
71
|
+
value
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'open3'
|
|
6
|
+
|
|
7
|
+
module Siba
|
|
8
|
+
class SibaFile
|
|
9
|
+
def run_this(name="noname")
|
|
10
|
+
yield
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
DIR_REGEXP = /^dir_/
|
|
14
|
+
FILE_REGEXP = /^file_/
|
|
15
|
+
FILE_UTILS_REGEXP = /^file_utils_/
|
|
16
|
+
|
|
17
|
+
def self.get_file_class(meth)
|
|
18
|
+
case meth
|
|
19
|
+
when FILE_UTILS_REGEXP
|
|
20
|
+
return FileUtils, meth.to_s.gsub(FILE_UTILS_REGEXP, "")
|
|
21
|
+
when DIR_REGEXP
|
|
22
|
+
return Dir, meth.to_s.gsub(DIR_REGEXP, "")
|
|
23
|
+
when FILE_REGEXP
|
|
24
|
+
return File, meth.to_s.gsub(FILE_REGEXP, "")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def method_missing(meth, *args, &block)
|
|
29
|
+
file_class, class_meth = SibaFile.get_file_class meth
|
|
30
|
+
if file_class
|
|
31
|
+
file_class.send(class_meth, *args, &block)
|
|
32
|
+
else
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def respond_to?(meth)
|
|
38
|
+
if SibaFile.get_file_class meth
|
|
39
|
+
true
|
|
40
|
+
else
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def file_expand_path(file_name, dir_string=nil)
|
|
46
|
+
file_utils_cd Siba.current_dir unless Siba.current_dir.nil?
|
|
47
|
+
File.expand_path file_name, dir_string
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Runs shell command and raises error if it fails
|
|
51
|
+
# returns output (both stdout and stderr)
|
|
52
|
+
def run_shell(command, fail_message=nil)
|
|
53
|
+
strout, status = Open3.capture2e command
|
|
54
|
+
raise strout if status.to_i != 0
|
|
55
|
+
return strout
|
|
56
|
+
rescue Exception => ex
|
|
57
|
+
fail_message ||= "Failed to run the command: #{command}"
|
|
58
|
+
raise Siba::Error, "#{fail_message}
|
|
59
|
+
#{ex.message}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Runs the shell command.
|
|
63
|
+
# Works the same way as Kernel.system method but without showing the output.
|
|
64
|
+
# Returns true if it was successfull.
|
|
65
|
+
def shell_ok?(command)
|
|
66
|
+
# Using Open3 instead of `` or system("cmd") in order to hide stderr output
|
|
67
|
+
sout, status = Open3.capture2e command
|
|
68
|
+
return status.to_i == 0
|
|
69
|
+
rescue
|
|
70
|
+
return false
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Used to inject "siba_file" to classes that include this module
|
|
75
|
+
module FilePlug
|
|
76
|
+
def siba_file
|
|
77
|
+
FilePlug.siba_file
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.siba_file
|
|
81
|
+
@siba_file ||= SibaFile.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# It is used in test to insert mock SibaFile object
|
|
85
|
+
def self.siba_file=(val)
|
|
86
|
+
@siba_file = val
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class SibaKernel
|
|
5
|
+
undef_method :puts
|
|
6
|
+
def method_missing(meth, *args, &block)
|
|
7
|
+
if Kernel.respond_to? meth
|
|
8
|
+
Kernel.send meth, *args, &block
|
|
9
|
+
else
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def respond_to?(meth)
|
|
15
|
+
if Kernel.respond_to? meth
|
|
16
|
+
true
|
|
17
|
+
else
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module KernelPlug
|
|
24
|
+
def siba_kernel
|
|
25
|
+
KernelPlug.siba_kernel
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.siba_kernel
|
|
29
|
+
@siba_kernel ||= Siba::SibaKernel.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# It is used in test to insert mock SibaKernel object
|
|
33
|
+
def self.siba_kernel=(val)
|
|
34
|
+
@siba_kernel = val
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'logger'
|
|
3
|
+
|
|
4
|
+
module Siba
|
|
5
|
+
class SibaLogger
|
|
6
|
+
LogLevels = %w(debug info warn error fatal unknown)
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor :quiet, :verbose, :no_log, :messages
|
|
10
|
+
|
|
11
|
+
def log_level?(level)
|
|
12
|
+
SibaLogger::LogLevels.include? level
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def check_log_level(level)
|
|
16
|
+
raise "Unsupported log level '#{level}'" unless SibaLogger::log_level? level
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def level_to_i(level)
|
|
20
|
+
check_log_level level
|
|
21
|
+
SibaLogger::LogLevels.index level
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def count(severity=nil, exact_level=true)
|
|
25
|
+
return 0 if SibaLogger.messages.nil?
|
|
26
|
+
return SibaLogger.messages.size if severity.nil?
|
|
27
|
+
severity_i = SibaLogger.level_to_i severity
|
|
28
|
+
SibaLogger.messages.count do |i|
|
|
29
|
+
if exact_level
|
|
30
|
+
i.level == severity_i
|
|
31
|
+
else
|
|
32
|
+
i.level >= severity_i
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attr_accessor :show_finish_message
|
|
39
|
+
|
|
40
|
+
def initialize(name, path_to_log_file, show_start_message = true)
|
|
41
|
+
@show_finish_message = true
|
|
42
|
+
@name = name
|
|
43
|
+
SibaLogger.messages = []
|
|
44
|
+
@loggers = []
|
|
45
|
+
|
|
46
|
+
@strlog = StringIO.new
|
|
47
|
+
@loggers << Logger.new(@strlog)
|
|
48
|
+
|
|
49
|
+
unless SibaLogger.quiet
|
|
50
|
+
@stdout_log = Logger.new(STDOUT)
|
|
51
|
+
@loggers << stdout_log
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
unless path_to_log_file.nil? || SibaLogger.no_log
|
|
55
|
+
@file = File.open(path_to_log_file, "a:utf-8")
|
|
56
|
+
@file_log = Logger.new(file)
|
|
57
|
+
@loggers << file_log
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
@loggers.each do |logger|
|
|
61
|
+
logger.formatter = method(:formatter)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
file_log.info "
|
|
65
|
+
||----------NEW LOG----------||
|
|
66
|
+
|| #{Time.now} ||
|
|
67
|
+
||---------------------------||
|
|
68
|
+
" unless file_log.nil?
|
|
69
|
+
|
|
70
|
+
info "#{name} started" if show_start_message
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def to_s
|
|
74
|
+
strlog.string
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def close
|
|
78
|
+
if show_finish_message
|
|
79
|
+
if SibaLogger.count('fatal') > 0
|
|
80
|
+
info "#{name} failed"
|
|
81
|
+
elsif SibaLogger.count('warn', false) == 0
|
|
82
|
+
info "#{name} finished successfully"
|
|
83
|
+
else
|
|
84
|
+
info "#{name} completed with some issues"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
unless file.nil?
|
|
89
|
+
file.close
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
unless file_log.nil?
|
|
93
|
+
file_log.close
|
|
94
|
+
end
|
|
95
|
+
@loggers = []
|
|
96
|
+
@strlog = nil
|
|
97
|
+
@file_log = nil
|
|
98
|
+
@file = nil
|
|
99
|
+
@stdout_log = nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def warn(*args, &block)
|
|
103
|
+
log('warn', *args, &block)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def log_exception(exception, log_only_backtrace=false)
|
|
107
|
+
log('debug',exception.message) unless log_only_backtrace
|
|
108
|
+
unless exception.backtrace.nil?
|
|
109
|
+
log('debug',"\n--- stack trace ---\n#{exception.backtrace.join("\n")}\n--- stack trace ---")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def method_missing(meth, *args, &block)
|
|
114
|
+
if SibaLogger::log_level? meth.to_s
|
|
115
|
+
log(meth.to_s, *args, &block)
|
|
116
|
+
else
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def respond_to?(meth)
|
|
122
|
+
if SibaLogger::log_level? meth.to_s
|
|
123
|
+
true
|
|
124
|
+
else
|
|
125
|
+
super
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
attr_accessor :loggers, :name, :strlog, :file_log, :stdout_log, :file
|
|
131
|
+
|
|
132
|
+
def log(level, *args, &block)
|
|
133
|
+
raise Siba::Error, "Log is closed" if loggers.empty?
|
|
134
|
+
level_i = SibaLogger::level_to_i level
|
|
135
|
+
unless block.nil?
|
|
136
|
+
msg = block.call.to_s
|
|
137
|
+
else
|
|
138
|
+
assert "Wrong number of arguments" if args.size != 1
|
|
139
|
+
msg = args[0].to_s
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
log_message = LogMessage.new
|
|
143
|
+
log_message.level = level_i
|
|
144
|
+
log_message.time = Time.now
|
|
145
|
+
log_message.msg = msg
|
|
146
|
+
SibaLogger.messages << log_message
|
|
147
|
+
|
|
148
|
+
loggers.each do |l|
|
|
149
|
+
l.send(level, msg) unless l == stdout_log
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
unless stdout_log.nil?
|
|
153
|
+
stdout_log.send(level, EncodingHelper.encode_to_external(msg)) unless level == 'debug' && !SibaLogger.verbose
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def formatter(severity, datetime, progname, msg)
|
|
158
|
+
if ["INFO", "DEBUG"].include? severity
|
|
159
|
+
severity = ""
|
|
160
|
+
else
|
|
161
|
+
severity = "WARNING" if severity == "WARN"
|
|
162
|
+
severity += " - "
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
"#{severity}#{msg}\n"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
class LogMessage
|
|
170
|
+
attr_accessor :level, :time, :msg
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class SibaTask
|
|
5
|
+
include Siba::LoggerPlug
|
|
6
|
+
|
|
7
|
+
attr_accessor :category, :type, :options, :plugin
|
|
8
|
+
|
|
9
|
+
def initialize(options, category)
|
|
10
|
+
@category = category
|
|
11
|
+
load Siba::SibaCheck.options_hash(options, category)
|
|
12
|
+
rescue
|
|
13
|
+
logger.error "Failed to load #{category} plugin"
|
|
14
|
+
raise
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def backup(*args)
|
|
18
|
+
logger.debug "Running #{category}/#{type}"
|
|
19
|
+
@plugin.backup *args
|
|
20
|
+
rescue Exception
|
|
21
|
+
logger.error "Failed to backup #{category}/#{type}"
|
|
22
|
+
raise
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def restore(*args)
|
|
26
|
+
logger.debug "Restoring #{category}/#{type}"
|
|
27
|
+
@plugin.restore *args
|
|
28
|
+
rescue Exception
|
|
29
|
+
logger.error "Failed to restore #{category}/#{type}"
|
|
30
|
+
raise
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def load(options)
|
|
36
|
+
@options = options
|
|
37
|
+
@type = Siba::SibaCheck.options_string(@options, "type")
|
|
38
|
+
@type.downcase!
|
|
39
|
+
@plugin = Siba::PluginLoader.loader.load(category, type, options)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'siba/tasks/siba_task'
|
|
4
|
+
|
|
5
|
+
module Siba
|
|
6
|
+
class SibaTasks
|
|
7
|
+
include Siba::FilePlug
|
|
8
|
+
attr_accessor :tasks
|
|
9
|
+
|
|
10
|
+
def initialize(options, path_to_options_yml, skip_source_task)
|
|
11
|
+
@path_to_options_yml = path_to_options_yml
|
|
12
|
+
raise 'Options are not loaded' if options.nil?
|
|
13
|
+
|
|
14
|
+
@tasks = {}
|
|
15
|
+
Siba::Plugins::CATEGORIES.each do |category|
|
|
16
|
+
next if category == "source" && skip_source_task
|
|
17
|
+
@tasks[category] = SibaTask.new options, category
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def backup
|
|
22
|
+
siba_file.run_this "backup" do
|
|
23
|
+
@tasks["source"].backup source_dir
|
|
24
|
+
raise Siba::Error, "There are no files to backup" if Siba::FileHelper.dir_empty? source_dir
|
|
25
|
+
OptionsBackup.save_options_backup path_to_options_yml, source_dir
|
|
26
|
+
|
|
27
|
+
archive_file_name = @tasks["archive"].backup source_dir, archive_dir, SibaTasks.backup_name
|
|
28
|
+
unless archive_file_name =~ /^#{SibaTasks.backup_name}/
|
|
29
|
+
raise Siba::Error, "Archive file name must begin with: #{SibaTasks.backup_name}"
|
|
30
|
+
end
|
|
31
|
+
path_to_archive = File.join archive_dir, archive_file_name
|
|
32
|
+
unless siba_file.file_file? path_to_archive
|
|
33
|
+
raise Siba::Error, "Failed to create archive file: #{path_to_archive}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
name_of_encrypted_file = @tasks["encryption"].backup path_to_archive, encryption_dir
|
|
37
|
+
unless name_of_encrypted_file =~ /^#{archive_file_name}/
|
|
38
|
+
raise Siba::Error, "File name of encrypted file must begin with: #{archive_file_name}"
|
|
39
|
+
end
|
|
40
|
+
path_to_backup = File.join encryption_dir, name_of_encrypted_file
|
|
41
|
+
unless siba_file.file_file? path_to_backup
|
|
42
|
+
raise Siba::Error, "Failed to encrypt backup: #{path_to_backup}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
@tasks["destination"].backup path_to_backup
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def restore(backup_file_name)
|
|
50
|
+
siba_file.run_this do
|
|
51
|
+
@tasks["destination"].restore backup_file_name, destination_dir
|
|
52
|
+
path_to_backup = File.join destination_dir, backup_file_name
|
|
53
|
+
unless siba_file.file_file? path_to_backup
|
|
54
|
+
raise Siba::Error, "Failed to get backup from destination: #{backup_file_name}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
archive_file_name = @tasks["encryption"].restore path_to_backup, encryption_dir
|
|
58
|
+
path_to_archive = File.join encryption_dir, archive_file_name
|
|
59
|
+
unless siba_file.file_file? path_to_archive
|
|
60
|
+
raise Siba::Error, "Failed to get archive file: #{path_to_archive}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@tasks["archive"].restore path_to_archive, source_dir
|
|
64
|
+
if Siba::FileHelper.dir_empty? source_dir
|
|
65
|
+
raise Siba::Error, "Failed to extract archive: #{path_to_archive}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
@tasks["source"] = OptionsBackup.load_source_from_backup source_dir
|
|
69
|
+
@tasks["source"].restore source_dir
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def get_backups_list
|
|
74
|
+
@tasks["destination"].plugin.get_backups_list Siba.backup_name
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.backup_name(now=nil)
|
|
78
|
+
if Siba::StringHelper.nil_or_empty Siba.backup_name
|
|
79
|
+
raise Siba::Error, "Backup task name is not specified"
|
|
80
|
+
end
|
|
81
|
+
"#{Siba.backup_name}-#{SibaTasks.backup_name_suffix(now)}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
attr_accessor :path_to_options_yml
|
|
87
|
+
|
|
88
|
+
def source_dir
|
|
89
|
+
@source_dir ||= TestFiles::mkdir_in_tmp_dir("src").freeze
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def archive_dir
|
|
93
|
+
@archive_dir ||= TestFiles::mkdir_in_tmp_dir("arc").freeze
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def encryption_dir
|
|
97
|
+
@encryption_dir ||= TestFiles::mkdir_in_tmp_dir("enc").freeze
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def destination_dir
|
|
101
|
+
@destination_dir ||= TestFiles::mkdir_in_tmp_dir("dest").freeze
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def self.backup_name_suffix(now=nil)
|
|
105
|
+
now ||= Time.now
|
|
106
|
+
|
|
107
|
+
# Monthly backup on the 1st day of each month
|
|
108
|
+
# "month-01" through "month-12"
|
|
109
|
+
return "month-#{"%02d" % now.month}" if now.day == 1
|
|
110
|
+
|
|
111
|
+
# Weekly backup on Sunday
|
|
112
|
+
# "week-1-sun" through "week-5-sun"
|
|
113
|
+
return "week-#{(now.day-1) / 7 + 1}-sun" if now.wday == 0
|
|
114
|
+
|
|
115
|
+
# Daily backup
|
|
116
|
+
# "day-2-mon" through "day-7-sat"
|
|
117
|
+
"day-#{now.wday+1}-#{now.strftime("%a").downcase}"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|