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,77 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba::Destination
|
|
4
|
+
module Dir
|
|
5
|
+
class DestDir
|
|
6
|
+
include Siba::FilePlug
|
|
7
|
+
include Siba::LoggerPlug
|
|
8
|
+
attr_accessor :dir
|
|
9
|
+
|
|
10
|
+
def initialize(dir)
|
|
11
|
+
@dir = siba_file.file_expand_path dir
|
|
12
|
+
test_dir_access
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def copy_backup_to_dest(path_to_backup)
|
|
16
|
+
siba_file.run_this "copy backup to dest" do
|
|
17
|
+
logger.info "Copying backup to destination directory: #{dir}"
|
|
18
|
+
unless siba_file.file_file? path_to_backup
|
|
19
|
+
raise Siba::Error, "Backup file '#{path_to_backup}' does not exist"
|
|
20
|
+
end
|
|
21
|
+
unless siba_file.file_directory? dir
|
|
22
|
+
raise Siba::Error, "Destination directory '#{dir}' does not exist"
|
|
23
|
+
end
|
|
24
|
+
siba_file.file_utils_cp(path_to_backup, dir)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def restore_backup_to_dir(backup_name, to_dir)
|
|
29
|
+
siba_file.run_this do
|
|
30
|
+
logger.info "Copying backup from destination directory: #{dir}"
|
|
31
|
+
path_to_backup = File.join dir, backup_name
|
|
32
|
+
unless siba_file.file_file? path_to_backup
|
|
33
|
+
raise Siba::Error, "Can not find backup #{path_to_backup}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
siba_file.file_utils_cp path_to_backup, to_dir
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_dir_access
|
|
41
|
+
siba_file.run_this "test dir access" do
|
|
42
|
+
# create dest dir
|
|
43
|
+
begin
|
|
44
|
+
siba_file.file_utils_mkpath dir unless siba_file.file_directory? dir
|
|
45
|
+
rescue Exception
|
|
46
|
+
logger.error "Failed to create destination dir '#{dir}'."
|
|
47
|
+
raise
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# copy a test file to dest dir
|
|
51
|
+
begin
|
|
52
|
+
test_file = Siba::TestFiles.prepare_test_file "destination_dir", dir
|
|
53
|
+
raise "Can not find the test file." unless siba_file.file_file? test_file
|
|
54
|
+
siba_file.file_utils_remove_entry_secure test_file
|
|
55
|
+
rescue Exception
|
|
56
|
+
logger.error "Could not write to destination dir '#{dir}'"
|
|
57
|
+
raise
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
logger.debug "Access to destination directory is verified"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Returns an array of two-element arrays: [file_name, mtime]
|
|
65
|
+
def get_backups_list(backup_name)
|
|
66
|
+
siba_file.run_this do
|
|
67
|
+
Siba::FileHelper.entries(dir).select do |f|
|
|
68
|
+
f =~ /^#{backup_name}/
|
|
69
|
+
end.map do |f|
|
|
70
|
+
mtime = siba_file.file_mtime File.join dir, f
|
|
71
|
+
[f, mtime]
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'siba/plugins/destination/dir/dest_dir'
|
|
4
|
+
|
|
5
|
+
module Siba::Destination
|
|
6
|
+
module Dir
|
|
7
|
+
class Init
|
|
8
|
+
attr_accessor :dest_dir
|
|
9
|
+
|
|
10
|
+
def initialize(options)
|
|
11
|
+
dir = Siba::SibaCheck.options_string options, "dir"
|
|
12
|
+
@dest_dir = Siba::Destination::Dir::DestDir.new dir
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def backup(path_to_backup_file)
|
|
16
|
+
@dest_dir.copy_backup_to_dest path_to_backup_file
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Put backup file into dir
|
|
20
|
+
def restore(backup_name, dir)
|
|
21
|
+
@dest_dir.restore_backup_to_dir backup_name, dir
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns an array of two-element arrays:
|
|
25
|
+
# [backup_file_name, modification_time]
|
|
26
|
+
def get_backups_list(backup_name)
|
|
27
|
+
@dest_dir.get_backups_list backup_name
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba::Encryption
|
|
4
|
+
module Gpg
|
|
5
|
+
class Encryption
|
|
6
|
+
include Siba::LoggerPlug
|
|
7
|
+
include Siba::FilePlug
|
|
8
|
+
|
|
9
|
+
DEFAULT_CIPHER = "AES256"
|
|
10
|
+
|
|
11
|
+
attr_accessor :passphrase, :cipher
|
|
12
|
+
|
|
13
|
+
def initialize(passphrase, cipher=DEFAULT_CIPHER)
|
|
14
|
+
@passphrase = passphrase
|
|
15
|
+
@cipher = Encryption.check_cipher cipher
|
|
16
|
+
check_password_strength
|
|
17
|
+
test_encryption
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def encrypt(path_to_archive)
|
|
21
|
+
path_to_encrypted_backup = "#{path_to_archive}.gpg"
|
|
22
|
+
siba_file.run_this("encrypt") do
|
|
23
|
+
if siba_file.file_file? path_to_encrypted_backup
|
|
24
|
+
raise Siba::Error, "Encrypted file #{path_to_encrypted_backup} already exists"
|
|
25
|
+
end
|
|
26
|
+
passphare_for_command = passphrase.gsub('"','\\"')
|
|
27
|
+
gpg_homedir = Siba::TestFiles.mkdir_in_tmp_dir "gpg-homedir"
|
|
28
|
+
command_without_password = %(gpg -c -q --batch --homedir="#{gpg_homedir}" --no-options --cipher-algo=#{cipher} --passphrase="****" --no-use-agent "#{path_to_archive}")
|
|
29
|
+
command = command_without_password.gsub "****", passphare_for_command
|
|
30
|
+
siba_file.run_shell command, "failed to encrypt: #{command_without_password}"
|
|
31
|
+
unless siba_file.file_file? path_to_encrypted_backup
|
|
32
|
+
raise siba::error, "failed to find encrypted backup file: #{command_without_password}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
path_to_encrypted_backup
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def decrypt(path_to_encrypted_file, path_to_decrypted_file=nil)
|
|
39
|
+
path_to_decrypted_file = path_to_encrypted_file.gsub /\.gpg$/, "" if path_to_decrypted_file.nil?
|
|
40
|
+
siba_file.run_this("decrypt") do
|
|
41
|
+
if siba_file.file_file? path_to_decrypted_file
|
|
42
|
+
raise Siba::Error, "Decrypted file #{path_to_decrypted_file} already exists"
|
|
43
|
+
end
|
|
44
|
+
passphare_for_command = passphrase.gsub('"','\\"')
|
|
45
|
+
gpg_homedir = Siba::TestFiles.mkdir_in_tmp_dir "gpg-homedir"
|
|
46
|
+
command_without_password = %(gpg -d -q --batch --homedir="#{gpg_homedir}" --no-options --passphrase="****" -o "#{path_to_decrypted_file}" --no-use-agent "#{path_to_encrypted_file}")
|
|
47
|
+
command = command_without_password.gsub "****", passphare_for_command
|
|
48
|
+
siba_file.run_shell command, "failed to decrypt: #{command_without_password}"
|
|
49
|
+
unless siba_file.file_file? path_to_decrypted_file
|
|
50
|
+
raise siba::error, "failed to find decrypted backup file: #{command_without_password}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
path_to_decrypted_file
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_encryption
|
|
57
|
+
begin
|
|
58
|
+
siba_file.run_this("test_encryption") do
|
|
59
|
+
# encrypt
|
|
60
|
+
path_to_source_file = Siba::TestFiles.prepare_test_file "encryption-gpg"
|
|
61
|
+
path_to_encrypted_file = encrypt path_to_source_file
|
|
62
|
+
raise unless path_to_encrypted_file == "#{path_to_source_file}.gpg"
|
|
63
|
+
raise unless siba_file.file_file? path_to_encrypted_file
|
|
64
|
+
raise if siba_file.file_utils_compare_file path_to_source_file, path_to_encrypted_file
|
|
65
|
+
|
|
66
|
+
# decrypt
|
|
67
|
+
path_to_output_file = "#{path_to_source_file}.decrypted"
|
|
68
|
+
path_to_decrypted_file = decrypt path_to_encrypted_file, path_to_output_file
|
|
69
|
+
raise unless path_to_decrypted_file == path_to_output_file
|
|
70
|
+
raise unless siba_file.file_utils_compare_file path_to_source_file, path_to_decrypted_file
|
|
71
|
+
|
|
72
|
+
logger.debug "GPG encryption is verified"
|
|
73
|
+
end
|
|
74
|
+
rescue Exception
|
|
75
|
+
logger.error "'gpg' encryption utility does not work correctly. Try reinstalling it."
|
|
76
|
+
raise
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class << self
|
|
81
|
+
include Siba::FilePlug
|
|
82
|
+
include Siba::LoggerPlug
|
|
83
|
+
|
|
84
|
+
def check_cipher(cipher)
|
|
85
|
+
siba_file.run_this("check_cipher") do
|
|
86
|
+
supported_ciphers = nil
|
|
87
|
+
begin
|
|
88
|
+
supported_ciphers = Encryption.get_cipher_names
|
|
89
|
+
rescue Exception
|
|
90
|
+
logger.error "'gpg' encryption utility is not found. Please install it."
|
|
91
|
+
raise
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
supported_ciphers_msg = "Please use one of the following: #{supported_ciphers.join(', ')}."
|
|
95
|
+
if cipher.nil?
|
|
96
|
+
cipher = Encryption::DEFAULT_CIPHER
|
|
97
|
+
raise Siba::CheckError, "Default cipher '#{cipher}' is not supported.
|
|
98
|
+
#{supported_ciphers_msg}" unless supported_ciphers.include?(cipher)
|
|
99
|
+
else
|
|
100
|
+
cipher.upcase!
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
raise Siba::CheckError, "'#{cipher}' cipher is not supported.
|
|
104
|
+
#{supported_ciphers_msg}" unless supported_ciphers.include?(cipher)
|
|
105
|
+
end
|
|
106
|
+
cipher
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def get_cipher_names
|
|
110
|
+
output = siba_file.run_shell "gpg --version"
|
|
111
|
+
cipher_names = parse_cipher_names output
|
|
112
|
+
raise Siba::Error, "Failed to get the list of supported ciphers" if cipher_names.empty?
|
|
113
|
+
cipher_names
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def parse_cipher_names(version)
|
|
117
|
+
scan = version.scan /Cipher:(.*?)\n\w+:/m
|
|
118
|
+
scan = version.scan /Cipher:(.*)/m if scan.size == 0
|
|
119
|
+
if scan.size == 0 || !scan[0].is_a?(Array) || scan[0].size == 0 || !scan[0][0].is_a?(String)
|
|
120
|
+
raise "Failed to parse gpg version information"
|
|
121
|
+
end
|
|
122
|
+
scan = scan[0][0]
|
|
123
|
+
scan.gsub!(/ |\n/, "")
|
|
124
|
+
scan.split(",").each {|a| a.upcase!}
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def check_password_strength
|
|
131
|
+
seconds_to_crack = Siba::PasswordStrength.seconds_to_crack(@passphrase)
|
|
132
|
+
if Siba::PasswordStrength.is_weak? seconds_to_crack
|
|
133
|
+
timespan_to_guess = Siba::PasswordStrength.seconds_to_timespan seconds_to_crack
|
|
134
|
+
guess_estimation_message = "It will take #{timespan_to_guess} to guess it."
|
|
135
|
+
logger.warn "Your encryption password is weak. #{guess_estimation_message}"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'siba/helpers/password_strength'
|
|
4
|
+
require 'siba/plugins/encryption/gpg/encryption'
|
|
5
|
+
|
|
6
|
+
module Siba::Encryption
|
|
7
|
+
module Gpg
|
|
8
|
+
class Init
|
|
9
|
+
include Siba::LoggerPlug
|
|
10
|
+
include Siba::FilePlug
|
|
11
|
+
attr_accessor :encryption
|
|
12
|
+
|
|
13
|
+
def initialize(options)
|
|
14
|
+
passphrase = Siba::SibaCheck.options_string(options, "passphrase")
|
|
15
|
+
cipher = Siba::SibaCheck.options_string(options, "cipher", true)
|
|
16
|
+
@encryption = Siba::Encryption::Gpg::Encryption.new passphrase, cipher
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Encrypt backup archive file (path_to_archive) and put it to dest_dir.
|
|
20
|
+
# Return the name of encrypted file. It must begin with archive name
|
|
21
|
+
# and its ending must always be the same.
|
|
22
|
+
def backup(path_to_archive, dest_dir)
|
|
23
|
+
logger.info "Encrypting backup with 'gpg', cipher: '#{encryption.cipher}'"
|
|
24
|
+
path_to_encrypted_file = encryption.encrypt path_to_archive
|
|
25
|
+
|
|
26
|
+
# move encrypted file to dest_dir
|
|
27
|
+
file_name = File.basename path_to_encrypted_file
|
|
28
|
+
dest_file_path = File.join dest_dir, file_name
|
|
29
|
+
siba_file.file_utils_mv path_to_encrypted_file, dest_file_path
|
|
30
|
+
file_name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Decrypt backup file (path_to_backup) to_dir.
|
|
34
|
+
# Return the name of decrypted file.
|
|
35
|
+
def restore(path_to_backup, to_dir)
|
|
36
|
+
logger.info "Decrypting backup with 'gpg', cipher: '#{encryption.cipher}'"
|
|
37
|
+
decrypted_file_name = File.basename path_to_backup
|
|
38
|
+
decrypted_file_name.gsub! /\.gpg$/, ""
|
|
39
|
+
path_to_decrypted_file = File.join to_dir, decrypted_file_name
|
|
40
|
+
encryption.decrypt path_to_backup, path_to_decrypted_file
|
|
41
|
+
decrypted_file_name
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class InstalledPlugins
|
|
5
|
+
GEM_PREFIX = "siba-"
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
include Siba::FilePlug
|
|
9
|
+
|
|
10
|
+
def installed?(category, type)
|
|
11
|
+
types = all_installed[category]
|
|
12
|
+
return false if types.nil?
|
|
13
|
+
types.include? type
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def all_installed
|
|
17
|
+
@installed ||= find_installed
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def plugin_path(category, type)
|
|
21
|
+
unless installed? category, type
|
|
22
|
+
raise Siba::Error, "Plugin #{plugin_category_and_type(category, type)} is not installed"
|
|
23
|
+
end
|
|
24
|
+
siba_file.run_this do
|
|
25
|
+
path = type_dir category, type
|
|
26
|
+
unless siba_file.file_directory? path
|
|
27
|
+
path = Siba::GemHelper.gem_path gem_name(category, type)
|
|
28
|
+
path = File.join path, "lib", gem_name(category, type)
|
|
29
|
+
end
|
|
30
|
+
unless siba_file.file_directory? path
|
|
31
|
+
raise Siba::Error, "Failed to get path to plugin #{plugin_category_and_type(category, type)}"
|
|
32
|
+
end
|
|
33
|
+
path
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def category_dir(category)
|
|
38
|
+
File.expand_path "../#{category}/", __FILE__
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def type_dir(category, type)
|
|
42
|
+
File.join category_dir(category), type
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def gem_name(category, type)
|
|
46
|
+
"#{GEM_PREFIX}#{category}-#{type}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def plugin_category_and_type(category, type)
|
|
50
|
+
"#{category}#{type.nil? ? "" : '-' + type}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def find_installed
|
|
56
|
+
installed = {}
|
|
57
|
+
Siba::GemHelper.all_local_gems.map{|a| a.name}.each do |item|
|
|
58
|
+
Siba::Plugins::CATEGORIES.each do |category|
|
|
59
|
+
installed[category] ||= []
|
|
60
|
+
gem_prefix_full = /^#{GEM_PREFIX}#{category}-/
|
|
61
|
+
installed[category] << item.gsub(gem_prefix_full, '') if item =~ /#{gem_prefix_full}.*$/
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
Siba::Plugins::CATEGORIES.each do |category|
|
|
66
|
+
installed[category] += Dir.glob(File.join(category_dir(category),"*")).select { |entry|
|
|
67
|
+
File.directory? entry
|
|
68
|
+
}.select{|dir| File.file?(File.join(dir,"init.rb")) }
|
|
69
|
+
.map{|directory| File.basename(directory)}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
installed
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class PluginLoader
|
|
5
|
+
include Siba::LoggerPlug
|
|
6
|
+
include Siba::FilePlug
|
|
7
|
+
|
|
8
|
+
InitClassName = "Init"
|
|
9
|
+
|
|
10
|
+
def self.loader
|
|
11
|
+
@loader ||= PluginLoader.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load(category, type, options)
|
|
15
|
+
unless Siba::Plugins.valid_category? category
|
|
16
|
+
raise PluginLoadError, "Incorrect plugin category '#{category}'. Available plugin categories are: #{Siba::Plugins.categories_str}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
raise PluginLoadError, "Options data is incorrect for #{plugin_category_and_type} plugin." unless options.is_a? Hash
|
|
20
|
+
|
|
21
|
+
@category=category
|
|
22
|
+
@type=type
|
|
23
|
+
@options = options
|
|
24
|
+
logger.debug "Loading #{plugin_category_and_type} plugin"
|
|
25
|
+
|
|
26
|
+
require_plugin
|
|
27
|
+
plugin_module = get_plugin_module
|
|
28
|
+
plugin_type_module = get_plugin_type_module plugin_module
|
|
29
|
+
init_class = get_plugin_init_class plugin_type_module
|
|
30
|
+
init_plugin(init_class)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
attr_accessor :category, :type, :options
|
|
35
|
+
|
|
36
|
+
def require_plugin
|
|
37
|
+
path_to_init_file = File.join(plugin_dir, "init.rb")
|
|
38
|
+
if File.exists?(path_to_init_file)
|
|
39
|
+
require path_to_init_file
|
|
40
|
+
else
|
|
41
|
+
gem_name = Siba::InstalledPlugins.gem_name category, type
|
|
42
|
+
begin
|
|
43
|
+
Gem::Specification.find_by_name(gem_name)
|
|
44
|
+
rescue Gem::LoadError
|
|
45
|
+
raise PluginLoadError, "Unknown type '#{type}' for '#{category}' plugin. #{available_types_msg}"
|
|
46
|
+
end
|
|
47
|
+
require gem_name
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def get_plugin_module
|
|
52
|
+
plugin_module_name = "#{category.capitalize}"
|
|
53
|
+
Siba.const_get(plugin_module_name)
|
|
54
|
+
rescue Exception
|
|
55
|
+
raise PluginLoadError, "Failed to load #{plugin_category_and_type} plugin: module 'Siba::#{plugin_module_name}' is undefined."
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_plugin_type_module(plugin_module)
|
|
59
|
+
plugin_type_module_name = StringHelper.camelize type
|
|
60
|
+
plugin_module.const_get(plugin_type_module_name)
|
|
61
|
+
rescue
|
|
62
|
+
raise PluginLoadError, "Failed to load #{plugin_category_and_type} plugin: module 'Siba::#{category.capitalize}::#{plugin_type_module_name}' is undefined."
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def get_plugin_init_class(plugin_type_module)
|
|
66
|
+
plugin_type_module.const_get InitClassName
|
|
67
|
+
rescue Exception => e
|
|
68
|
+
raise PluginLoadError, "#{InitClassName} class is undefined for #{plugin_category_and_type} plugin."
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def init_plugin(plugin_init_class)
|
|
72
|
+
plugin_init_class.new options
|
|
73
|
+
rescue ArgumentError
|
|
74
|
+
logger.error "Failed to load #{plugin_category_and_type} plugin: 'initialize' method is not defined or has wrong agruments."
|
|
75
|
+
raise
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def plugin_category_and_type
|
|
79
|
+
Siba::InstalledPlugins.plugin_category_and_type category, type
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def plugins_root_dir
|
|
83
|
+
Siba::InstalledPlugins.category_dir category
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def plugin_dir
|
|
87
|
+
Siba::InstalledPlugins.type_dir category, type
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def available_types_msg
|
|
91
|
+
return "No #{category} plugins are installed." if find_all_installed.empty?
|
|
92
|
+
return "Available types are: #{find_all_installed.join(", ")}." if find_all_installed.size > 1
|
|
93
|
+
"Available type is '#{find_all_installed.join(", ")}'."
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def find_all_installed
|
|
97
|
+
Siba::InstalledPlugins.all_installed[category]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|