backup 3.0.27 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|