backup-agoddard 3.0.27
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of backup-agoddard might be problematic. Click here for more details.
- data/.gitignore +8 -0
- data/.travis.yml +10 -0
- data/Gemfile +28 -0
- data/Guardfile +23 -0
- data/LICENSE.md +24 -0
- data/README.md +478 -0
- data/backup.gemspec +32 -0
- data/bin/backup +11 -0
- data/lib/backup.rb +133 -0
- data/lib/backup/archive.rb +117 -0
- data/lib/backup/binder.rb +22 -0
- data/lib/backup/cleaner.rb +121 -0
- data/lib/backup/cli/helpers.rb +93 -0
- data/lib/backup/cli/utility.rb +255 -0
- data/lib/backup/compressor/base.rb +35 -0
- data/lib/backup/compressor/bzip2.rb +50 -0
- data/lib/backup/compressor/custom.rb +53 -0
- data/lib/backup/compressor/gzip.rb +50 -0
- data/lib/backup/compressor/lzma.rb +52 -0
- data/lib/backup/compressor/pbzip2.rb +59 -0
- data/lib/backup/config.rb +174 -0
- data/lib/backup/configuration.rb +33 -0
- data/lib/backup/configuration/helpers.rb +130 -0
- data/lib/backup/configuration/store.rb +24 -0
- data/lib/backup/database/base.rb +53 -0
- data/lib/backup/database/mongodb.rb +230 -0
- data/lib/backup/database/mysql.rb +160 -0
- data/lib/backup/database/postgresql.rb +144 -0
- data/lib/backup/database/redis.rb +136 -0
- data/lib/backup/database/riak.rb +67 -0
- data/lib/backup/dependency.rb +108 -0
- data/lib/backup/encryptor/base.rb +29 -0
- data/lib/backup/encryptor/gpg.rb +760 -0
- data/lib/backup/encryptor/open_ssl.rb +72 -0
- data/lib/backup/errors.rb +124 -0
- data/lib/backup/hooks.rb +68 -0
- data/lib/backup/logger.rb +152 -0
- data/lib/backup/model.rb +409 -0
- data/lib/backup/notifier/base.rb +81 -0
- data/lib/backup/notifier/campfire.rb +155 -0
- data/lib/backup/notifier/hipchat.rb +93 -0
- data/lib/backup/notifier/mail.rb +206 -0
- data/lib/backup/notifier/prowl.rb +65 -0
- data/lib/backup/notifier/pushover.rb +88 -0
- data/lib/backup/notifier/twitter.rb +70 -0
- data/lib/backup/package.rb +47 -0
- data/lib/backup/packager.rb +100 -0
- data/lib/backup/pipeline.rb +110 -0
- data/lib/backup/splitter.rb +75 -0
- data/lib/backup/storage/base.rb +99 -0
- data/lib/backup/storage/cloudfiles.rb +87 -0
- data/lib/backup/storage/cycler.rb +117 -0
- data/lib/backup/storage/dropbox.rb +178 -0
- data/lib/backup/storage/ftp.rb +119 -0
- data/lib/backup/storage/local.rb +82 -0
- data/lib/backup/storage/ninefold.rb +116 -0
- data/lib/backup/storage/rsync.rb +149 -0
- data/lib/backup/storage/s3.rb +94 -0
- data/lib/backup/storage/scp.rb +99 -0
- data/lib/backup/storage/sftp.rb +108 -0
- data/lib/backup/syncer/base.rb +46 -0
- data/lib/backup/syncer/cloud/base.rb +247 -0
- data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
- data/lib/backup/syncer/cloud/s3.rb +68 -0
- data/lib/backup/syncer/rsync/base.rb +49 -0
- data/lib/backup/syncer/rsync/local.rb +55 -0
- data/lib/backup/syncer/rsync/pull.rb +36 -0
- data/lib/backup/syncer/rsync/push.rb +116 -0
- data/lib/backup/template.rb +46 -0
- data/lib/backup/version.rb +43 -0
- data/spec-live/.gitignore +6 -0
- data/spec-live/README +7 -0
- data/spec-live/backups/config.rb +83 -0
- data/spec-live/backups/config.yml.template +46 -0
- data/spec-live/backups/models.rb +184 -0
- data/spec-live/compressor/custom_spec.rb +30 -0
- data/spec-live/compressor/gzip_spec.rb +30 -0
- data/spec-live/encryptor/gpg_keys.rb +239 -0
- data/spec-live/encryptor/gpg_spec.rb +287 -0
- data/spec-live/notifier/mail_spec.rb +121 -0
- data/spec-live/spec_helper.rb +151 -0
- data/spec-live/storage/dropbox_spec.rb +151 -0
- data/spec-live/storage/local_spec.rb +83 -0
- data/spec-live/storage/scp_spec.rb +193 -0
- data/spec-live/syncer/cloud/s3_spec.rb +124 -0
- data/spec/archive_spec.rb +335 -0
- data/spec/cleaner_spec.rb +312 -0
- data/spec/cli/helpers_spec.rb +301 -0
- data/spec/cli/utility_spec.rb +411 -0
- data/spec/compressor/base_spec.rb +52 -0
- data/spec/compressor/bzip2_spec.rb +217 -0
- data/spec/compressor/custom_spec.rb +106 -0
- data/spec/compressor/gzip_spec.rb +217 -0
- data/spec/compressor/lzma_spec.rb +123 -0
- data/spec/compressor/pbzip2_spec.rb +165 -0
- data/spec/config_spec.rb +321 -0
- data/spec/configuration/helpers_spec.rb +247 -0
- data/spec/configuration/store_spec.rb +39 -0
- data/spec/configuration_spec.rb +62 -0
- data/spec/database/base_spec.rb +63 -0
- data/spec/database/mongodb_spec.rb +510 -0
- data/spec/database/mysql_spec.rb +411 -0
- data/spec/database/postgresql_spec.rb +353 -0
- data/spec/database/redis_spec.rb +334 -0
- data/spec/database/riak_spec.rb +176 -0
- data/spec/dependency_spec.rb +51 -0
- data/spec/encryptor/base_spec.rb +40 -0
- data/spec/encryptor/gpg_spec.rb +909 -0
- data/spec/encryptor/open_ssl_spec.rb +148 -0
- data/spec/errors_spec.rb +306 -0
- data/spec/hooks_spec.rb +35 -0
- data/spec/logger_spec.rb +367 -0
- data/spec/model_spec.rb +694 -0
- data/spec/notifier/base_spec.rb +104 -0
- data/spec/notifier/campfire_spec.rb +217 -0
- data/spec/notifier/hipchat_spec.rb +211 -0
- data/spec/notifier/mail_spec.rb +316 -0
- data/spec/notifier/prowl_spec.rb +138 -0
- data/spec/notifier/pushover_spec.rb +123 -0
- data/spec/notifier/twitter_spec.rb +153 -0
- data/spec/package_spec.rb +61 -0
- data/spec/packager_spec.rb +213 -0
- data/spec/pipeline_spec.rb +259 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/splitter_spec.rb +120 -0
- data/spec/storage/base_spec.rb +166 -0
- data/spec/storage/cloudfiles_spec.rb +254 -0
- data/spec/storage/cycler_spec.rb +247 -0
- data/spec/storage/dropbox_spec.rb +480 -0
- data/spec/storage/ftp_spec.rb +271 -0
- data/spec/storage/local_spec.rb +259 -0
- data/spec/storage/ninefold_spec.rb +343 -0
- data/spec/storage/rsync_spec.rb +362 -0
- data/spec/storage/s3_spec.rb +245 -0
- data/spec/storage/scp_spec.rb +233 -0
- data/spec/storage/sftp_spec.rb +244 -0
- data/spec/syncer/base_spec.rb +109 -0
- data/spec/syncer/cloud/base_spec.rb +515 -0
- data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
- data/spec/syncer/cloud/s3_spec.rb +174 -0
- data/spec/syncer/rsync/base_spec.rb +98 -0
- data/spec/syncer/rsync/local_spec.rb +149 -0
- data/spec/syncer/rsync/pull_spec.rb +98 -0
- data/spec/syncer/rsync/push_spec.rb +333 -0
- data/spec/version_spec.rb +21 -0
- data/templates/cli/utility/archive +25 -0
- data/templates/cli/utility/compressor/bzip2 +4 -0
- data/templates/cli/utility/compressor/custom +11 -0
- data/templates/cli/utility/compressor/gzip +4 -0
- data/templates/cli/utility/compressor/lzma +10 -0
- data/templates/cli/utility/compressor/pbzip2 +10 -0
- data/templates/cli/utility/config +32 -0
- data/templates/cli/utility/database/mongodb +18 -0
- data/templates/cli/utility/database/mysql +21 -0
- data/templates/cli/utility/database/postgresql +17 -0
- data/templates/cli/utility/database/redis +16 -0
- data/templates/cli/utility/database/riak +11 -0
- data/templates/cli/utility/encryptor/gpg +27 -0
- data/templates/cli/utility/encryptor/openssl +9 -0
- data/templates/cli/utility/model.erb +23 -0
- data/templates/cli/utility/notifier/campfire +12 -0
- data/templates/cli/utility/notifier/hipchat +15 -0
- data/templates/cli/utility/notifier/mail +22 -0
- data/templates/cli/utility/notifier/prowl +11 -0
- data/templates/cli/utility/notifier/pushover +11 -0
- data/templates/cli/utility/notifier/twitter +13 -0
- data/templates/cli/utility/splitter +7 -0
- data/templates/cli/utility/storage/cloud_files +22 -0
- data/templates/cli/utility/storage/dropbox +20 -0
- data/templates/cli/utility/storage/ftp +12 -0
- data/templates/cli/utility/storage/local +7 -0
- data/templates/cli/utility/storage/ninefold +9 -0
- data/templates/cli/utility/storage/rsync +11 -0
- data/templates/cli/utility/storage/s3 +19 -0
- data/templates/cli/utility/storage/scp +11 -0
- data/templates/cli/utility/storage/sftp +11 -0
- data/templates/cli/utility/syncer/cloud_files +46 -0
- data/templates/cli/utility/syncer/rsync_local +12 -0
- data/templates/cli/utility/syncer/rsync_pull +17 -0
- data/templates/cli/utility/syncer/rsync_push +17 -0
- data/templates/cli/utility/syncer/s3 +43 -0
- data/templates/general/links +11 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +9 -0
- data/templates/notifier/mail/success.erb +7 -0
- data/templates/notifier/mail/warning.erb +9 -0
- data/templates/storage/dropbox/authorization_url.erb +6 -0
- data/templates/storage/dropbox/authorized.erb +4 -0
- data/templates/storage/dropbox/cache_file_written.erb +10 -0
- metadata +277 -0
data/backup.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('lib/backup/version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
|
7
|
+
##
|
8
|
+
# General configuration / information
|
9
|
+
gem.name = 'backup-agoddard'
|
10
|
+
gem.version = Backup::Version.current
|
11
|
+
gem.platform = Gem::Platform::RUBY
|
12
|
+
gem.authors = 'Michael van Rooijen; Anthony Goddard; Dane O\'Connor'
|
13
|
+
gem.email = 'meskyanichi@gmail.com; agoddard@eol.org'
|
14
|
+
gem.homepage = 'http://github.com/agoddard/backup'
|
15
|
+
gem.summary = 'Backup is a RubyGem, written for UNIX-like operating systems, that allows you to easily perform backup operations on both your remote and local environments. It provides you with an elegant DSL in Ruby for modeling your backups. Backup has built-in support for various databases, storage protocols/services, syncers, compressors, encryptors and notifiers which you can mix and match. It was built with modularity, extensibility and simplicity in mind.'
|
16
|
+
|
17
|
+
##
|
18
|
+
# Files and folder that need to be compiled in to the Ruby Gem
|
19
|
+
gem.files = %x[git ls-files].split("\n")
|
20
|
+
gem.test_files = %x[git ls-files -- {spec}/*].split("\n")
|
21
|
+
gem.require_path = 'lib'
|
22
|
+
|
23
|
+
##
|
24
|
+
# The Backup CLI executable
|
25
|
+
gem.executables = ['backup']
|
26
|
+
|
27
|
+
##
|
28
|
+
# Gem dependencies
|
29
|
+
gem.add_dependency 'thor', ['>= 0.15.4', '< 2']
|
30
|
+
gem.add_dependency 'open4', ['~> 1.3.0']
|
31
|
+
|
32
|
+
end
|
data/bin/backup
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Load the Backup core library
|
5
|
+
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
|
data/lib/backup.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Load Ruby Core Libraries
|
4
|
+
require 'rubygems'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'tempfile'
|
7
|
+
require 'yaml'
|
8
|
+
require 'etc'
|
9
|
+
|
10
|
+
require 'open4'
|
11
|
+
require 'thor'
|
12
|
+
|
13
|
+
##
|
14
|
+
# The Backup Ruby Gem
|
15
|
+
module Backup
|
16
|
+
|
17
|
+
##
|
18
|
+
# Backup's internal paths
|
19
|
+
LIBRARY_PATH = File.join(File.dirname(__FILE__), 'backup')
|
20
|
+
CLI_PATH = File.join(LIBRARY_PATH, 'cli')
|
21
|
+
STORAGE_PATH = File.join(LIBRARY_PATH, 'storage')
|
22
|
+
DATABASE_PATH = File.join(LIBRARY_PATH, 'database')
|
23
|
+
COMPRESSOR_PATH = File.join(LIBRARY_PATH, 'compressor')
|
24
|
+
ENCRYPTOR_PATH = File.join(LIBRARY_PATH, 'encryptor')
|
25
|
+
NOTIFIER_PATH = File.join(LIBRARY_PATH, 'notifier')
|
26
|
+
SYNCER_PATH = File.join(LIBRARY_PATH, 'syncer')
|
27
|
+
TEMPLATE_PATH = File.expand_path('../../templates', __FILE__)
|
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
|
+
##
|
37
|
+
# Autoload Backup storage files
|
38
|
+
module Storage
|
39
|
+
autoload :Base, File.join(STORAGE_PATH, 'base')
|
40
|
+
autoload :Cycler, File.join(STORAGE_PATH, 'cycler')
|
41
|
+
autoload :S3, File.join(STORAGE_PATH, 's3')
|
42
|
+
autoload :CloudFiles, File.join(STORAGE_PATH, 'cloudfiles')
|
43
|
+
autoload :Ninefold, File.join(STORAGE_PATH, 'ninefold')
|
44
|
+
autoload :Dropbox, File.join(STORAGE_PATH, 'dropbox')
|
45
|
+
autoload :FTP, File.join(STORAGE_PATH, 'ftp')
|
46
|
+
autoload :SFTP, File.join(STORAGE_PATH, 'sftp')
|
47
|
+
autoload :SCP, File.join(STORAGE_PATH, 'scp')
|
48
|
+
autoload :RSync, File.join(STORAGE_PATH, 'rsync')
|
49
|
+
autoload :Local, File.join(STORAGE_PATH, 'local')
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Autoload Backup syncer files
|
54
|
+
module Syncer
|
55
|
+
autoload :Base, File.join(SYNCER_PATH, 'base')
|
56
|
+
module Cloud
|
57
|
+
autoload :Base, File.join(SYNCER_PATH, 'cloud', 'base')
|
58
|
+
autoload :CloudFiles, File.join(SYNCER_PATH, 'cloud', 'cloud_files')
|
59
|
+
autoload :S3, File.join(SYNCER_PATH, 'cloud', 's3')
|
60
|
+
end
|
61
|
+
module RSync
|
62
|
+
autoload :Base, File.join(SYNCER_PATH, 'rsync', 'base')
|
63
|
+
autoload :Local, File.join(SYNCER_PATH, 'rsync', 'local')
|
64
|
+
autoload :Push, File.join(SYNCER_PATH, 'rsync', 'push')
|
65
|
+
autoload :Pull, File.join(SYNCER_PATH, 'rsync', 'pull')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Autoload Backup database files
|
71
|
+
module Database
|
72
|
+
autoload :Base, File.join(DATABASE_PATH, 'base')
|
73
|
+
autoload :MySQL, File.join(DATABASE_PATH, 'mysql')
|
74
|
+
autoload :PostgreSQL, File.join(DATABASE_PATH, 'postgresql')
|
75
|
+
autoload :MongoDB, File.join(DATABASE_PATH, 'mongodb')
|
76
|
+
autoload :Redis, File.join(DATABASE_PATH, 'redis')
|
77
|
+
autoload :Riak, File.join(DATABASE_PATH, 'riak')
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Autoload compressor files
|
82
|
+
module Compressor
|
83
|
+
autoload :Base, File.join(COMPRESSOR_PATH, 'base')
|
84
|
+
autoload :Gzip, File.join(COMPRESSOR_PATH, 'gzip')
|
85
|
+
autoload :Bzip2, File.join(COMPRESSOR_PATH, 'bzip2')
|
86
|
+
autoload :Custom, File.join(COMPRESSOR_PATH, 'custom')
|
87
|
+
autoload :Pbzip2, File.join(COMPRESSOR_PATH, 'pbzip2')
|
88
|
+
autoload :Lzma, File.join(COMPRESSOR_PATH, 'lzma')
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Autoload encryptor files
|
93
|
+
module Encryptor
|
94
|
+
autoload :Base, File.join(ENCRYPTOR_PATH, 'base')
|
95
|
+
autoload :OpenSSL, File.join(ENCRYPTOR_PATH, 'open_ssl')
|
96
|
+
autoload :GPG, File.join(ENCRYPTOR_PATH, 'gpg')
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Autoload notification files
|
101
|
+
module Notifier
|
102
|
+
autoload :Base, File.join(NOTIFIER_PATH, 'base')
|
103
|
+
autoload :Binder, File.join(NOTIFIER_PATH, 'binder')
|
104
|
+
autoload :Mail, File.join(NOTIFIER_PATH, 'mail')
|
105
|
+
autoload :Twitter, File.join(NOTIFIER_PATH, 'twitter')
|
106
|
+
autoload :Campfire, File.join(NOTIFIER_PATH, 'campfire')
|
107
|
+
autoload :Prowl, File.join(NOTIFIER_PATH, 'prowl')
|
108
|
+
autoload :Hipchat, File.join(NOTIFIER_PATH, 'hipchat')
|
109
|
+
autoload :Pushover, File.join(NOTIFIER_PATH, 'pushover')
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Require Backup base files
|
114
|
+
%w{
|
115
|
+
archive
|
116
|
+
binder
|
117
|
+
cleaner
|
118
|
+
config
|
119
|
+
configuration
|
120
|
+
dependency
|
121
|
+
errors
|
122
|
+
hooks
|
123
|
+
logger
|
124
|
+
model
|
125
|
+
package
|
126
|
+
packager
|
127
|
+
pipeline
|
128
|
+
splitter
|
129
|
+
template
|
130
|
+
version
|
131
|
+
}.each {|lib| require File.join(LIBRARY_PATH, lib) }
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
class Archive
|
5
|
+
include Backup::CLI::Helpers
|
6
|
+
|
7
|
+
##
|
8
|
+
# Stores the name of the archive
|
9
|
+
attr_accessor :name
|
10
|
+
|
11
|
+
##
|
12
|
+
# Stores an array of different paths/files to store
|
13
|
+
attr_accessor :paths
|
14
|
+
|
15
|
+
##
|
16
|
+
# Stores an array of different paths/files to exclude
|
17
|
+
attr_accessor :excludes
|
18
|
+
|
19
|
+
##
|
20
|
+
# String of additional arguments for the `tar` command
|
21
|
+
attr_accessor :tar_args
|
22
|
+
|
23
|
+
##
|
24
|
+
# Takes the name of the archive and the configuration block
|
25
|
+
def initialize(model, name, &block)
|
26
|
+
@model = model
|
27
|
+
@name = name.to_s
|
28
|
+
@paths = Array.new
|
29
|
+
@excludes = Array.new
|
30
|
+
@tar_args = ''
|
31
|
+
|
32
|
+
instance_eval(&block) if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Adds new paths to the @paths instance variable array
|
37
|
+
def add(path)
|
38
|
+
path = File.expand_path(path)
|
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
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Adds new paths to the @excludes instance variable array
|
52
|
+
def exclude(path)
|
53
|
+
@excludes << File.expand_path(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Adds the given String of +options+ to the `tar` command.
|
58
|
+
# e.g. '-h --xattrs'
|
59
|
+
def tar_options(options)
|
60
|
+
@tar_args = options
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Archives all the provided paths in to a single .tar file
|
65
|
+
# and places that .tar file in the folder which later will be packaged
|
66
|
+
# If the model is configured with a Compressor, the tar command output
|
67
|
+
# will be piped through the Compressor command and the file extension
|
68
|
+
# will be adjusted to indicate the type of compression used.
|
69
|
+
def perform!
|
70
|
+
Logger.message "#{ self.class } has started archiving:\n" +
|
71
|
+
paths.map {|path| " #{path}" }.join("\n")
|
72
|
+
|
73
|
+
archive_path = File.join(Config.tmp_path, @model.trigger, 'archives')
|
74
|
+
FileUtils.mkdir_p(archive_path)
|
75
|
+
|
76
|
+
archive_ext = 'tar'
|
77
|
+
pipeline = Pipeline.new
|
78
|
+
|
79
|
+
pipeline << "#{ utility(:tar) } #{ tar_args } -cPf - " +
|
80
|
+
"#{ paths_to_exclude } #{ paths_to_package }"
|
81
|
+
|
82
|
+
if @model.compressor
|
83
|
+
@model.compressor.compress_with do |command, ext|
|
84
|
+
pipeline << command
|
85
|
+
archive_ext << ext
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
pipeline << "cat > '#{ File.join(archive_path, "#{name}.#{archive_ext}") }'"
|
90
|
+
pipeline.run
|
91
|
+
if pipeline.success?
|
92
|
+
Logger.message "#{ self.class } Complete!"
|
93
|
+
else
|
94
|
+
raise Errors::Archive::PipelineError,
|
95
|
+
"Failed to Create Backup Archive\n" +
|
96
|
+
pipeline.error_messages
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
##
|
103
|
+
# Returns a "tar-ready" string of all the specified paths combined
|
104
|
+
def paths_to_package
|
105
|
+
paths.map {|path| "'#{path}'" }.join(' ')
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Returns a "tar-ready" string of all the specified excludes combined
|
110
|
+
def paths_to_exclude
|
111
|
+
if excludes.any?
|
112
|
+
excludes.map {|path| "--exclude='#{path}'" }.join(' ')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
class Binder
|
5
|
+
|
6
|
+
##
|
7
|
+
# Creates a new Backup::Notifier::Binder instance. Loops through the provided
|
8
|
+
# Hash to set instance variables
|
9
|
+
def initialize(key_and_values)
|
10
|
+
key_and_values.each do |key, value|
|
11
|
+
instance_variable_set("@#{ key }", value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Returns the binding (needs a wrapper method because #binding is a private method)
|
17
|
+
def get_binding
|
18
|
+
binding
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Cleaner
|
5
|
+
class << self
|
6
|
+
|
7
|
+
##
|
8
|
+
# Logs warnings if any temporary files still exist
|
9
|
+
# from the last time this model/trigger was run,
|
10
|
+
# then removes the files.
|
11
|
+
def prepare(model)
|
12
|
+
@model = model
|
13
|
+
|
14
|
+
messages = []
|
15
|
+
if packaging_folder_dirty?
|
16
|
+
messages << <<-EOS
|
17
|
+
The temporary backup folder still contains files!
|
18
|
+
'#{ File.join(Config.tmp_path, @model.trigger) }'
|
19
|
+
These files will now be removed.
|
20
|
+
EOS
|
21
|
+
FileUtils.rm_rf(File.join(Config.tmp_path, @model.trigger))
|
22
|
+
end
|
23
|
+
|
24
|
+
package_files = tmp_path_package_files
|
25
|
+
unless package_files.empty?
|
26
|
+
# the chances that tmp_path would be dirty
|
27
|
+
# AND package files exist are practically nil
|
28
|
+
messages << ('-' * 74) unless messages.empty?
|
29
|
+
|
30
|
+
messages << <<-EOS
|
31
|
+
The temporary backup folder '#{ Config.tmp_path }'
|
32
|
+
appears to contain the package files from the previous backup!
|
33
|
+
#{ package_files.join("\n") }
|
34
|
+
These files will now be removed.
|
35
|
+
EOS
|
36
|
+
package_files.each {|file| FileUtils.rm_f(file) }
|
37
|
+
end
|
38
|
+
|
39
|
+
unless messages.empty?
|
40
|
+
Logger.warn Errors::CleanerError.new(<<-EOS)
|
41
|
+
Cleanup Warning
|
42
|
+
#{ messages.join("\n") }
|
43
|
+
Please check the log for messages and/or your notifications
|
44
|
+
concerning this backup: '#{ @model.label } (#{ @model.trigger })'
|
45
|
+
The temporary files which had to be removed should not have existed.
|
46
|
+
EOS
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Remove the temporary folder used during packaging
|
52
|
+
def remove_packaging(model)
|
53
|
+
Logger.message "Cleaning up the temporary files..."
|
54
|
+
FileUtils.rm_rf(File.join(Config.tmp_path, model.trigger))
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Remove the final package files from tmp_path
|
59
|
+
# Note: 'force' is used, since a Local Storage may *move* these files.
|
60
|
+
def remove_package(package)
|
61
|
+
Logger.message "Cleaning up the package files..."
|
62
|
+
package.filenames.each do |file|
|
63
|
+
FileUtils.rm_f(File.join(Config.tmp_path, file))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Logs warnings if any temporary files still exist
|
69
|
+
# when errors occur during the backup
|
70
|
+
def warnings(model)
|
71
|
+
@model = model
|
72
|
+
|
73
|
+
messages = []
|
74
|
+
if packaging_folder_dirty?
|
75
|
+
messages << <<-EOS
|
76
|
+
The temporary backup folder still contains files!
|
77
|
+
'#{ File.join(Config.tmp_path, @model.trigger) }'
|
78
|
+
This folder may contain completed Archives and/or Database backups.
|
79
|
+
EOS
|
80
|
+
end
|
81
|
+
|
82
|
+
package_files = tmp_path_package_files
|
83
|
+
unless package_files.empty?
|
84
|
+
# the chances that tmp_path would be dirty
|
85
|
+
# AND package files exist are practically nil
|
86
|
+
messages << ('-' * 74) unless messages.empty?
|
87
|
+
|
88
|
+
messages << <<-EOS
|
89
|
+
The temporary backup folder '#{ Config.tmp_path }'
|
90
|
+
appears to contain the backup files which were to be stored:
|
91
|
+
#{ package_files.join("\n") }
|
92
|
+
EOS
|
93
|
+
end
|
94
|
+
|
95
|
+
unless messages.empty?
|
96
|
+
Logger.warn Errors::CleanerError.new(<<-EOS)
|
97
|
+
Cleanup Warning
|
98
|
+
#{ messages.join("\n") }
|
99
|
+
Make sure you check these files before the next scheduled backup for
|
100
|
+
'#{ @model.label } (#{ @model.trigger })'
|
101
|
+
These files will be removed at that time!
|
102
|
+
EOS
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def packaging_folder_dirty?
|
109
|
+
!Dir[File.join(Config.tmp_path, @model.trigger, '*')].empty?
|
110
|
+
end
|
111
|
+
|
112
|
+
def tmp_path_package_files
|
113
|
+
Dir[File.join(
|
114
|
+
Config.tmp_path,
|
115
|
+
"????.??.??.??.??.??.#{ @model.trigger }.tar{,[.-]*}"
|
116
|
+
)]
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module CLI
|
5
|
+
module Helpers
|
6
|
+
UTILITY = {}
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
##
|
11
|
+
# Runs a system command
|
12
|
+
#
|
13
|
+
# All messages generated by the command will be logged.
|
14
|
+
# Messages on STDERR will be logged as warnings.
|
15
|
+
#
|
16
|
+
# If the command fails to execute, or returns a non-zero exit status
|
17
|
+
# an Error will be raised.
|
18
|
+
#
|
19
|
+
# Returns STDOUT
|
20
|
+
def run(command)
|
21
|
+
name = command_name(command)
|
22
|
+
Logger.message "Running system utility '#{ name }'..."
|
23
|
+
|
24
|
+
begin
|
25
|
+
out, err = '', ''
|
26
|
+
ps = Open4.popen4(command) do |pid, stdin, stdout, stderr|
|
27
|
+
stdin.close
|
28
|
+
out, err = stdout.read.strip, stderr.read.strip
|
29
|
+
end
|
30
|
+
rescue Exception => e
|
31
|
+
raise Errors::CLI::SystemCallError.wrap(e, <<-EOS)
|
32
|
+
Failed to execute system command on #{ RUBY_PLATFORM }
|
33
|
+
Command was: #{ command }
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
|
37
|
+
if ps.success?
|
38
|
+
unless out.empty?
|
39
|
+
Logger.message(
|
40
|
+
out.lines.map {|line| "#{ name }:STDOUT: #{ line }" }.join
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
unless err.empty?
|
45
|
+
Logger.warn(
|
46
|
+
err.lines.map {|line| "#{ name }:STDERR: #{ line }" }.join
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
return out
|
51
|
+
else
|
52
|
+
raise Errors::CLI::SystemCallError, <<-EOS
|
53
|
+
'#{ name }' Failed on #{ RUBY_PLATFORM }
|
54
|
+
The following information should help to determine the problem:
|
55
|
+
Command was: #{ command }
|
56
|
+
Exit Status: #{ ps.exitstatus }
|
57
|
+
STDOUT Messages: #{ out.empty? ? 'None' : "\n#{ out }" }
|
58
|
+
STDERR Messages: #{ err.empty? ? 'None' : "\n#{ err }" }
|
59
|
+
EOS
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
##
|
65
|
+
# Returns the full path to the specified utility.
|
66
|
+
# Raises an error if utility can not be found in the system's $PATH
|
67
|
+
def utility(name)
|
68
|
+
name = name.to_s.strip
|
69
|
+
raise Errors::CLI::UtilityNotFoundError,
|
70
|
+
'Utility Name Empty' if name.empty?
|
71
|
+
|
72
|
+
path = UTILITY[name] || %x[which #{ name } 2>/dev/null].chomp
|
73
|
+
if path.empty?
|
74
|
+
raise Errors::CLI::UtilityNotFoundError, <<-EOS
|
75
|
+
Could not locate '#{ name }'.
|
76
|
+
Make sure the specified utility is installed
|
77
|
+
and available in your system's $PATH.
|
78
|
+
EOS
|
79
|
+
end
|
80
|
+
UTILITY[name] = path
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Returns the name of the command name from the given command line
|
85
|
+
def command_name(command)
|
86
|
+
i = command =~ /\s/
|
87
|
+
command = command.slice(0, i) if i
|
88
|
+
command.split('/')[-1]
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|