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.
Files changed (159) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +18 -0
  4. data/LICENSE +22 -0
  5. data/README.md +47 -0
  6. data/Rakefile +27 -0
  7. data/bin/siba +5 -0
  8. data/lib/siba.rb +27 -0
  9. data/lib/siba/backup.rb +31 -0
  10. data/lib/siba/console.rb +196 -0
  11. data/lib/siba/errors.rb +8 -0
  12. data/lib/siba/generator.rb +115 -0
  13. data/lib/siba/globals.rb +19 -0
  14. data/lib/siba/helpers/encoding_helper.rb +38 -0
  15. data/lib/siba/helpers/file_helper.rb +89 -0
  16. data/lib/siba/helpers/gem_helper.rb +22 -0
  17. data/lib/siba/helpers/password_strength.rb +94 -0
  18. data/lib/siba/helpers/security_helper.rb +30 -0
  19. data/lib/siba/helpers/string_helper.rb +32 -0
  20. data/lib/siba/helpers/test/extend_test.rb +114 -0
  21. data/lib/siba/helpers/test/file_mock.rb +38 -0
  22. data/lib/siba/helpers/test/helper.rb +55 -0
  23. data/lib/siba/helpers/test/kernel_mock.rb +44 -0
  24. data/lib/siba/helpers/test/removable_constants.rb +18 -0
  25. data/lib/siba/helpers/test/require.rb +12 -0
  26. data/lib/siba/logger_plug.rb +36 -0
  27. data/lib/siba/options_backup.rb +37 -0
  28. data/lib/siba/options_loader.rb +38 -0
  29. data/lib/siba/plugins/archive/tar/archive.rb +117 -0
  30. data/lib/siba/plugins/archive/tar/init.rb +38 -0
  31. data/lib/siba/plugins/archive/tar/options.yml +1 -0
  32. data/lib/siba/plugins/destination/dir/dest_dir.rb +77 -0
  33. data/lib/siba/plugins/destination/dir/init.rb +31 -0
  34. data/lib/siba/plugins/destination/dir/options.yml +2 -0
  35. data/lib/siba/plugins/encryption/gpg/encryption.rb +140 -0
  36. data/lib/siba/plugins/encryption/gpg/init.rb +45 -0
  37. data/lib/siba/plugins/encryption/gpg/options.yml +2 -0
  38. data/lib/siba/plugins/installed_plugins.rb +77 -0
  39. data/lib/siba/plugins/plugin_loader.rb +100 -0
  40. data/lib/siba/plugins/plugins.rb +57 -0
  41. data/lib/siba/plugins/plugins.yml +9 -0
  42. data/lib/siba/plugins/source/files/files.rb +166 -0
  43. data/lib/siba/plugins/source/files/init.rb +33 -0
  44. data/lib/siba/plugins/source/files/options.yml +11 -0
  45. data/lib/siba/restore.rb +113 -0
  46. data/lib/siba/scaffold.rb +166 -0
  47. data/lib/siba/siba_check.rb +75 -0
  48. data/lib/siba/siba_file.rb +89 -0
  49. data/lib/siba/siba_kernel.rb +37 -0
  50. data/lib/siba/siba_logger.rb +172 -0
  51. data/lib/siba/tasks/siba_task.rb +42 -0
  52. data/lib/siba/tasks/siba_tasks.rb +120 -0
  53. data/lib/siba/test_files.rb +76 -0
  54. data/lib/siba/test_files/a_file +1 -0
  55. data/lib/siba/test_files/files_and_dirs/.hidden +1 -0
  56. data/lib/siba/test_files/files_and_dirs/.hidden_dir/file10 +1 -0
  57. data/lib/siba/test_files/files_and_dirs/File With Spaces +1 -0
  58. data/lib/siba/test_files/files_and_dirs/dir1/file10 +1 -0
  59. data/lib/siba/test_files/files_and_dirs/dir1/sub-dir/file111.txt +1 -0
  60. data/lib/siba/test_files/files_and_dirs/file1 +1 -0
  61. data/lib/siba/test_files/files_and_dirs/file2.txt +1 -0
  62. data/lib/siba/tmp_dir.rb +94 -0
  63. data/lib/siba/version.rb +5 -0
  64. data/scaffolds/archive.rb +26 -0
  65. data/scaffolds/destination.rb +20 -0
  66. data/scaffolds/encryption.rb +26 -0
  67. data/scaffolds/project/.gitignore +5 -0
  68. data/scaffolds/project/Gemfile +4 -0
  69. data/scaffolds/project/Guardfile +9 -0
  70. data/scaffolds/project/LICENSE +22 -0
  71. data/scaffolds/project/README.md +33 -0
  72. data/scaffolds/project/Rakefile +28 -0
  73. data/scaffolds/project/lib/siba-c6y-demo.rb +11 -0
  74. data/scaffolds/project/lib/siba-c6y-demo/options.yml +2 -0
  75. data/scaffolds/project/lib/siba-c6y-demo/version.rb +9 -0
  76. data/scaffolds/project/siba-c6y-demo.gemspec +26 -0
  77. data/scaffolds/project/test/helper/require_integration.rb +5 -0
  78. data/scaffolds/project/test/helper/require_unit.rb +4 -0
  79. data/scaffolds/project/test/integration/i9n_init.rb +35 -0
  80. data/scaffolds/project/test/unit/test_init.rb +43 -0
  81. data/scaffolds/project/test/unit/yml/valid.yml +8 -0
  82. data/scaffolds/shared/examples.rb +47 -0
  83. data/scaffolds/shared/init_example.rb +13 -0
  84. data/scaffolds/source.rb +25 -0
  85. data/siba.gemspec +30 -0
  86. data/test/helper/require_integration.rb +4 -0
  87. data/test/helper/require_unit.rb +4 -0
  88. data/test/integration/helpers/i9n_file_helper.rb +50 -0
  89. data/test/integration/i9n_backup.rb +53 -0
  90. data/test/integration/i9n_console.rb +16 -0
  91. data/test/integration/i9n_generator.rb +29 -0
  92. data/test/integration/i9n_options_backup.rb +22 -0
  93. data/test/integration/i9n_scaffold.rb +27 -0
  94. data/test/integration/i9n_siba_file.rb +30 -0
  95. data/test/integration/i9n_test_unicode_files.rb +40 -0
  96. data/test/integration/i9n_tmp_dir.rb +44 -0
  97. data/test/integration/plugins/archive/tar/i9n_archive.rb +18 -0
  98. data/test/integration/plugins/destination/dir/i9n_dest_dir.rb +52 -0
  99. data/test/integration/plugins/encryption/gpg/i9n_encryption.rb +87 -0
  100. data/test/integration/plugins/i9n_installed_plugins.rb +13 -0
  101. data/test/integration/plugins/source/files/i9n_files.rb +146 -0
  102. data/test/integration/tasks/i9n_siba_tasks.rb +30 -0
  103. data/test/integration/yml/valid.yml +16 -0
  104. data/test/unit/helpers/test_encoding_helper.rb +17 -0
  105. data/test/unit/helpers/test_gem_helper.rb +17 -0
  106. data/test/unit/helpers/test_security_helper.rb +21 -0
  107. data/test/unit/helpers/test_string_helper.rb +35 -0
  108. data/test/unit/plugins/archive/tar/test_archive.rb +41 -0
  109. data/test/unit/plugins/archive/tar/test_init.rb +36 -0
  110. data/test/unit/plugins/archive/tar/yml/archive/check_installed.yml +2 -0
  111. data/test/unit/plugins/archive/tar/yml/init/default_compression.yml +1 -0
  112. data/test/unit/plugins/archive/tar/yml/init/invalid_compression.yml +2 -0
  113. data/test/unit/plugins/archive/tar/yml/init/valid.yml +2 -0
  114. data/test/unit/plugins/destination/dir/test_dest_dir.rb +41 -0
  115. data/test/unit/plugins/destination/dir/test_init.rb +36 -0
  116. data/test/unit/plugins/destination/dir/yml/init/valid.yml +2 -0
  117. data/test/unit/plugins/encryption/gpg/test_encryption.rb +70 -0
  118. data/test/unit/plugins/encryption/gpg/test_init.rb +47 -0
  119. data/test/unit/plugins/source/files/test_files.rb +44 -0
  120. data/test/unit/plugins/source/files/test_init.rb +48 -0
  121. data/test/unit/plugins/source/files/test_path_match.rb +140 -0
  122. data/test/unit/plugins/source/files/yml/ignore_list.yml +8 -0
  123. data/test/unit/plugins/source/files/yml/ignore_not_array.yml +5 -0
  124. data/test/unit/plugins/source/files/yml/include_not_array.yml +3 -0
  125. data/test/unit/plugins/source/files/yml/include_subdirs_false.yml +6 -0
  126. data/test/unit/plugins/source/files/yml/include_subdirs_missing.yml +5 -0
  127. data/test/unit/plugins/source/files/yml/no_ignore.yml +4 -0
  128. data/test/unit/plugins/source/files/yml/no_include.yml +1 -0
  129. data/test/unit/plugins/source/files/yml/valid.yml +9 -0
  130. data/test/unit/plugins/test_installed_plugins.rb +32 -0
  131. data/test/unit/plugins/test_plugin_loader.rb +27 -0
  132. data/test/unit/plugins/test_plugins.rb +44 -0
  133. data/test/unit/tasks/test_siba_task.rb +30 -0
  134. data/test/unit/tasks/test_siba_tasks.rb +84 -0
  135. data/test/unit/tasks/yml/task/invalid.yml +4 -0
  136. data/test/unit/tasks/yml/task/valid.yml +7 -0
  137. data/test/unit/test_backup.rb +18 -0
  138. data/test/unit/test_console.rb +166 -0
  139. data/test/unit/test_generator.rb +21 -0
  140. data/test/unit/test_globals.rb +34 -0
  141. data/test/unit/test_log_message.rb +26 -0
  142. data/test/unit/test_logger_plug.rb +49 -0
  143. data/test/unit/test_options_backup.rb +21 -0
  144. data/test/unit/test_options_loader.rb +72 -0
  145. data/test/unit/test_password_strength.rb +76 -0
  146. data/test/unit/test_restore.rb +18 -0
  147. data/test/unit/test_scaffold.rb +26 -0
  148. data/test/unit/test_siba_check.rb +118 -0
  149. data/test/unit/test_siba_logger.rb +174 -0
  150. data/test/unit/test_tmp_dir.rb +21 -0
  151. data/test/unit/yml/options_loader/array.yml +2 -0
  152. data/test/unit/yml/options_loader/empty.yml +0 -0
  153. data/test/unit/yml/options_loader/invalid.yml +4 -0
  154. data/test/unit/yml/options_loader/string.yml +1 -0
  155. data/test/unit/yml/options_loader/utf8_with_bom.yml +2 -0
  156. data/test/unit/yml/options_loader/valid.yml +12 -0
  157. data/test/unit/yml/siba_options_backup.yml +20 -0
  158. data/test/unit/yml/valid.yml +18 -0
  159. 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