backup 3.0.27 → 3.1.0
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/LICENSE.md +1 -1
- data/README.md +139 -386
- data/bin/backup +1 -7
- data/lib/backup.rb +3 -9
- data/lib/backup/archive.rb +26 -20
- data/lib/backup/cleaner.rb +2 -2
- data/lib/backup/cli.rb +366 -0
- data/lib/backup/compressor/base.rb +2 -2
- data/lib/backup/compressor/gzip.rb +35 -1
- data/lib/backup/config.rb +1 -2
- data/lib/backup/database/base.rb +2 -2
- data/lib/backup/database/mongodb.rb +3 -3
- data/lib/backup/database/mysql.rb +3 -2
- data/lib/backup/database/postgresql.rb +3 -2
- data/lib/backup/database/riak.rb +18 -5
- data/lib/backup/dependency.rb +144 -93
- data/lib/backup/encryptor/base.rb +2 -2
- data/lib/backup/logger.rb +108 -110
- data/lib/backup/logger/console.rb +51 -0
- data/lib/backup/logger/logfile.rb +113 -0
- data/lib/backup/logger/syslog.rb +116 -0
- data/lib/backup/model.rb +67 -65
- data/lib/backup/notifier/base.rb +1 -1
- data/lib/backup/notifier/hipchat.rb +1 -1
- data/lib/backup/notifier/mail.rb +1 -1
- data/lib/backup/notifier/pushover.rb +6 -3
- data/lib/backup/packager.rb +4 -4
- data/lib/backup/pipeline.rb +17 -3
- data/lib/backup/splitter.rb +2 -2
- data/lib/backup/storage/base.rb +2 -2
- data/lib/backup/storage/cloudfiles.rb +2 -2
- data/lib/backup/storage/dropbox.rb +4 -4
- data/lib/backup/storage/ftp.rb +2 -2
- data/lib/backup/storage/local.rb +2 -2
- data/lib/backup/storage/ninefold.rb +2 -2
- data/lib/backup/storage/rsync.rb +3 -3
- data/lib/backup/storage/s3.rb +2 -2
- data/lib/backup/storage/scp.rb +2 -6
- data/lib/backup/storage/sftp.rb +2 -5
- data/lib/backup/syncer/base.rb +1 -1
- data/lib/backup/syncer/cloud/base.rb +15 -8
- data/lib/backup/syncer/rsync/local.rb +1 -1
- data/lib/backup/syncer/rsync/pull.rb +1 -1
- data/lib/backup/syncer/rsync/push.rb +1 -1
- data/lib/backup/utilities.rb +211 -0
- data/lib/backup/version.rb +1 -1
- data/templates/cli/{utility/archive → archive} +4 -8
- data/templates/cli/{utility/compressor → compressor}/bzip2 +0 -0
- data/templates/cli/{utility/compressor → compressor}/custom +0 -0
- data/templates/cli/{utility/compressor → compressor}/gzip +0 -0
- data/templates/cli/{utility/compressor → compressor}/lzma +0 -0
- data/templates/cli/{utility/compressor → compressor}/pbzip2 +0 -0
- data/templates/cli/config +68 -0
- data/templates/cli/{utility/database → database}/mongodb +1 -1
- data/templates/cli/{utility/database → database}/mysql +1 -1
- data/templates/cli/{utility/database → database}/postgresql +1 -1
- data/templates/cli/{utility/database → database}/redis +0 -0
- data/templates/cli/database/riak +20 -0
- data/templates/cli/{utility/encryptor → encryptor}/gpg +0 -0
- data/templates/cli/{utility/encryptor → encryptor}/openssl +0 -0
- data/templates/cli/{utility/model.erb → model.erb} +4 -4
- data/templates/cli/{utility/notifier → notifier}/campfire +0 -0
- data/templates/cli/{utility/notifier → notifier}/hipchat +0 -0
- data/templates/cli/{utility/notifier → notifier}/mail +0 -0
- data/templates/cli/{utility/notifier → notifier}/prowl +0 -0
- data/templates/cli/{utility/notifier → notifier}/pushover +0 -0
- data/templates/cli/{utility/notifier → notifier}/twitter +0 -0
- data/templates/cli/{utility/splitter → splitter} +0 -0
- data/templates/cli/{utility/storage → storage}/cloud_files +0 -0
- data/templates/cli/{utility/storage → storage}/dropbox +0 -0
- data/templates/cli/{utility/storage → storage}/ftp +0 -0
- data/templates/cli/{utility/storage → storage}/local +0 -0
- data/templates/cli/{utility/storage → storage}/ninefold +0 -0
- data/templates/cli/{utility/storage → storage}/rsync +0 -0
- data/templates/cli/{utility/storage → storage}/s3 +0 -0
- data/templates/cli/{utility/storage → storage}/scp +0 -0
- data/templates/cli/{utility/storage → storage}/sftp +0 -0
- data/templates/cli/{utility/syncer → syncer}/cloud_files +0 -0
- data/templates/cli/{utility/syncer → syncer}/rsync_local +0 -0
- data/templates/cli/{utility/syncer → syncer}/rsync_pull +0 -0
- data/templates/cli/{utility/syncer → syncer}/rsync_push +0 -0
- data/templates/cli/{utility/syncer → syncer}/s3 +0 -0
- metadata +55 -131
- data/.gitignore +0 -8
- data/.travis.yml +0 -10
- data/Gemfile +0 -28
- data/Guardfile +0 -23
- data/backup.gemspec +0 -32
- data/lib/backup/cli/helpers.rb +0 -93
- data/lib/backup/cli/utility.rb +0 -255
- data/spec-live/.gitignore +0 -6
- data/spec-live/README +0 -7
- data/spec-live/backups/config.rb +0 -83
- data/spec-live/backups/config.yml.template +0 -46
- data/spec-live/backups/models.rb +0 -184
- data/spec-live/compressor/custom_spec.rb +0 -30
- data/spec-live/compressor/gzip_spec.rb +0 -30
- data/spec-live/encryptor/gpg_keys.rb +0 -239
- data/spec-live/encryptor/gpg_spec.rb +0 -287
- data/spec-live/notifier/mail_spec.rb +0 -121
- data/spec-live/spec_helper.rb +0 -151
- data/spec-live/storage/dropbox_spec.rb +0 -151
- data/spec-live/storage/local_spec.rb +0 -83
- data/spec-live/storage/scp_spec.rb +0 -193
- data/spec-live/syncer/cloud/s3_spec.rb +0 -124
- data/spec/archive_spec.rb +0 -335
- data/spec/cleaner_spec.rb +0 -312
- data/spec/cli/helpers_spec.rb +0 -301
- data/spec/cli/utility_spec.rb +0 -411
- data/spec/compressor/base_spec.rb +0 -52
- data/spec/compressor/bzip2_spec.rb +0 -217
- data/spec/compressor/custom_spec.rb +0 -106
- data/spec/compressor/gzip_spec.rb +0 -217
- data/spec/compressor/lzma_spec.rb +0 -123
- data/spec/compressor/pbzip2_spec.rb +0 -165
- data/spec/config_spec.rb +0 -321
- data/spec/configuration/helpers_spec.rb +0 -247
- data/spec/configuration/store_spec.rb +0 -39
- data/spec/configuration_spec.rb +0 -62
- data/spec/database/base_spec.rb +0 -63
- data/spec/database/mongodb_spec.rb +0 -510
- data/spec/database/mysql_spec.rb +0 -411
- data/spec/database/postgresql_spec.rb +0 -353
- data/spec/database/redis_spec.rb +0 -334
- data/spec/database/riak_spec.rb +0 -176
- data/spec/dependency_spec.rb +0 -51
- data/spec/encryptor/base_spec.rb +0 -40
- data/spec/encryptor/gpg_spec.rb +0 -909
- data/spec/encryptor/open_ssl_spec.rb +0 -148
- data/spec/errors_spec.rb +0 -306
- data/spec/logger_spec.rb +0 -367
- data/spec/model_spec.rb +0 -666
- data/spec/notifier/base_spec.rb +0 -104
- data/spec/notifier/campfire_spec.rb +0 -217
- data/spec/notifier/hipchat_spec.rb +0 -211
- data/spec/notifier/mail_spec.rb +0 -316
- data/spec/notifier/prowl_spec.rb +0 -138
- data/spec/notifier/pushover_spec.rb +0 -123
- data/spec/notifier/twitter_spec.rb +0 -153
- data/spec/package_spec.rb +0 -61
- data/spec/packager_spec.rb +0 -213
- data/spec/pipeline_spec.rb +0 -259
- data/spec/spec_helper.rb +0 -60
- data/spec/splitter_spec.rb +0 -120
- data/spec/storage/base_spec.rb +0 -166
- data/spec/storage/cloudfiles_spec.rb +0 -254
- data/spec/storage/cycler_spec.rb +0 -247
- data/spec/storage/dropbox_spec.rb +0 -480
- data/spec/storage/ftp_spec.rb +0 -271
- data/spec/storage/local_spec.rb +0 -259
- data/spec/storage/ninefold_spec.rb +0 -343
- data/spec/storage/rsync_spec.rb +0 -362
- data/spec/storage/s3_spec.rb +0 -245
- data/spec/storage/scp_spec.rb +0 -233
- data/spec/storage/sftp_spec.rb +0 -244
- data/spec/syncer/base_spec.rb +0 -109
- data/spec/syncer/cloud/base_spec.rb +0 -515
- data/spec/syncer/cloud/cloud_files_spec.rb +0 -181
- data/spec/syncer/cloud/s3_spec.rb +0 -174
- data/spec/syncer/rsync/base_spec.rb +0 -98
- data/spec/syncer/rsync/local_spec.rb +0 -149
- data/spec/syncer/rsync/pull_spec.rb +0 -98
- data/spec/syncer/rsync/push_spec.rb +0 -333
- data/spec/version_spec.rb +0 -21
- data/templates/cli/utility/config +0 -32
- data/templates/cli/utility/database/riak +0 -11
data/bin/backup
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
|
-
# Load the Backup core library
|
|
5
4
|
require File.expand_path("../../lib/backup", __FILE__)
|
|
6
|
-
|
|
7
|
-
# Load the Backup command line interface utility
|
|
8
|
-
require File.expand_path("../../lib/backup/cli/utility", __FILE__)
|
|
9
|
-
|
|
10
|
-
# Initialize the Backup command line utility
|
|
11
|
-
Backup::CLI::Utility.start
|
|
5
|
+
Backup::CLI.start
|
data/lib/backup.rb
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
require 'rubygems'
|
|
5
5
|
require 'fileutils'
|
|
6
6
|
require 'tempfile'
|
|
7
|
+
require 'syslog'
|
|
7
8
|
require 'yaml'
|
|
8
9
|
require 'etc'
|
|
9
10
|
|
|
@@ -17,7 +18,6 @@ module Backup
|
|
|
17
18
|
##
|
|
18
19
|
# Backup's internal paths
|
|
19
20
|
LIBRARY_PATH = File.join(File.dirname(__FILE__), 'backup')
|
|
20
|
-
CLI_PATH = File.join(LIBRARY_PATH, 'cli')
|
|
21
21
|
STORAGE_PATH = File.join(LIBRARY_PATH, 'storage')
|
|
22
22
|
DATABASE_PATH = File.join(LIBRARY_PATH, 'database')
|
|
23
23
|
COMPRESSOR_PATH = File.join(LIBRARY_PATH, 'compressor')
|
|
@@ -26,13 +26,6 @@ module Backup
|
|
|
26
26
|
SYNCER_PATH = File.join(LIBRARY_PATH, 'syncer')
|
|
27
27
|
TEMPLATE_PATH = File.expand_path('../../templates', __FILE__)
|
|
28
28
|
|
|
29
|
-
##
|
|
30
|
-
# Autoload Backup CLI files
|
|
31
|
-
module CLI
|
|
32
|
-
autoload :Helpers, File.join(CLI_PATH, 'helpers')
|
|
33
|
-
autoload :Utility, File.join(CLI_PATH, 'utility')
|
|
34
|
-
end
|
|
35
|
-
|
|
36
29
|
##
|
|
37
30
|
# Autoload Backup storage files
|
|
38
31
|
module Storage
|
|
@@ -100,7 +93,6 @@ module Backup
|
|
|
100
93
|
# Autoload notification files
|
|
101
94
|
module Notifier
|
|
102
95
|
autoload :Base, File.join(NOTIFIER_PATH, 'base')
|
|
103
|
-
autoload :Binder, File.join(NOTIFIER_PATH, 'binder')
|
|
104
96
|
autoload :Mail, File.join(NOTIFIER_PATH, 'mail')
|
|
105
97
|
autoload :Twitter, File.join(NOTIFIER_PATH, 'twitter')
|
|
106
98
|
autoload :Campfire, File.join(NOTIFIER_PATH, 'campfire')
|
|
@@ -112,10 +104,12 @@ module Backup
|
|
|
112
104
|
##
|
|
113
105
|
# Require Backup base files
|
|
114
106
|
%w{
|
|
107
|
+
utilities
|
|
115
108
|
archive
|
|
116
109
|
binder
|
|
117
110
|
cleaner
|
|
118
111
|
config
|
|
112
|
+
cli
|
|
119
113
|
configuration
|
|
120
114
|
dependency
|
|
121
115
|
errors
|
data/lib/backup/archive.rb
CHANGED
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
module Backup
|
|
4
4
|
class Archive
|
|
5
|
-
include Backup::
|
|
5
|
+
include Backup::Utilities::Helpers
|
|
6
6
|
|
|
7
7
|
##
|
|
8
8
|
# Stores the name of the archive
|
|
9
|
-
|
|
9
|
+
attr_reader :name
|
|
10
10
|
|
|
11
11
|
##
|
|
12
12
|
# Stores an array of different paths/files to store
|
|
13
|
-
|
|
13
|
+
attr_reader :paths
|
|
14
14
|
|
|
15
15
|
##
|
|
16
16
|
# Stores an array of different paths/files to exclude
|
|
17
|
-
|
|
17
|
+
attr_reader :excludes
|
|
18
18
|
|
|
19
19
|
##
|
|
20
20
|
# String of additional arguments for the `tar` command
|
|
21
|
-
|
|
21
|
+
attr_reader :tar_args
|
|
22
22
|
|
|
23
23
|
##
|
|
24
24
|
# Takes the name of the archive and the configuration block
|
|
@@ -35,16 +35,7 @@ module Backup
|
|
|
35
35
|
##
|
|
36
36
|
# Adds new paths to the @paths instance variable array
|
|
37
37
|
def add(path)
|
|
38
|
-
|
|
39
|
-
if File.exist?(path)
|
|
40
|
-
@paths << path
|
|
41
|
-
else
|
|
42
|
-
Logger.warn Errors::Archive::NotFoundError.new(<<-EOS)
|
|
43
|
-
The following path was not found:
|
|
44
|
-
#{ path }
|
|
45
|
-
This path will be omitted from the '#{ name }' Archive.
|
|
46
|
-
EOS
|
|
47
|
-
end
|
|
38
|
+
@paths << File.expand_path(path)
|
|
48
39
|
end
|
|
49
40
|
|
|
50
41
|
##
|
|
@@ -67,7 +58,7 @@ module Backup
|
|
|
67
58
|
# will be piped through the Compressor command and the file extension
|
|
68
59
|
# will be adjusted to indicate the type of compression used.
|
|
69
60
|
def perform!
|
|
70
|
-
Logger.
|
|
61
|
+
Logger.info "#{ self.class } has started archiving:\n" +
|
|
71
62
|
paths.map {|path| " #{path}" }.join("\n")
|
|
72
63
|
|
|
73
64
|
archive_path = File.join(Config.tmp_path, @model.trigger, 'archives')
|
|
@@ -76,8 +67,11 @@ module Backup
|
|
|
76
67
|
archive_ext = 'tar'
|
|
77
68
|
pipeline = Pipeline.new
|
|
78
69
|
|
|
79
|
-
pipeline
|
|
80
|
-
|
|
70
|
+
pipeline.add(
|
|
71
|
+
"#{ utility(:tar) } #{ tar_arguments } -cPf - " +
|
|
72
|
+
"#{ paths_to_exclude } #{ paths_to_package }",
|
|
73
|
+
tar_success_codes
|
|
74
|
+
)
|
|
81
75
|
|
|
82
76
|
if @model.compressor
|
|
83
77
|
@model.compressor.compress_with do |command, ext|
|
|
@@ -86,10 +80,11 @@ module Backup
|
|
|
86
80
|
end
|
|
87
81
|
end
|
|
88
82
|
|
|
89
|
-
pipeline << "
|
|
83
|
+
pipeline << "#{ utility(:cat) } > " +
|
|
84
|
+
"'#{ File.join(archive_path, "#{name}.#{archive_ext}") }'"
|
|
90
85
|
pipeline.run
|
|
91
86
|
if pipeline.success?
|
|
92
|
-
Logger.
|
|
87
|
+
Logger.info "#{ self.class } Complete!"
|
|
93
88
|
else
|
|
94
89
|
raise Errors::Archive::PipelineError,
|
|
95
90
|
"Failed to Create Backup Archive\n" +
|
|
@@ -113,5 +108,16 @@ module Backup
|
|
|
113
108
|
end
|
|
114
109
|
end
|
|
115
110
|
|
|
111
|
+
##
|
|
112
|
+
# Returns arguments for GNU or BSD tar.
|
|
113
|
+
def tar_arguments
|
|
114
|
+
gnu_tar? ? "--ignore-failed-read #{ tar_args }".strip : tar_args
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# Returns successful GNU or BSD tar exit codes.
|
|
119
|
+
def tar_success_codes
|
|
120
|
+
gnu_tar? ? [0, 1] : [0]
|
|
121
|
+
end
|
|
116
122
|
end
|
|
117
123
|
end
|
data/lib/backup/cleaner.rb
CHANGED
|
@@ -50,7 +50,7 @@ module Backup
|
|
|
50
50
|
##
|
|
51
51
|
# Remove the temporary folder used during packaging
|
|
52
52
|
def remove_packaging(model)
|
|
53
|
-
Logger.
|
|
53
|
+
Logger.info "Cleaning up the temporary files..."
|
|
54
54
|
FileUtils.rm_rf(File.join(Config.tmp_path, model.trigger))
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -58,7 +58,7 @@ module Backup
|
|
|
58
58
|
# Remove the final package files from tmp_path
|
|
59
59
|
# Note: 'force' is used, since a Local Storage may *move* these files.
|
|
60
60
|
def remove_package(package)
|
|
61
|
-
Logger.
|
|
61
|
+
Logger.info "Cleaning up the package files..."
|
|
62
62
|
package.filenames.each do |file|
|
|
63
63
|
FileUtils.rm_f(File.join(Config.tmp_path, file))
|
|
64
64
|
end
|
data/lib/backup/cli.rb
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Build the Backup Command Line Interface using Thor
|
|
5
|
+
module Backup
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
include Thor::Actions
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# [Perform]
|
|
11
|
+
# Performs the backup process. The only required option is the --trigger [-t].
|
|
12
|
+
# If the other options (--config-file, --data-path, --cache-path, --tmp-path) aren't specified
|
|
13
|
+
# they will fallback to the (good) defaults
|
|
14
|
+
#
|
|
15
|
+
# If --root-path is given, it will be used as the base path for our defaults,
|
|
16
|
+
# as well as the base path for any option specified as a relative path.
|
|
17
|
+
# Any option given as an absolute path will be used "as-is".
|
|
18
|
+
desc 'perform', "Performs the backup for the specified trigger(s)."
|
|
19
|
+
long_desc "Performs the backup for the specified trigger(s).\n\n" +
|
|
20
|
+
"You may perform multiple backups by providing multiple triggers, separated by commas.\n\n" +
|
|
21
|
+
"Example:\n\s\s$ backup perform --triggers backup1,backup2,backup3,backup4\n\n" +
|
|
22
|
+
"This will invoke 4 backups, and they will run in the order specified (not asynchronous).\n\n" +
|
|
23
|
+
"\n\n" +
|
|
24
|
+
"--root-path may be an absolute path or relative to the current working directory.\n\n" +
|
|
25
|
+
"To use the current directory, you can use: `--root-path .` (i.e. a period for the argument)"
|
|
26
|
+
|
|
27
|
+
method_option :trigger, :type => :string, :required => true, :aliases => ['-t', '--triggers'],
|
|
28
|
+
:desc => "Triggers to perform. e.g. 'trigger_a,trigger_b'"
|
|
29
|
+
method_option :config_file, :type => :string, :default => '', :aliases => '-c',
|
|
30
|
+
:desc => "Path to your config.rb file. " +
|
|
31
|
+
"Absolute, or relative to --root-path."
|
|
32
|
+
method_option :root_path, :type => :string, :default => '', :aliases => '-r',
|
|
33
|
+
:desc => "Root path to base all relative path on. " +
|
|
34
|
+
"Absolute or relative to current directory (#{Dir.pwd})."
|
|
35
|
+
method_option :data_path, :type => :string, :default => '', :aliases => '-d',
|
|
36
|
+
:desc => "Path to store persisted data (storage 'keep' data). " +
|
|
37
|
+
"Absolute, or relative to --root-path."
|
|
38
|
+
method_option :log_path, :type => :string, :default => '', :aliases => '-l',
|
|
39
|
+
:desc => "Path to store Backup's log file. " +
|
|
40
|
+
"Absolute, or relative to --root-path."
|
|
41
|
+
method_option :cache_path, :type => :string, :default => '',
|
|
42
|
+
:desc => "Path to store Dropbox's cached authorization. " +
|
|
43
|
+
"Absolute, or relative to --root-path."
|
|
44
|
+
method_option :tmp_path, :type => :string, :default => '',
|
|
45
|
+
:desc => "Path to store temporary data during the backup process. " +
|
|
46
|
+
"Absolute, or relative to --root-path."
|
|
47
|
+
# Note that :quiet, :syslog and :logfile are specified as :string types,
|
|
48
|
+
# so the --no-<option> usage will set the value to nil instead of false.
|
|
49
|
+
method_option :quiet, :type => :string, :default => false, :aliases => '-q', :banner => '',
|
|
50
|
+
:desc => "Disable console log output. " +
|
|
51
|
+
"May be force enabled using --no-quiet."
|
|
52
|
+
method_option :syslog, :type => :string, :default => false, :banner => '',
|
|
53
|
+
:desc => "Enable logging to syslog. " +
|
|
54
|
+
"May be forced disabled using --no-syslog."
|
|
55
|
+
method_option :logfile, :type => :string, :default => true, :banner => '',
|
|
56
|
+
:desc => "Enable Backup's log file. " +
|
|
57
|
+
"May be forced disabled using --no-logfile."
|
|
58
|
+
method_option :check, :type => :boolean, :default => false,
|
|
59
|
+
:desc => "Check `config.rb` and all Model configuration for errors or warnings."
|
|
60
|
+
|
|
61
|
+
def perform
|
|
62
|
+
##
|
|
63
|
+
# Prepare to perform requested backup jobs.
|
|
64
|
+
models = nil
|
|
65
|
+
begin
|
|
66
|
+
##
|
|
67
|
+
# Set logger options
|
|
68
|
+
opts = options
|
|
69
|
+
Logger.configure do
|
|
70
|
+
console.quiet = opts[:quiet]
|
|
71
|
+
logfile.enabled = opts[:logfile]
|
|
72
|
+
logfile.log_path = opts[:log_path]
|
|
73
|
+
syslog.enabled = opts[:syslog]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Update Config variables
|
|
78
|
+
# (config_file, root_path, data_path, cache_path, tmp_path)
|
|
79
|
+
Config.update(options)
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# Ensure the :cache_path and :tmp_path are created
|
|
83
|
+
# if they do not yet exist
|
|
84
|
+
[Config.cache_path, Config.tmp_path].each do |path|
|
|
85
|
+
FileUtils.mkdir_p(path)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Load the user's +config.rb+ file (and all their Models).
|
|
90
|
+
# May update Logger options.
|
|
91
|
+
Config.load_config!
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Identify all Models to be run for the given +triggers+.
|
|
95
|
+
triggers = options[:trigger].split(',').map(&:strip)
|
|
96
|
+
models = triggers.map {|trigger|
|
|
97
|
+
Model.find_by_trigger(trigger)
|
|
98
|
+
}.flatten.uniq
|
|
99
|
+
|
|
100
|
+
if models.empty?
|
|
101
|
+
raise Errors::CLIError,
|
|
102
|
+
"No Models found for trigger(s) '#{triggers.join(',')}'."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if options[:check] && Logger.has_warnings?
|
|
106
|
+
raise Errors::CLIError, 'Configuration Check has warnings.'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
##
|
|
110
|
+
# Finalize Logger configuration and begin real-time logging.
|
|
111
|
+
Logger.start!
|
|
112
|
+
|
|
113
|
+
rescue => err
|
|
114
|
+
Logger.error Errors::CLIError.wrap(err)
|
|
115
|
+
Logger.error 'Configuration Check Failed.' if options[:check]
|
|
116
|
+
# Logger configuration will be ignored
|
|
117
|
+
# and messages will be output to the console only.
|
|
118
|
+
Logger.abort!
|
|
119
|
+
exit(1)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
if options[:check]
|
|
123
|
+
Logger.info 'Configuration Check Succeeded.'
|
|
124
|
+
else
|
|
125
|
+
##
|
|
126
|
+
# Perform the backup job for each Model found for the given triggers,
|
|
127
|
+
# clearing the Logger after each job.
|
|
128
|
+
#
|
|
129
|
+
# Model#perform! handles all exceptions from this point,
|
|
130
|
+
# as each model may fail and return here to allow others to run.
|
|
131
|
+
models.each do |model|
|
|
132
|
+
model.perform!
|
|
133
|
+
Logger.clear!
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
# [Generate:Model]
|
|
140
|
+
# Generates a model configuration file based on the arguments passed in.
|
|
141
|
+
# For example:
|
|
142
|
+
# $ backup generate:model --trigger my_backup --databases='mongodb'
|
|
143
|
+
# will generate a pre-populated model with a base MongoDB setup
|
|
144
|
+
desc 'generate:model', "Generates a Backup model file."
|
|
145
|
+
long_desc "Generates a Backup model file.\n\n" +
|
|
146
|
+
"\s\sNote: '--config-path' is the path to the directory where 'config.rb' is located.\n\n" +
|
|
147
|
+
"\s\sThe model file will be created as '<config_path>/models/<trigger>.rb'\n\n" +
|
|
148
|
+
"\s\sDefault: #{Config.root_path}\n\n"
|
|
149
|
+
|
|
150
|
+
method_option :trigger, :type => :string, :required => true, :aliases => '-t'
|
|
151
|
+
method_option :config_path, :type => :string,
|
|
152
|
+
:desc => 'Path to your Backup configuration directory'
|
|
153
|
+
|
|
154
|
+
# options with their available values
|
|
155
|
+
%w{ databases storages syncers
|
|
156
|
+
encryptors compressors notifiers }.map(&:to_sym).each do |name|
|
|
157
|
+
path = File.join(Backup::TEMPLATE_PATH, 'cli', name.to_s[0..-2])
|
|
158
|
+
method_option name, :type => :string, :desc =>
|
|
159
|
+
"(#{Dir[path + '/*'].sort.map {|p| File.basename(p) }.join(', ')})"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
method_option :archives, :type => :boolean
|
|
163
|
+
method_option :splitter, :type => :boolean, :default => true,
|
|
164
|
+
:desc => "use `--no-splitter` to disable"
|
|
165
|
+
|
|
166
|
+
define_method "generate:model" do
|
|
167
|
+
opts = options.merge(
|
|
168
|
+
:trigger => options[:trigger].gsub(/\W/, '_'),
|
|
169
|
+
:config_path => options[:config_path] ?
|
|
170
|
+
File.expand_path(options[:config_path]) : nil
|
|
171
|
+
)
|
|
172
|
+
config_path = opts[:config_path] || Config.root_path
|
|
173
|
+
models_path = File.join(config_path, "models")
|
|
174
|
+
config = File.join(config_path, "config.rb")
|
|
175
|
+
model = File.join(models_path, "#{opts[:trigger]}.rb")
|
|
176
|
+
|
|
177
|
+
FileUtils.mkdir_p(models_path)
|
|
178
|
+
if overwrite?(model)
|
|
179
|
+
File.open(model, 'w') do |file|
|
|
180
|
+
file.write(
|
|
181
|
+
Backup::Template.new({:options => opts}).result("cli/model.erb")
|
|
182
|
+
)
|
|
183
|
+
end
|
|
184
|
+
puts "Generated model file: '#{ model }'."
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if not File.exist?(config)
|
|
188
|
+
File.open(config, "w") do |file|
|
|
189
|
+
file.write(Backup::Template.new.result("cli/config"))
|
|
190
|
+
end
|
|
191
|
+
puts "Generated configuration file: '#{ config }'."
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
##
|
|
196
|
+
# [Generate:Config]
|
|
197
|
+
# Generates the main configuration file
|
|
198
|
+
desc 'generate:config', 'Generates the main Backup bootstrap/configuration file'
|
|
199
|
+
method_option :config_path, :type => :string,
|
|
200
|
+
:desc => "Path to your Backup configuration directory. Default: #{Config.root_path}"
|
|
201
|
+
|
|
202
|
+
define_method 'generate:config' do
|
|
203
|
+
config_path = options[:config_path] ?
|
|
204
|
+
File.expand_path(options[:config_path]) : Config.root_path
|
|
205
|
+
config = File.join(config_path, "config.rb")
|
|
206
|
+
|
|
207
|
+
FileUtils.mkdir_p(config_path)
|
|
208
|
+
if overwrite?(config)
|
|
209
|
+
File.open(config, "w") do |file|
|
|
210
|
+
file.write(Backup::Template.new.result("cli/config"))
|
|
211
|
+
end
|
|
212
|
+
puts "Generated configuration file: '#{ config }'."
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# [Decrypt]
|
|
218
|
+
# Shorthand for decrypting encrypted files
|
|
219
|
+
desc 'decrypt', 'Decrypts encrypted files'
|
|
220
|
+
method_option :encryptor, :type => :string, :required => true
|
|
221
|
+
method_option :in, :type => :string, :required => true
|
|
222
|
+
method_option :out, :type => :string, :required => true
|
|
223
|
+
method_option :base64, :type => :boolean, :default => false
|
|
224
|
+
method_option :password_file, :type => :string, :default => ''
|
|
225
|
+
method_option :salt, :type => :boolean, :default => false
|
|
226
|
+
|
|
227
|
+
def decrypt
|
|
228
|
+
case options[:encryptor].downcase
|
|
229
|
+
when 'openssl'
|
|
230
|
+
base64 = options[:base64] ? '-base64' : ''
|
|
231
|
+
password = options[:password_file].empty? ? '' : "-pass file:#{options[:password_file]}"
|
|
232
|
+
salt = options[:salt] ? '-salt' : ''
|
|
233
|
+
%x[openssl aes-256-cbc -d #{base64} #{password} #{salt} -in '#{options[:in]}' -out '#{options[:out]}']
|
|
234
|
+
when 'gpg'
|
|
235
|
+
%x[gpg -o '#{options[:out]}' -d '#{options[:in]}']
|
|
236
|
+
else
|
|
237
|
+
puts "Unknown encryptor: #{options[:encryptor]}"
|
|
238
|
+
puts "Use either 'openssl' or 'gpg'."
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
##
|
|
243
|
+
# [Dependencies]
|
|
244
|
+
# Returns a list of Backup's dependencies
|
|
245
|
+
desc 'dependencies', 'Display, Check or Install Dependencies for Backup.'
|
|
246
|
+
long_desc 'Display the list of dependencies for Backup, check the installation status, or install them through Backup.'
|
|
247
|
+
method_option :install, :type => :string
|
|
248
|
+
method_option :list, :type => :boolean
|
|
249
|
+
method_option :installed, :type => :string
|
|
250
|
+
|
|
251
|
+
def dependencies
|
|
252
|
+
unless options.any?
|
|
253
|
+
puts
|
|
254
|
+
puts "To display a list of available dependencies, run:\n\n"
|
|
255
|
+
puts " backup dependencies --list"
|
|
256
|
+
puts
|
|
257
|
+
puts "To install one of these dependencies (with the correct version), run:\n\n"
|
|
258
|
+
puts " backup dependencies --install <name>"
|
|
259
|
+
puts
|
|
260
|
+
puts "To check if a dependency is already installed, run:\n\n"
|
|
261
|
+
puts " backup dependencies --installed <name>"
|
|
262
|
+
exit
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
if options[:list]
|
|
266
|
+
deps = Dependency.all
|
|
267
|
+
width = 15 + deps.map {|dep| dep.used_for }.map(&:length).max
|
|
268
|
+
deps.each do |dep|
|
|
269
|
+
puts
|
|
270
|
+
puts "Gem Name: #{ dep.name }"
|
|
271
|
+
puts "Version: #{ dep.requirements.join(', ') }"
|
|
272
|
+
puts "Used for: #{ dep.used_for }"
|
|
273
|
+
puts '-' * width
|
|
274
|
+
end
|
|
275
|
+
exit
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
name = options[:install] || options[:installed]
|
|
279
|
+
unless dep = Dependency.find(name)
|
|
280
|
+
abort "'#{ name }' is not a Backup dependency."
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
if options[:install]
|
|
284
|
+
if Helpers.bundler_loaded?
|
|
285
|
+
abort <<-EOS.gsub(/^ +/, '')
|
|
286
|
+
=== Bundler Detected ===
|
|
287
|
+
This command should not be run within a Bundler managed environment.
|
|
288
|
+
While it is possible to install Backup and it's dependencies using
|
|
289
|
+
Bundler, the gem version requirements must still be met as shown by:
|
|
290
|
+
> backup dependencies --list
|
|
291
|
+
EOS
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
dep.dependencies.each do |_dep|
|
|
295
|
+
unless _dep.installed?
|
|
296
|
+
abort <<-EOS.gsub(/^ +/, '')
|
|
297
|
+
The '#{ dep.name }' gem requires '#{ _dep.name }'
|
|
298
|
+
Please install this first using the following command:
|
|
299
|
+
> backup dependencies --install #{ _dep.name }
|
|
300
|
+
EOS
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
dep.install!
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
if options[:installed]
|
|
308
|
+
name, err_msg = nil, nil
|
|
309
|
+
|
|
310
|
+
dep.dependencies.each do |_dep|
|
|
311
|
+
unless _dep.installed?
|
|
312
|
+
name = _dep.name
|
|
313
|
+
err_msg = "'#{ dep.name }' requires the '#{ name }' gem."
|
|
314
|
+
break
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
unless err_msg || dep.installed?
|
|
319
|
+
name = dep.name
|
|
320
|
+
err_msg = "'#{ name }' is not installed."
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
if err_msg
|
|
324
|
+
abort <<-EOS.gsub(/^ +/, '')
|
|
325
|
+
#{ err_msg }
|
|
326
|
+
To install the gem, issue the following command:
|
|
327
|
+
> backup dependencies --install #{ name }
|
|
328
|
+
Please try again after installing the missing dependency.
|
|
329
|
+
EOS
|
|
330
|
+
else
|
|
331
|
+
puts "'#{ dep.name }' is installed."
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
##
|
|
337
|
+
# [Version]
|
|
338
|
+
# Returns the current version of the Backup gem
|
|
339
|
+
map '-v' => :version
|
|
340
|
+
desc 'version', 'Display installed Backup version'
|
|
341
|
+
def version
|
|
342
|
+
puts "Backup #{Backup::Version.current}"
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
private
|
|
346
|
+
|
|
347
|
+
##
|
|
348
|
+
# Helper method for asking the user if he/she wants to overwrite the file
|
|
349
|
+
def overwrite?(path)
|
|
350
|
+
if File.exist?(path)
|
|
351
|
+
return yes? "A file already exists at '#{ path }'. Do you want to overwrite? [y/n]"
|
|
352
|
+
end
|
|
353
|
+
true
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# This is to avoid Thor's warnings when stubbing methods on the Thor class.
|
|
357
|
+
module Helpers
|
|
358
|
+
class << self
|
|
359
|
+
def bundler_loaded?
|
|
360
|
+
defined?(Bundler)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
end
|
|
366
|
+
end
|