backup-agoddard 3.0.27
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 +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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'ostruct'
|
|
4
|
+
|
|
5
|
+
module Backup
|
|
6
|
+
module Configuration
|
|
7
|
+
class Store < OpenStruct
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Returns an Array of all attribute method names
|
|
11
|
+
# that default values were set for.
|
|
12
|
+
def _attributes
|
|
13
|
+
@table.keys
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Used only within the specs
|
|
18
|
+
def reset!
|
|
19
|
+
@table.clear
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class Base
|
|
6
|
+
include Backup::CLI::Helpers
|
|
7
|
+
include Backup::Configuration::Helpers
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Creates a new instance of the MongoDB database object
|
|
11
|
+
# * Called using super(model) from subclasses *
|
|
12
|
+
def initialize(model)
|
|
13
|
+
@model = model
|
|
14
|
+
load_defaults!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Super method for all child (database) objects. Every database object's #perform!
|
|
19
|
+
# method should call #super before anything else to prepare
|
|
20
|
+
def perform!
|
|
21
|
+
prepare!
|
|
22
|
+
log!
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Defines the @dump_path and ensures it exists by creating it
|
|
29
|
+
def prepare!
|
|
30
|
+
@dump_path = File.join(
|
|
31
|
+
Config.tmp_path,
|
|
32
|
+
@model.trigger,
|
|
33
|
+
'databases',
|
|
34
|
+
self.class.name.split('::').last
|
|
35
|
+
)
|
|
36
|
+
FileUtils.mkdir_p(@dump_path)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Return the database name, with Backup namespace removed
|
|
41
|
+
def database_name
|
|
42
|
+
self.class.to_s.sub('Backup::', '')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Logs a message to the console and log file to inform
|
|
47
|
+
# the client that Backup is dumping the database
|
|
48
|
+
def log!
|
|
49
|
+
Logger.message "#{ database_name } started dumping and archiving '#{ name }'."
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class MongoDB < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Name of the database that needs to get dumped
|
|
9
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Credentials for the specified database
|
|
13
|
+
attr_accessor :username, :password
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Connectivity options
|
|
17
|
+
attr_accessor :host, :port
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# IPv6 support (disabled by default)
|
|
21
|
+
attr_accessor :ipv6
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Collections to dump, collections that aren't specified won't get dumped
|
|
25
|
+
attr_accessor :only_collections
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Additional "mongodump" options
|
|
29
|
+
attr_accessor :additional_options
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Path to the mongodump utility (optional)
|
|
33
|
+
attr_accessor :mongodump_utility
|
|
34
|
+
|
|
35
|
+
attr_deprecate :utility_path, :version => '3.0.21',
|
|
36
|
+
:message => 'Use MongoDB#mongodump_utility instead.',
|
|
37
|
+
:action => lambda {|klass, val| klass.mongodump_utility = val }
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Path to the mongo utility (optional)
|
|
41
|
+
attr_accessor :mongo_utility
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# 'lock' dump meaning wrapping mongodump with fsync & lock
|
|
45
|
+
attr_accessor :lock
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Creates a new instance of the MongoDB database object
|
|
49
|
+
def initialize(model, &block)
|
|
50
|
+
super(model)
|
|
51
|
+
|
|
52
|
+
@only_collections ||= Array.new
|
|
53
|
+
@additional_options ||= Array.new
|
|
54
|
+
@ipv6 ||= false
|
|
55
|
+
@lock ||= false
|
|
56
|
+
|
|
57
|
+
instance_eval(&block) if block_given?
|
|
58
|
+
|
|
59
|
+
@mongodump_utility ||= utility(:mongodump)
|
|
60
|
+
@mongo_utility ||= utility(:mongo)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Performs the mongodump command and outputs the data to the
|
|
65
|
+
# specified path based on the 'trigger'. If the user hasn't specified any
|
|
66
|
+
# specific collections to dump, it'll dump everything. If the user has specified
|
|
67
|
+
# collections to dump, it'll loop through the array of collections and invoke the
|
|
68
|
+
# 'mongodump' command once per collection
|
|
69
|
+
def perform!
|
|
70
|
+
super
|
|
71
|
+
|
|
72
|
+
lock_database if @lock
|
|
73
|
+
@only_collections.empty? ? dump! : specific_collection_dump!
|
|
74
|
+
|
|
75
|
+
rescue => err
|
|
76
|
+
raise Errors::Database::MongoDBError.wrap(err, 'Database Dump Failed!')
|
|
77
|
+
ensure
|
|
78
|
+
unlock_database if @lock
|
|
79
|
+
package! unless err
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Builds and runs the mongodump command
|
|
86
|
+
def dump!
|
|
87
|
+
run(mongodump)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# For each collection in the @only_collections array, it'll
|
|
92
|
+
# build the whole 'mongodump' command, append the '--collection' option,
|
|
93
|
+
# and run the command built command
|
|
94
|
+
def specific_collection_dump!
|
|
95
|
+
@only_collections.each do |collection|
|
|
96
|
+
run("#{mongodump} --collection='#{collection}'")
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Builds the full mongodump string based on all attributes
|
|
102
|
+
def mongodump
|
|
103
|
+
"#{ mongodump_utility } #{ database } #{ credential_options } " +
|
|
104
|
+
"#{ connectivity_options } #{ ipv6_option } #{ user_options } #{ dump_directory }"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
##
|
|
108
|
+
# If a compressor is configured, packages the dump_path into a
|
|
109
|
+
# single compressed tar archive, then removes the dump_path.
|
|
110
|
+
# e.g.
|
|
111
|
+
# if the database was dumped to:
|
|
112
|
+
# ~/Backup/.tmp/databases/MongoDB/
|
|
113
|
+
# then it will be packaged into:
|
|
114
|
+
# ~/Backup/.tmp/databases/MongoDB-<timestamp>.tar.gz
|
|
115
|
+
def package!
|
|
116
|
+
return unless @model.compressor
|
|
117
|
+
|
|
118
|
+
pipeline = Pipeline.new
|
|
119
|
+
base_dir = File.dirname(@dump_path)
|
|
120
|
+
dump_dir = File.basename(@dump_path)
|
|
121
|
+
timestamp = Time.now.to_i.to_s[-5, 5]
|
|
122
|
+
outfile = @dump_path + '-' + timestamp + '.tar'
|
|
123
|
+
|
|
124
|
+
Logger.message(
|
|
125
|
+
"#{ database_name } started compressing and packaging:\n" +
|
|
126
|
+
" '#{ @dump_path }'"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
pipeline << "#{ utility(:tar) } -cf - -C '#{ base_dir }' '#{ dump_dir }'"
|
|
130
|
+
@model.compressor.compress_with do |command, ext|
|
|
131
|
+
pipeline << command
|
|
132
|
+
outfile << ext
|
|
133
|
+
end
|
|
134
|
+
pipeline << "cat > #{ outfile }"
|
|
135
|
+
|
|
136
|
+
pipeline.run
|
|
137
|
+
if pipeline.success?
|
|
138
|
+
Logger.message(
|
|
139
|
+
"#{ database_name } completed compressing and packaging:\n" +
|
|
140
|
+
" '#{ outfile }'"
|
|
141
|
+
)
|
|
142
|
+
FileUtils.rm_rf(@dump_path)
|
|
143
|
+
else
|
|
144
|
+
raise Errors::Database::PipelineError,
|
|
145
|
+
"#{ database_name } Failed to create compressed dump package:\n" +
|
|
146
|
+
"'#{ outfile }'\n" +
|
|
147
|
+
pipeline.error_messages
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
##
|
|
152
|
+
# Returns the MongoDB database selector syntax
|
|
153
|
+
def database
|
|
154
|
+
"--db='#{ name }'" if name
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
##
|
|
158
|
+
# Builds the MongoDB credentials syntax to authenticate the user
|
|
159
|
+
# to perform the database dumping process
|
|
160
|
+
def credential_options
|
|
161
|
+
%w[username password].map do |option|
|
|
162
|
+
next if send(option).to_s.empty?
|
|
163
|
+
"--#{option}='#{send(option)}'"
|
|
164
|
+
end.compact.join(' ')
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# Builds the MongoDB connectivity options syntax to connect the user
|
|
169
|
+
# to perform the database dumping process
|
|
170
|
+
def connectivity_options
|
|
171
|
+
%w[host port].map do |option|
|
|
172
|
+
next if send(option).to_s.empty?
|
|
173
|
+
"--#{option}='#{send(option)}'"
|
|
174
|
+
end.compact.join(' ')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Returns the mongodump syntax for enabling ipv6
|
|
179
|
+
def ipv6_option
|
|
180
|
+
@ipv6 ? '--ipv6' : ''
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
##
|
|
184
|
+
# Builds a MongoDB compatible string for the
|
|
185
|
+
# additional options specified by the user
|
|
186
|
+
def user_options
|
|
187
|
+
@additional_options.join(' ')
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
##
|
|
191
|
+
# Returns the MongoDB syntax for determining where to output all the database dumps,
|
|
192
|
+
# e.g. ~/Backup/.tmp/databases/MongoDB/<databases here>/<database collections>
|
|
193
|
+
def dump_directory
|
|
194
|
+
"--out='#{ @dump_path }'"
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
##
|
|
198
|
+
# Locks and FSyncs the database to bring it up to sync
|
|
199
|
+
# and ensure no 'write operations' are performed during the
|
|
200
|
+
# dump process
|
|
201
|
+
def lock_database
|
|
202
|
+
lock_command = <<-EOS.gsub(/^ +/, ' ')
|
|
203
|
+
echo 'use admin
|
|
204
|
+
db.runCommand({"fsync" : 1, "lock" : 1})' | #{ "#{ mongo_utility } #{ mongo_uri }" }
|
|
205
|
+
EOS
|
|
206
|
+
|
|
207
|
+
run(lock_command)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
# Unlocks the (locked) database
|
|
212
|
+
def unlock_database
|
|
213
|
+
unlock_command = <<-EOS.gsub(/^ +/, ' ')
|
|
214
|
+
echo 'use admin
|
|
215
|
+
db.$cmd.sys.unlock.findOne()' | #{ "#{ mongo_utility } #{ mongo_uri }" }
|
|
216
|
+
EOS
|
|
217
|
+
|
|
218
|
+
run(unlock_command)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
##
|
|
222
|
+
# Builds a Mongo URI based on the provided attributes
|
|
223
|
+
def mongo_uri
|
|
224
|
+
["#{ host }:#{ port }#{ ('/' + name) if name }",
|
|
225
|
+
credential_options, ipv6_option].join(' ').strip
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class MySQL < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Name of the database that needs to get dumped
|
|
9
|
+
# To dump all databases, set this to `:all` or leave blank.
|
|
10
|
+
attr_accessor :name
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Credentials for the specified database
|
|
14
|
+
attr_accessor :username, :password
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Connectivity options
|
|
18
|
+
attr_accessor :host, :port, :socket
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Tables to skip while dumping the database
|
|
22
|
+
attr_accessor :skip_tables
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Tables to dump, tables that aren't specified won't get dumped
|
|
26
|
+
attr_accessor :only_tables
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Additional "mysqldump" options
|
|
30
|
+
attr_accessor :additional_options
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Path to mysqldump utility (optional)
|
|
34
|
+
attr_accessor :mysqldump_utility
|
|
35
|
+
|
|
36
|
+
attr_deprecate :utility_path, :version => '3.0.21',
|
|
37
|
+
:message => 'Use MySQL#mysqldump_utility instead.',
|
|
38
|
+
:action => lambda {|klass, val| klass.mysqldump_utility = val }
|
|
39
|
+
|
|
40
|
+
##
|
|
41
|
+
# Creates a new instance of the MySQL adapter object
|
|
42
|
+
def initialize(model, &block)
|
|
43
|
+
super(model)
|
|
44
|
+
|
|
45
|
+
@skip_tables ||= Array.new
|
|
46
|
+
@only_tables ||= Array.new
|
|
47
|
+
@additional_options ||= Array.new
|
|
48
|
+
|
|
49
|
+
instance_eval(&block) if block_given?
|
|
50
|
+
|
|
51
|
+
@name ||= :all
|
|
52
|
+
@mysqldump_utility ||= utility(:mysqldump)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Performs the mysqldump command and outputs the
|
|
57
|
+
# data to the specified path based on the 'trigger'
|
|
58
|
+
def perform!
|
|
59
|
+
super
|
|
60
|
+
|
|
61
|
+
pipeline = Pipeline.new
|
|
62
|
+
dump_ext = 'sql'
|
|
63
|
+
|
|
64
|
+
pipeline << mysqldump
|
|
65
|
+
if @model.compressor
|
|
66
|
+
@model.compressor.compress_with do |command, ext|
|
|
67
|
+
pipeline << command
|
|
68
|
+
dump_ext << ext
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
pipeline << "cat > '#{ File.join(@dump_path, dump_filename) }.#{ dump_ext }'"
|
|
72
|
+
|
|
73
|
+
pipeline.run
|
|
74
|
+
if pipeline.success?
|
|
75
|
+
Logger.message "#{ database_name } Complete!"
|
|
76
|
+
else
|
|
77
|
+
raise Errors::Database::PipelineError,
|
|
78
|
+
"#{ database_name } Dump Failed!\n" +
|
|
79
|
+
pipeline.error_messages
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
##
|
|
86
|
+
# Builds the full mysqldump string based on all attributes
|
|
87
|
+
def mysqldump
|
|
88
|
+
"#{ mysqldump_utility } #{ credential_options } #{ connectivity_options } " +
|
|
89
|
+
"#{ user_options } #{ db_name } #{ tables_to_dump } #{ tables_to_skip }"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Returns the filename to use for dumping the database(s)
|
|
94
|
+
def dump_filename
|
|
95
|
+
dump_all? ? 'all-databases' : name
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
##
|
|
99
|
+
# Builds the credentials MySQL syntax to authenticate the user
|
|
100
|
+
# to perform the database dumping process
|
|
101
|
+
def credential_options
|
|
102
|
+
%w[username password].map do |option|
|
|
103
|
+
next if send(option).to_s.empty?
|
|
104
|
+
"--#{option}='#{send(option)}'".gsub('--username', '--user')
|
|
105
|
+
end.compact.join(' ')
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Builds the MySQL connectivity options syntax to connect the user
|
|
110
|
+
# to perform the database dumping process
|
|
111
|
+
def connectivity_options
|
|
112
|
+
%w[host port socket].map do |option|
|
|
113
|
+
next if send(option).to_s.empty?
|
|
114
|
+
"--#{option}='#{send(option)}'"
|
|
115
|
+
end.compact.join(' ')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
##
|
|
119
|
+
# Builds a MySQL compatible string for the additional options
|
|
120
|
+
# specified by the user
|
|
121
|
+
def user_options
|
|
122
|
+
additional_options.join(' ')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# Returns the database name to use in the mysqldump command.
|
|
127
|
+
# When dumping all databases, the database name is replaced
|
|
128
|
+
# with the command option to dump all databases.
|
|
129
|
+
def db_name
|
|
130
|
+
dump_all? ? '--all-databases' : name
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# Builds the MySQL syntax for specifying which tables to dump
|
|
135
|
+
# during the dumping of the database
|
|
136
|
+
def tables_to_dump
|
|
137
|
+
only_tables.join(' ') unless dump_all?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
##
|
|
141
|
+
# Builds the MySQL syntax for specifying which tables to skip
|
|
142
|
+
# during the dumping of the database
|
|
143
|
+
def tables_to_skip
|
|
144
|
+
skip_tables.map do |table|
|
|
145
|
+
table = (dump_all? || table['.']) ? table : "#{ name }.#{ table }"
|
|
146
|
+
"--ignore-table='#{ table }'"
|
|
147
|
+
end.join(' ')
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
# Return true if we're dumping all databases.
|
|
152
|
+
# `name` will be set to :all if it is not set,
|
|
153
|
+
# so this will be true by default
|
|
154
|
+
def dump_all?
|
|
155
|
+
name == :all
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|