backupii 0.1.0.pre.alpha.1
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.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +37 -0
- data/bin/backupii +5 -0
- data/bin/docker_test +24 -0
- data/lib/backup/archive.rb +171 -0
- data/lib/backup/binder.rb +23 -0
- data/lib/backup/cleaner.rb +114 -0
- data/lib/backup/cli.rb +376 -0
- data/lib/backup/cloud_io/base.rb +40 -0
- data/lib/backup/cloud_io/cloud_files.rb +301 -0
- data/lib/backup/cloud_io/s3.rb +256 -0
- data/lib/backup/compressor/base.rb +34 -0
- data/lib/backup/compressor/bzip2.rb +37 -0
- data/lib/backup/compressor/custom.rb +51 -0
- data/lib/backup/compressor/gzip.rb +76 -0
- data/lib/backup/config/dsl.rb +103 -0
- data/lib/backup/config/helpers.rb +139 -0
- data/lib/backup/config.rb +122 -0
- data/lib/backup/database/base.rb +89 -0
- data/lib/backup/database/mongodb.rb +189 -0
- data/lib/backup/database/mysql.rb +194 -0
- data/lib/backup/database/openldap.rb +97 -0
- data/lib/backup/database/postgresql.rb +134 -0
- data/lib/backup/database/redis.rb +179 -0
- data/lib/backup/database/riak.rb +82 -0
- data/lib/backup/database/sqlite.rb +57 -0
- data/lib/backup/encryptor/base.rb +29 -0
- data/lib/backup/encryptor/gpg.rb +745 -0
- data/lib/backup/encryptor/open_ssl.rb +76 -0
- data/lib/backup/errors.rb +55 -0
- data/lib/backup/logger/console.rb +50 -0
- data/lib/backup/logger/fog_adapter.rb +27 -0
- data/lib/backup/logger/logfile.rb +134 -0
- data/lib/backup/logger/syslog.rb +116 -0
- data/lib/backup/logger.rb +199 -0
- data/lib/backup/model.rb +478 -0
- data/lib/backup/notifier/base.rb +128 -0
- data/lib/backup/notifier/campfire.rb +63 -0
- data/lib/backup/notifier/command.rb +101 -0
- data/lib/backup/notifier/datadog.rb +107 -0
- data/lib/backup/notifier/flowdock.rb +101 -0
- data/lib/backup/notifier/hipchat.rb +118 -0
- data/lib/backup/notifier/http_post.rb +116 -0
- data/lib/backup/notifier/mail.rb +235 -0
- data/lib/backup/notifier/nagios.rb +67 -0
- data/lib/backup/notifier/pagerduty.rb +82 -0
- data/lib/backup/notifier/prowl.rb +70 -0
- data/lib/backup/notifier/pushover.rb +73 -0
- data/lib/backup/notifier/ses.rb +126 -0
- data/lib/backup/notifier/slack.rb +149 -0
- data/lib/backup/notifier/twitter.rb +57 -0
- data/lib/backup/notifier/zabbix.rb +62 -0
- data/lib/backup/package.rb +53 -0
- data/lib/backup/packager.rb +108 -0
- data/lib/backup/pipeline.rb +122 -0
- data/lib/backup/splitter.rb +75 -0
- data/lib/backup/storage/base.rb +72 -0
- data/lib/backup/storage/cloud_files.rb +158 -0
- data/lib/backup/storage/cycler.rb +73 -0
- data/lib/backup/storage/dropbox.rb +208 -0
- data/lib/backup/storage/ftp.rb +118 -0
- data/lib/backup/storage/local.rb +63 -0
- data/lib/backup/storage/qiniu.rb +68 -0
- data/lib/backup/storage/rsync.rb +251 -0
- data/lib/backup/storage/s3.rb +157 -0
- data/lib/backup/storage/scp.rb +67 -0
- data/lib/backup/storage/sftp.rb +82 -0
- data/lib/backup/syncer/base.rb +70 -0
- data/lib/backup/syncer/cloud/base.rb +180 -0
- data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
- data/lib/backup/syncer/cloud/local_file.rb +99 -0
- data/lib/backup/syncer/cloud/s3.rb +118 -0
- data/lib/backup/syncer/rsync/base.rb +55 -0
- data/lib/backup/syncer/rsync/local.rb +29 -0
- data/lib/backup/syncer/rsync/pull.rb +49 -0
- data/lib/backup/syncer/rsync/push.rb +206 -0
- data/lib/backup/template.rb +45 -0
- data/lib/backup/utilities.rb +235 -0
- data/lib/backup/version.rb +5 -0
- data/lib/backup.rb +141 -0
- data/templates/cli/archive +28 -0
- data/templates/cli/compressor/bzip2 +4 -0
- data/templates/cli/compressor/custom +7 -0
- data/templates/cli/compressor/gzip +4 -0
- data/templates/cli/config +123 -0
- data/templates/cli/databases/mongodb +15 -0
- data/templates/cli/databases/mysql +18 -0
- data/templates/cli/databases/openldap +24 -0
- data/templates/cli/databases/postgresql +16 -0
- data/templates/cli/databases/redis +16 -0
- data/templates/cli/databases/riak +17 -0
- data/templates/cli/databases/sqlite +11 -0
- data/templates/cli/encryptor/gpg +27 -0
- data/templates/cli/encryptor/openssl +9 -0
- data/templates/cli/model +26 -0
- data/templates/cli/notifier/zabbix +15 -0
- data/templates/cli/notifiers/campfire +12 -0
- data/templates/cli/notifiers/command +32 -0
- data/templates/cli/notifiers/datadog +57 -0
- data/templates/cli/notifiers/flowdock +16 -0
- data/templates/cli/notifiers/hipchat +16 -0
- data/templates/cli/notifiers/http_post +32 -0
- data/templates/cli/notifiers/mail +24 -0
- data/templates/cli/notifiers/nagios +13 -0
- data/templates/cli/notifiers/pagerduty +12 -0
- data/templates/cli/notifiers/prowl +11 -0
- data/templates/cli/notifiers/pushover +11 -0
- data/templates/cli/notifiers/ses +15 -0
- data/templates/cli/notifiers/slack +22 -0
- data/templates/cli/notifiers/twitter +13 -0
- data/templates/cli/splitter +7 -0
- data/templates/cli/storages/cloud_files +11 -0
- data/templates/cli/storages/dropbox +20 -0
- data/templates/cli/storages/ftp +13 -0
- data/templates/cli/storages/local +8 -0
- data/templates/cli/storages/qiniu +12 -0
- data/templates/cli/storages/rsync +17 -0
- data/templates/cli/storages/s3 +16 -0
- data/templates/cli/storages/scp +15 -0
- data/templates/cli/storages/sftp +15 -0
- data/templates/cli/syncers/cloud_files +22 -0
- data/templates/cli/syncers/rsync_local +20 -0
- data/templates/cli/syncers/rsync_pull +28 -0
- data/templates/cli/syncers/rsync_push +28 -0
- data/templates/cli/syncers/s3 +27 -0
- data/templates/general/links +3 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +16 -0
- data/templates/notifier/mail/success.erb +16 -0
- data/templates/notifier/mail/warning.erb +16 -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 +507 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Database
|
5
|
+
class Redis < Base
|
6
|
+
class Error < Backup::Error; end
|
7
|
+
|
8
|
+
MODES = %i[copy sync].freeze
|
9
|
+
|
10
|
+
##
|
11
|
+
# Mode of operation.
|
12
|
+
#
|
13
|
+
# [:copy]
|
14
|
+
# Copies the redis dump file specified by {#rdb_path}.
|
15
|
+
# This data will be current as of the last RDB Snapshot
|
16
|
+
# performed by the server (per your redis.conf settings).
|
17
|
+
# You may set {#invoke_save} to +true+ to have Backup issue
|
18
|
+
# a +SAVE+ command to update the dump file with the current
|
19
|
+
# data before performing the copy.
|
20
|
+
#
|
21
|
+
# [:sync]
|
22
|
+
# Performs a dump of your redis data using +redis-cli --rdb -+.
|
23
|
+
# Redis implements this internally using a +SYNC+ command.
|
24
|
+
# The operation is analogous to requesting a +BGSAVE+, then having the
|
25
|
+
# dump returned. This mode is capable of dumping data from a local or
|
26
|
+
# remote server. Requires Redis v2.6 or better.
|
27
|
+
#
|
28
|
+
# Defaults to +:copy+.
|
29
|
+
attr_accessor :mode
|
30
|
+
|
31
|
+
##
|
32
|
+
# Full path to the redis dump file.
|
33
|
+
#
|
34
|
+
# Required when {#mode} is +:copy+.
|
35
|
+
attr_accessor :rdb_path
|
36
|
+
|
37
|
+
##
|
38
|
+
# Perform a +SAVE+ command using the +redis-cli+ utility
|
39
|
+
# before copying the dump file specified by {#rdb_path}.
|
40
|
+
#
|
41
|
+
# Only valid when {#mode} is +:copy+.
|
42
|
+
attr_accessor :invoke_save
|
43
|
+
|
44
|
+
##
|
45
|
+
# Connectivity options for the +redis-cli+ utility.
|
46
|
+
attr_accessor :host, :port, :socket
|
47
|
+
|
48
|
+
##
|
49
|
+
# Password for the +redis-cli+ utility.
|
50
|
+
attr_accessor :password
|
51
|
+
|
52
|
+
##
|
53
|
+
# Additional options for the +redis-cli+ utility.
|
54
|
+
attr_accessor :additional_options
|
55
|
+
|
56
|
+
def initialize(model, database_id = nil, &block)
|
57
|
+
super
|
58
|
+
instance_eval(&block) if block_given?
|
59
|
+
|
60
|
+
@mode ||= :copy
|
61
|
+
|
62
|
+
raise Error, "'#{mode}' is not a valid mode" unless MODES.include?(mode)
|
63
|
+
|
64
|
+
if mode == :copy && rdb_path.nil?
|
65
|
+
raise Error, "`rdb_path` must be set when `mode` is :copy"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Performs the dump based on {#mode} and stores the Redis dump file
|
71
|
+
# to the +dump_path+ using the +dump_filename+.
|
72
|
+
#
|
73
|
+
# <trigger>/databases/Redis[-<database_id>].rdb[.gz]
|
74
|
+
def perform!
|
75
|
+
super
|
76
|
+
|
77
|
+
case mode
|
78
|
+
when :sync
|
79
|
+
# messages output by `redis-cli --rdb` on $stderr
|
80
|
+
Logger.configure do
|
81
|
+
ignore_warning(%r{Transfer finished with success})
|
82
|
+
ignore_warning(%r{SYNC sent to master})
|
83
|
+
end
|
84
|
+
sync!
|
85
|
+
when :copy
|
86
|
+
save! if invoke_save
|
87
|
+
copy!
|
88
|
+
end
|
89
|
+
|
90
|
+
log!(:finished)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def sync!
|
96
|
+
pipeline = Pipeline.new
|
97
|
+
dump_ext = "rdb".dup
|
98
|
+
|
99
|
+
pipeline << "#{redis_cli_cmd} --rdb -"
|
100
|
+
|
101
|
+
if model.compressor
|
102
|
+
model.compressor.compress_with do |command, ext|
|
103
|
+
pipeline << command
|
104
|
+
dump_ext << ext
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
pipeline << "#{utility(:cat)} > " \
|
109
|
+
"'#{File.join(dump_path, dump_filename)}.#{dump_ext}'"
|
110
|
+
|
111
|
+
pipeline.run
|
112
|
+
|
113
|
+
unless pipeline.success?
|
114
|
+
raise Error, "Dump Failed!\n" + pipeline.error_messages
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def save!
|
119
|
+
resp = run("#{redis_cli_cmd} SAVE")
|
120
|
+
unless resp =~ %r{OK$}
|
121
|
+
raise Error, <<-EOS
|
122
|
+
Failed to invoke the `SAVE` command
|
123
|
+
Response was: #{resp}
|
124
|
+
EOS
|
125
|
+
end
|
126
|
+
rescue Error
|
127
|
+
if resp =~ %r{save already in progress}
|
128
|
+
unless (attempts ||= "0".dup).next! == "5"
|
129
|
+
sleep 5
|
130
|
+
retry
|
131
|
+
end
|
132
|
+
end
|
133
|
+
raise
|
134
|
+
end
|
135
|
+
|
136
|
+
def copy!
|
137
|
+
unless File.exist?(rdb_path)
|
138
|
+
raise Error, <<-EOS
|
139
|
+
Redis database dump not found
|
140
|
+
`rdb_path` was '#{rdb_path}'
|
141
|
+
EOS
|
142
|
+
end
|
143
|
+
|
144
|
+
dst_path = File.join(dump_path, dump_filename + ".rdb")
|
145
|
+
if model.compressor
|
146
|
+
model.compressor.compress_with do |command, ext|
|
147
|
+
run("#{command} -c '#{rdb_path}' > '#{dst_path + ext}'")
|
148
|
+
end
|
149
|
+
else
|
150
|
+
FileUtils.cp(rdb_path, dst_path)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def redis_cli_cmd
|
155
|
+
"#{utility("redis-cli")} #{password_option} " \
|
156
|
+
"#{connectivity_options} #{user_options}"
|
157
|
+
end
|
158
|
+
|
159
|
+
def password_option
|
160
|
+
return unless password
|
161
|
+
|
162
|
+
"-a '#{password}'"
|
163
|
+
end
|
164
|
+
|
165
|
+
def connectivity_options
|
166
|
+
return "-s '#{socket}'" if socket
|
167
|
+
|
168
|
+
opts = []
|
169
|
+
opts << "-h '#{host}'" if host
|
170
|
+
opts << "-p '#{port}'" if port
|
171
|
+
opts.join(" ")
|
172
|
+
end
|
173
|
+
|
174
|
+
def user_options
|
175
|
+
Array(additional_options).join(" ")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Database
|
5
|
+
class Riak < Base
|
6
|
+
##
|
7
|
+
# Node is the node from which to perform the backup.
|
8
|
+
# Default: riak@127.0.0.1
|
9
|
+
attr_accessor :node
|
10
|
+
|
11
|
+
##
|
12
|
+
# Cookie is the Erlang cookie/shared secret used to connect to the node.
|
13
|
+
# Default: riak
|
14
|
+
attr_accessor :cookie
|
15
|
+
|
16
|
+
##
|
17
|
+
# Username for the riak instance
|
18
|
+
# Default: riak
|
19
|
+
attr_accessor :user
|
20
|
+
|
21
|
+
def initialize(model, database_id = nil, &block)
|
22
|
+
super
|
23
|
+
instance_eval(&block) if block_given?
|
24
|
+
|
25
|
+
@node ||= "riak@127.0.0.1"
|
26
|
+
@cookie ||= "riak"
|
27
|
+
@user ||= "riak"
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Performs the dump using `riak-admin backup`.
|
32
|
+
#
|
33
|
+
# This will be stored in the final backup package as
|
34
|
+
# <trigger>/databases/<dump_filename>-<node>[.gz]
|
35
|
+
def perform!
|
36
|
+
super
|
37
|
+
|
38
|
+
dump_file = File.join(dump_path, dump_filename)
|
39
|
+
with_riak_owned_dump_path do
|
40
|
+
run("#{riakadmin} backup #{node} #{cookie} '#{dump_file}' node")
|
41
|
+
end
|
42
|
+
|
43
|
+
if model.compressor
|
44
|
+
model.compressor.compress_with do |command, ext|
|
45
|
+
# `riak-admin` appends `node` to the filename.
|
46
|
+
dump_file << "-#{node}"
|
47
|
+
run("#{command} -c '#{dump_file}' > '#{dump_file + ext}'")
|
48
|
+
FileUtils.rm_f(dump_file)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
log!(:finished)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
##
|
58
|
+
# The `riak-admin backup` command is run as the riak +user+,
|
59
|
+
# so +user+ must have write priviledges to the +dump_path+.
|
60
|
+
#
|
61
|
+
# Note that the riak +user+ must also have access to +dump_path+.
|
62
|
+
# This means Backup's +tmp_path+ can not be under the home directory of
|
63
|
+
# the user running Backup, since the absence of the execute bit on their
|
64
|
+
# home directory would deny +user+ access.
|
65
|
+
def with_riak_owned_dump_path
|
66
|
+
run "#{utility(:sudo)} -n #{utility(:chown)} #{user} '#{dump_path}'"
|
67
|
+
yield
|
68
|
+
ensure
|
69
|
+
# reclaim ownership
|
70
|
+
run "#{utility(:sudo)} -n #{utility(:chown)} -R " \
|
71
|
+
"#{Config.user} '#{dump_path}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# `riak-admin` must be run as the riak +user+.
|
76
|
+
# It will do this itself, but without `-n` and emits a message on STDERR.
|
77
|
+
def riakadmin
|
78
|
+
"#{utility(:sudo)} -n -u #{user} #{utility("riak-admin")}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Database
|
5
|
+
class SQLite < Base
|
6
|
+
class Error < Backup::Error; end
|
7
|
+
|
8
|
+
##
|
9
|
+
# Path to the sqlite3 file
|
10
|
+
attr_accessor :path
|
11
|
+
|
12
|
+
##
|
13
|
+
# Path to sqlite utility (optional)
|
14
|
+
attr_accessor :sqlitedump_utility
|
15
|
+
|
16
|
+
##
|
17
|
+
# Creates a new instance of the SQLite adapter object
|
18
|
+
def initialize(model, database_id = nil, &block)
|
19
|
+
super
|
20
|
+
instance_eval(&block) if block_given?
|
21
|
+
|
22
|
+
@sqlitedump_utility ||= utility(:sqlitedump)
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Performs the sqlitedump command and outputs the
|
27
|
+
# data to the specified path based on the 'trigger'
|
28
|
+
def perform!
|
29
|
+
super
|
30
|
+
|
31
|
+
dump = "echo '.dump' | #{sqlitedump_utility} #{path}"
|
32
|
+
|
33
|
+
pipeline = Pipeline.new
|
34
|
+
dump_ext = "sql".dup
|
35
|
+
|
36
|
+
pipeline << dump
|
37
|
+
if model.compressor
|
38
|
+
model.compressor.compress_with do |command, ext|
|
39
|
+
pipeline << command
|
40
|
+
dump_ext << ext
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
pipeline << "cat > '#{File.join(dump_path, dump_filename)}.#{dump_ext}'"
|
45
|
+
|
46
|
+
pipeline.run
|
47
|
+
|
48
|
+
if pipeline.success?
|
49
|
+
log!(:finished)
|
50
|
+
else
|
51
|
+
raise Error,
|
52
|
+
"#{database_name} Dump Failed!\n" + pipeline.error_messages
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Encryptor
|
5
|
+
class Base
|
6
|
+
include Utilities::Helpers
|
7
|
+
include Config::Helpers
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
load_defaults!
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
##
|
16
|
+
# Return the encryptor name, with Backup namespace removed
|
17
|
+
def encryptor_name
|
18
|
+
self.class.to_s.sub("Backup::", "")
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Logs a message to the console and log file to inform
|
23
|
+
# the client that Backup is encrypting the archive
|
24
|
+
def log!
|
25
|
+
Logger.info "Using #{encryptor_name} to encrypt the archive."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|